Worked example · 2024-12
@solana/web3.js npm supply-chain compromise — Solana — 2024-12-03
OAK Techniques observed:
- OAK-T11.002 (Wallet-Software Distribution Compromise — broad construction). The incident is an upstream-dependency compromise rather than a wallet-software compromise per se, but the structural shape — a malicious version of a load-bearing wallet-tooling library distributed through the legitimate package registry that downstream consumers update via standard package-management workflows — is the canonical T11.002 distribution-channel-compromise pattern. The library is a foundational SDK for Solana wallet and dApp development; the compromise sits one structural level upstream of the wallet-software-distribution layer that T11.002 directly addresses.
- OAK-T15.002 (Supply-Chain / Vendor-Pipeline Compromise) — the canonical npm-package sub-shape anchor for the shared-upstream-surface attack class. The malicious versions 1.95.6 and 1.95.7 propagated to every consumer that updated during the five-hour compromise window.
- OAK-T15.001 (Social Engineering of Operator Personnel) — the upstream entry vector was a spear-phishing pretext directed at an
@solananpm-organisation member with publish access; the pretext extracted both the npm credential and the 2FA code. - OAK-T15.004 (Operator-Side Credential Compromise) — the credentials extracted by the spear-phishing event were the npm-publisher credential surface; the case is also a canonical anchor for the publisher-credential sub-shape that produces shared-upstream-surface compromise without a corresponding endpoint-implant.
- OAK-G01 is NOT the attribution at v0.1 cutoff — public coverage attributes the spear-phishing-against-an-npm-org-member vector to commodity-cohort threat actors using standard credential-theft + 2FA-bypass tradecraft, not to DPRK / TraderTraitor. The case is structurally distinct from the broader 2023-2025 DPRK npm-package-supply-chain campaign (
Contagious Interview/Famous Chollimacohort) which uses attacker-published-malicious-packages as the substrate, not takeover-of-legitimate-package-publishing-credentials. The two cohorts converge on similar exploitation primitives but diverge on initial-access vector and operator attribution.
Summary
@solana/web3.js is the canonical Solana JavaScript / TypeScript SDK, used by wallet developers, dApp frontends, backend trading bots, and custodial-script environments to construct, sign, and submit Solana transactions. The library is published on the npm registry under the @solana org and at the time of the incident had approximately 500,000 weekly downloads and ~3,000 dependent packages.
On December 3, 2024, between approximately 15:20 UTC and 20:25 UTC, malicious versions 1.95.6 and 1.95.7 of @solana/web3.js were published to the npm registry. The malicious versions contained a backdoor function named addToQueue that exfiltrated private keys via crafted CloudFlare-style HTTP headers to an attacker-controlled endpoint. Calls to this function were strategically inserted at points in the library's code that legitimately access private-key material (transaction signing, key-derivation paths), allowing the backdoor to capture private keys from any runtime context where the library was used to sign transactions with locally-held private-key material.
The compromise vector — disclosed in Anza / Solana Foundation's post-mortem — was a spear-phishing attack against an @solana npm organisation member with publish access. The phishing email tricked the targeted maintainer into providing both their npm credentials and a 2FA code, allowing the attackers to publish the malicious versions to the registry under legitimate organisational credentials.
The malicious versions were detected by community researchers (initial reports surfaced through Socket and Wiz threat-intelligence feeds), reported to npm and Anza, and removed within ~5 hours of publication. The clean version 1.95.8 was published as the recommended-upgrade target. Anza, the Solana Foundation, and major Solana wallet vendors (Phantom, Solflare, Backpack) issued advisories confirming the impact scope and the upgrade path.
Wallet vendors confirmed they were largely unaffected:
- Phantom — confirmed its security team prevented impact through a combination of version-locking and code-review controls.
- Solflare — confirmed not affected; cited version-locking and rigorous code-review as protective controls.
- Backpack — confirmed not affected.
The realised loss landed on backend / bot operators who had private keys in the library's runtime context and who updated to the malicious version within the 5-hour window. Cumulative public-record extraction estimates are ~$190K-$200K; the actual full extraction may be higher but is not publicly tabulated.
Why this is structurally significant
The @solana/web3.js compromise sits at three structurally distinct intersections:
It is the canonical 2024 Solana-tooling-supply-chain incident. Pre-2024, Solana's tooling-supply-chain risk was primarily theoretical (in the sense that the SDK / tooling layer had not been the substrate for a publicly-confirmed extraction event — the 2022 Slope wallet incident was a wallet-vendor-side logging flaw, not an upstream-library compromise). The web3.js incident establishes that the Solana-tooling-supply-chain surface is now an active substrate for extraction events, and that the standard EVM-side defenses (Sigstore-style cryptographic attestation, npm 2FA enforcement, registry-side anomaly detection) are necessary but not sufficient when the attacker can defeat 2FA via spear-phishing.
It is the canonical 2024 example of a high-download-low-realised-loss compromise. The compromise affected a library with ~500K weekly downloads but produced ~$200K in realised loss. The structural reason — runtime-context-shape bounding the exfiltration surface — generalises beyond Solana and beyond JavaScript supply-chain risk. The class should inform defender-tooling priorities: not all upstream-library compromises produce loss proportional to the dependency graph; the runtime-context analysis is the load-bearing prediction. This is structurally distinct from cases where the runtime-context overlap is broader (e.g., the 2023-12 Ledger Connect Kit compromise, see
examples/2023-12-ledger-connect-kit.md, where the runtime context was browser-side wallet integration and the realised loss was ~$610K despite a much narrower window).It is a narrow-window-fast-rotation incident, structurally distinct from long-cycle DPRK supply-chain campaigns. The 5-hour live-malicious-version window, the lack of obfuscation in the
addToQueuefunction name (a commodity-loader naming pattern, not the careful operational-security of DPRK tradecraft), and the spear-phishing initial-access vector against an organisational-credential surface all converge on a commodity supply-chain-attacker fingerprint. Compared to the DPRKFamous Chollima/Contagious Interviewcohort that publishes attacker-controlled packages under fake-developer identities and operates them across months with careful obfuscation, the web3.js case is a different operator-tradecraft class. The OAK-G01 attribution does not apply at v0.1; future revisions may revisit if forensic surface evolves.
The case generalises beyond Solana to any chain whose tooling-SDK is published on a single shared package registry (npm, PyPI, Cargo, Maven). The structural shape — single-credential-takeover-of-a-load-bearing-package — is the canonical 2020-2025 supply-chain risk pattern, with the event-stream-2018 / ua-parser-js-2021 / colors-faker-2022 / xz-utils-2024 cases as the cross-ecosystem reference set. The web3.js case is the highest-magnitude publicly-confirmed Solana-side instance.
Timeline (UTC)
| When | Event | OAK ref |
|---|---|---|
| Pre-2024-12 | @solana/web3.js operates as standard Solana SDK with ~500K weekly downloads on npm; standard 2FA-protected publish workflow; library is a foundational dependency for Solana wallets, dApps, and backend infrastructure |
(genesis surface) |
| 2024-12-03 (early) | Spear-phishing email targets an @solana npm organisation member with publish access; the targeted maintainer provides both credentials and 2FA code |
Initial-access compromise (T11.002 broadly construed) |
| 2024-12-03 ~15:20 UTC | Malicious versions 1.95.6 and 1.95.7 of @solana/web3.js published to npm under legitimate organisational credentials; addToQueue backdoor exfiltrates private keys via crafted CloudFlare-style HTTP headers |
Malicious-version-live window starts |
| 2024-12-03 (live window) | Backend / bot operators who run automated npm update workflows or who update to the latest version within the window expose private keys via the library's runtime context; realised-loss-window concentrates here |
Extraction window |
| 2024-12-03 ~20:25 UTC | Community researchers (Socket, Wiz, others) detect the malicious versions and report to npm + Anza | (defender detection) |
| 2024-12-03 (immediate) | Malicious versions removed from npm; Anza / Solana Foundation publish initial advisory | (defender response — registry-layer) |
| 2024-12-03 → 2024-12-04 | Clean version 1.95.8 published; Phantom / Solflare / Backpack confirm unaffected status; ReversingLabs / Help Net Security / SecurityWeek / The Hacker News / Infosecurity / Decrypt / Mend / Wiz publish technical write-ups | (forensic surface) |
| 2024-12-04 onward | Cumulative realised loss estimated at ~$190K-$200K from public on-chain forensic tracing of the hardcoded exfiltration wallet address | (continuing forensic surface) |
| 2025 onward | npm publishes case-study coverage; the web3.js case becomes a standard reference in supply-chain-risk training and policy work | (long-cycle defender-tooling impact) |
What defenders observed
- Pre-event (publish-credential layer): the spear-phishing-against-an-npm-org-member vector was the load-bearing initial-access surface. The targeted maintainer was a legitimate
@solanaorg member with publish authority; the phishing email was crafted to extract both credentials and the 2FA code. Defender lesson: 2FA enforcement at the package-registry layer is necessary but not sufficient — a 2FA code provided to a phishing surface is functionally equivalent to no-2FA. The structurally-stronger control is hardware-token-bound 2FA (WebAuthn / FIDO2) which is phishing-resistant by design. - At-event (malicious-version-detection layer): the 5-hour live window was bounded by community-researcher detection. The signal — the introduction of a
addToQueuefunction that exfiltrates HTTP-header-encoded private-key material — is detectable at the static-analysis layer (any function that reads private-key material and emits HTTP requests is anomalous against the library's prior behavioural baseline). Defender lesson: package-registry-side anomaly detection (npm-side, GitHub-side, PyPI-side) is the canonical second-layer defense after publish-credential hardening. The Socket / Wiz / Snyk / GitHub Dependabot tooling cohort is the operational substrate; the web3.js case validates the value of the cohort at scale. - At-event (runtime-context-bounding layer): the realised loss was bounded by the runtime-context shape of the dependent applications. Wallet integrations (Phantom, Solflare, Backpack) hold private keys in browser-extension secure-context that does not pass keys through the library; their runtime-context overlap with the
addToQueueexfiltration target was zero, so they were structurally protected. Backend / bot operators whose private keys passed through the library's signing path were the realised-loss cohort. Defender lesson: dependency-graph metrics (download count, dependent-package count) are not a load-bearing predictor of realised loss for upstream-library compromises; runtime-context overlap is. - Post-event (advisory-and-rotation layer): the response from Anza, Solana Foundation, and major wallet vendors was structurally exemplary — initial advisory within hours, clean version published within hours, vendor-side impact statements within a day. The structural distinction from the 2023-12 Ledger Connect Kit incident (
examples/2023-12-ledger-connect-kit.md) is that the web3.js incident's runtime-context bounding kept the realised loss low, while Connect Kit's broader runtime-context produced higher per-window realised loss. Defender lesson: post-incident communications quality is structurally similar across the two cases; the realised-loss difference is a property of the runtime-context shape, not of the response quality. - Post-event (cohort-positioning layer): the case is structurally distinct from the DPRK
Famous Chollima/Contagious Interviewlong-cycle npm-package-supply-chain cohort. The DPRK cohort publishes attacker-controlled packages under fake-developer identities and operates them across months; the web3.js case is a credential-takeover of a legitimate package, executed within a 5-hour window. Defender lesson: supply-chain-attacker cohort segmentation matters for tooling-investment prioritisation — credential-takeover defenses (phishing-resistant 2FA, anomalous-publish detection) are the load-bearing class for the web3.js-style case; fake-developer-identity defenses (CV / interview-vetting, social-graph cross-checks) are the load-bearing class for the DPRK-style case.
What this example tells contributors writing future Technique pages
- T11.002 (Wallet-Software Distribution Compromise) covers upstream-library compromises in broad construction. Future T11.002 examples should preserve the substrate distinction: wallet-binary compromise (Slope 2022, Atomic Wallet 2023), wallet-frontend compromise (Connect Kit 2023, Curve frontend cases), and upstream-library compromise (web3.js 2024) are three structurally distinct sub-surfaces within the broader T11.002 class. The web3.js case is the canonical 2024 Solana-side worked example for the upstream-library sub-surface.
- Runtime-context bounding is the load-bearing predictor for upstream-library realised loss. Future supply-chain-compromise examples should explicitly characterise the runtime-context shape of the affected dependents and explain how the runtime-context overlap with the malicious payload's exfiltration target bounded the realised-loss window. Dependency-graph metrics alone are insufficient.
- Phishing-resistant 2FA (WebAuthn / FIDO2) is the canonical upstream-library hardening control. Future T11.002 examples involving credential-takeover should record whether the targeted publish credential was hardware-token-bound and treat that as a first-class defender-side observable.
- Cohort segmentation (commodity vs. DPRK) matters for tooling-investment framing. Future supply-chain-cohort analysis should not conflate the web3.js-style commodity credential-takeover cohort with the DPRK long-cycle fake-developer cohort. The two cohorts converge on the package-registry substrate but diverge on operator-tradecraft and defender-investment priorities.
- The 5-hour live-malicious-version window is a structural floor, not a ceiling. Faster live-window detection improves defender outcomes proportionally. Future supply-chain-incident examples should record the live-window duration as a first-class metric and treat live-window reduction as a defender-tooling-investment objective.
Public references
[wizweb3jssolana2024](proposed) — Wiz, "Solana web3.js Supply Chain Attack" incident page: https://threats.wiz.io/all-incidents/solana-web3js-supply-chain-attack[socketweb3jssolana2024](proposed) — Socket, "Supply Chain Attack Detected in Solana's web3.js Library": https://socket.dev/blog/supply-chain-attack-solana-web3-js-library[mendweb3jssolana2024](proposed) — Mend, "Solana npm Attack: How @solana/web3.js Was Compromised": https://www.mend.io/blog/the-solana-web3-js-incident-another-wake-up-call-for-supply-chain-security/[helpnetweb3jssolana2024](proposed) — Help Net Security, "Solana's popular web3.js library backdoored in supply chain compromise": https://www.helpnetsecurity.com/2024/12/04/solana-web3-js-supply-chain-compromise/[hackernewsweb3jssolana2024](proposed) — The Hacker News, "Researchers Uncover Backdoor in Solana's Popular Web3.js npm Library": https://thehackernews.com/2024/12/researchers-uncover-backdoor-in-solanas.html[reversinglabsweb3jssolana2024](proposed) — ReversingLabs, "Malware found in Solana npm library raises the bar for crypto security": https://www.reversinglabs.com/blog/malware-found-in-solana-npm-library-with-50m-downloads[securityweekweb3jssolana2024](proposed) — SecurityWeek, "Solana Web3.js Library Backdoored in Supply Chain Attack": https://www.securityweek.com/solana-web3-js-library-backdoored-in-supply-chain-attack/[infosecweb3jssolana2024](proposed) — Infosecurity Magazine, "Solana Library Supply Chain Attack Exposes Cryptocurrency Wallets": https://www.infosecurity-magazine.com/news/solana-library-supply-chain-attack/[decryptweb3jssolana2024](proposed) — Decrypt, "Solana Web3.js Library Compromised in Targeted Supply Chain Attack": https://decrypt.co/294742/solana-web3-js-library-compromised-in-targeted-supply-chain-attack[coinspeakerphantomweb3js2024](proposed) — Coinspeaker, "Phantom Assures Users of Wallet Security after Solana Library Vulnerability": https://www.coinspeaker.com/phantom-assures-users-wallet-security-solana-library-vulnerability/
Discussion
The @solana/web3.js December 2024 compromise is OAK's canonical 2024 Solana-tooling-supply-chain worked example. The case extends the T11.002 worked-example surface from wallet-binary compromise (Slope 2022 — see examples/2022-08-slope-phantom.md, Atomic Wallet 2023 — see examples/2023-06-atomic-wallet.md) and wallet-frontend compromise (Ledger Connect Kit 2023 — see examples/2023-12-ledger-connect-kit.md) into the upstream-library compromise sub-surface. The structural distinction within T11.002 is the load-bearing layer of the compromise: binary, frontend, library — each with structurally different runtime-context shapes and structurally different realised-loss profiles.
The structural distinguishing feature of the web3.js case — the runtime-context bounding that produced a ~$200K realised loss against a ~500K-weekly-download surface — generalises beyond Solana. The class is a recurring 2020-2025 supply-chain pattern (event-stream 2018 → ua-parser-js 2021 → colors-faker 2022 → xz-utils 2024 → web3.js 2024). Each case has its own runtime-context shape; the realised-loss profile follows the runtime-context analysis, not the dependency-graph analysis. OAK's T11.002 contributors should preserve this framing for future examples: dependency-graph metrics describe attack surface; runtime-context overlap describes realised loss.
The case's narrow attribution surface — pseudonymous, structurally distinct from DPRK / OAK-G01 — is structurally informative for the broader OAK-G01 attribution framework. The DPRK supply-chain-cohort (Lazarus / Famous Chollima / Contagious Interview) operates at different operational tempo (months not hours), uses different tradecraft (fake-developer identities not credential-takeover), and targets different recruitment surfaces (CV / interview / contractor onboarding not legitimate-org-member phishing). The web3.js case is structurally orthogonal to the DPRK cohort and should be treated as a separate operator-tradecraft class within OAK's supply-chain coverage. Future revisions may revisit this attribution if forensic surface evolves; at v0.1 cutoff the pseudonymous-commodity-cohort framing is the load-bearing public-record interpretation.
For OAK's broader cohort coverage, the web3.js case + the Slope wallet incident (examples/2022-08-slope-phantom.md) + the Solana Drainer cohort (commodity drainer kit derived from MS Drainer per Cyble 2024 forensic analysis) collectively establish that Solana wallet / tooling supply-chain compromises operate across multiple structurally-distinct sub-surfaces — wallet-vendor-logging-flaws (Slope), upstream-library-credential-takeover (web3.js), and commodity-drainer-kit infrastructure (post-MS-Drainer Solana fork). Each sub-surface has its own defender-tooling alignment; OAK's T11.002 v0.x development should preserve this taxonomy.