
Browser-Based Crypto-Stealer in NPM Supply Chain Attack – Advisory By SISA Sappers
Executive Summary
On September 8, 2025, the Node Package Manager (NPM) ecosystem was subjected to a massive supply chain attack impacting 18 popular JavaScript packages, which collectively account for over 2.6 billion weekly downloads. The incident was initiated through a sophisticated phishing campaign that compromised a high-profile package maintainer’s account. The attacker then injected malicious code—a crypto-draining malware—into new versions of these packages. The malware was designed to hijack cryptocurrency transactions within web browsers by intercepting and modifying wallet interactions for multiple blockchains, including Ethereum, Solana, and Bitcoin. The malicious packages were live on the NPM registry for approximately two hours before being detected and removed by the security community and NPM staff. This attack underscores the critical vulnerabilities of transitive dependencies and the single-point-of-failure risk associated with maintainer account security in the open-source software supply chain.

Packages Compromised
The following packages and versions were identified as compromised:
- backslash@0.2.1
- chalk@5.6.1
- chalk-template@1.1.1
- color-convert@3.1.1
- color-name@2.0.1
- color-string@2.1.1
- wrap-ansi@9.0.1
- supports-hyperlinks@4.1.1
- strip-ansi@7.1.1
- slice-ansi@7.1.1
- simple-swizzle@0.2.3
- is-arrayish@0.3.3
- error-ex@1.3.3
- has-ansi@6.0.1
- ansi-regex@6.2.1
- ansi-styles@6.2.2
- supports-color@10.2.1
- proto-tinker-wc@1.8.7
- debug@4.4.2
Timeline of Attack
- 13:16 UTC : Attacker begins publishing malicious versions of the 18 packages to the NPM registry.
- 13:21 UTC : Automated security systems at Aikido Security detect anomalous and obfuscated code in the newly published packages.
- 14:16 UTC : Public disclosures and community alerts begin to circulate.
- 15:20 UTC : The GitHub community independently identifies and reports the suspicious code.
- 17:20 UTC : NPM publicly acknowledges the breach and confirms they are working on removing the malicious packages.
- 19:59 UTC: NPM confirms to the maintainer that all impacted package versions have been removed from the registry
Attack Flow
The attack was executed in two primary stages: initial access through social engineering and the subsequent supply chain injection.
- Initial Access (Phishing): The attack began when a prolific package maintainer, Josh Junon (GitHub: qix), received a highly convincing phishing email impersonating NPM support. The email, sent from support@npmjs[.]help (a typosquatted domain of the legitimate support@npmjs.com), created a sense of urgency by claiming a mandatory 2FA update was required to avoid account lockout. The maintainer was directed to a credential-harvesting site hosted on a CDN.
- Credential & 2FA Capture: The phishing site captured the maintainer’s username, password, and time-sensitive 2FA code. This data was immediately exfiltrated to an attacker-controlled WebSocket (websocket-api2.publicvm[.]com).
- Account Takeover: Using the captured credentials, the attacker gained unauthorized access to the maintainer’s NPM and GitHub accounts.
- Malicious Code Injection: The attacker injected obfuscated, malicious code into the js files of the 18 popular packages controlled by the compromised account.
- Publishing Compromised Packages: The attacker published new, trojanized versions of these packages to the official NPM registry.
- Propagation: Developers and automated build systems worldwide began pulling these compromised packages into their projects as dependencies, unknowingly embedding the crypto-draining malware into their applications.
- Execution (Transaction Hijack): When an end-user interacted with an application built with a compromised package, the malware activated in their browser. It hooked into core browser functions (fetch, XMLHttpRequest) and crypto wallet APIs (ethereum) to intercept and alter outgoing cryptocurrency transactions, redirecting funds to attacker-controlled wallets just before the user’s final approval.
Technical Details
Initial Access
The attacker employed a classic phishing strategy using domain spoofing (typosquatting) and a credential harvesting website. The site’s content was delivered via the Bunny CDN service, using specific buckets to host the malicious infrastructure.
Attack Execution and Malware Functionality
The attack involved a browser-resident crypto-stealer embedded as a single obfuscated line of JavaScript appended to index.js in compromised npm packages. This ensured execution only in the end-user’s browser, leaving developer machines and servers unaffected—bypassing tools like EDR or vulnerability scanners. Multiple obfuscation layers concealed global objects (stealthProxyControl) and functions (runmask, newdlocal, checkethereumw) that managed core logic.
Dual-Mode Logic
The malware operated in two modes, determined by the presence of a Web3 wallet:
- Passive Address Swapping (No Wallet Detected):
- Hooked browser APIs (fetch, XMLHttpRequest) to inspect JSON responses.
- Replaced detected crypto addresses (BTC, ETH, SOL, TRX, LTC, BCH) with attacker-controlled ones.
- Used the Levenshtein distance algorithm to select visually similar addresses from a pool of 280 attacker wallets, making swaps hard to detect.
- Active Transaction Hijacking (Wallet Detected):
- Detected window.ethereum (e.g., MetaMask) and hooked wallet APIs (eth_sendTransaction).
- Intercepted and altered transaction parameters in memory, redirecting funds to the attacker’s Ethereum wallet 0xFc4a4858bafef54D1b1d7697bfb5c52F4c166976.
- Modified calls to ERC-20 functions via their 4-byte selectors:
- approve (0x095ea7b3), permit (0xd505accf), transfer (0xa9059cbb), transferFrom (0x23b872dd).
- This allowed not only theft of funds but also creation of unlimited token approvals for later draining.
Technical Mechanics
- Network Interception: Wrapped fetch and XMLHttpRequest to clone/modify JSON responses and inject attacker addresses.
- Wallet API Hooking: runmask() overwrote wallet methods (request, send, sendAsync) with wrappers that manipulated transaction data before relaying them.
- Solana Handling: Attempted manipulation of Solana transactions by overwriting pubkey, recipient, and destination with 19111111111111111111111111111111, but this caused failures instead of theft—indicating incomplete or experimental code.
Key Characteristics
- Client-side only: No persistence or server compromise.
- Stealth-focused: Limited aggressive behavior to high-value targets with active wallets.
- Operational sophistication: Careful OPSEC choices, structured code, and address similarity algorithms revealed a calculated, financially motivated adversary.
Impact Assessment
- Scope: The attack affected 18 packages with a combined 2.6 billion weekly downloads, making it one of the largest NPM supply chain incidents by reach.
- Target: The primary goal was financial theft through the draining of cryptocurrency from end-users of applications that included the compromised packages.
- Direct Impact: Any developer who updated to or installed the compromised package versions during the ~2-hour window incorporated the malware into their application builds.
- Indirect Impact: Arkham intelligence, which actively tracked the attacker’s known wallets, reported a total of approximately $1000 in stolen funds.

Image courtesy: Arkham intelligence
Arkham Intelligence aggregates and displays the total value of tokens held by an attacker across all linked addresses and blockchains. This provides a unified view of the attacker’s cross-chain asset holdings in real time.
Recommendations for Prevention
- Strengthen Maintainer Account Security:
- Enforce phishing-resistant Multi-Factor Authentication (MFA) (e.g., hardware security keys) for all maintainers on NPM and GitHub.
- Monitor account activity for anomalous login patterns (e.g., unusual geolocation, device fingerprints).
- Implement Package Signing and Verification:
- Adopt cryptographic signing for all packages (e.g., via Sigstore) to ensure package integrity and verify the author’s identity.
- Configure package managers to verify signatures upon installation and fail the build if a signature is invalid or missing.
- Harden the Publishing Process:
- Require multi-maintainer approval (multi-signature) for publishing new versions of critical packages.
- Enforce mandatory automated code scanning and manual code reviews for changes, especially those introducing obfuscation or network functionality.
- Secure Development Pipelines:
- Pin dependencies to exact, vetted versions using lockfiles. Avoid using loose version ranges (^ or ~).
- Use reproducible builds to ensure the same source code always produces the same build artifact.
- Maintain a private or proxied NPM registry for critical dependencies to control which versions are accessible.
Indicators of Compromise (IOCs)
- Phishing Email Sender: support@npmjs[.]help
- IP Address: 7.81.108 (Phishing Website)
- Malicious Domains / Buckets:
- static-mw-host.b-cdn[.]net
- img-data-backup.b-cdn[.]net
- Data Exfiltration Endpoint: websocket-api2.publicvm[.]com
- Code Identifiers:
- Obfuscated string: _0x112fa8
- Suspicious function names: checkethereumw, stealthProxyControl, runmask
- Attacker Ethereum Address (for approve hijack):
- 0xFc4a4858bafef54D1b1d7697bfb5c52F4c166976
Click here for IOC List: Suspicious Wallet Addresses
Untapped Attack Vectors
1. Weaponizing Wallets for Systemic DeFi Exploitation
The deployed malware was designed to steal funds from individual transactions. A more devastating, blockchain-native approach would have aimed to cause systemic failure in Decentralized Finance (DeFi) protocols, leading to far greater financial losses.
- Mass “Ice Phishing” for Unlimited Approvals: Instead of just hijacking an in-progress transaction, the malware could have implemented a more advanced “ice phishing” campaign. It could have prompted users with a deceptive but seemingly benign request, such as “Verify wallet to continue,” which, when signed, would grant the attacker’s smart contract unlimited, permanent spending approval
(approve or setApprovalForAll) for the user’s most valuable tokens (e.g., WETH, USDC, USDT). This would transform the malware into a “wallet drainer,” allowing the attacker to empty the entire contents of victims’ wallets at a later time.
A highly sophisticated attacker would recognize that the most valuable target is not the end-user, but the developer’s machine itself. By shifting the payload’s focus from a client-side clipper to a server-side credential harvester, the attacker could have gained direct control over a blockchain protocol’s core infrastructure.
- Targeting Developer Private Keys: Many blockchain developers store high-value private keys locally for deploying and testing smart contracts on both testnets and mainnets. A payload designed as an information stealer could have systematically scanned the developer’s machine for these keys, searching for .env files, wallet storage directories, or plaintext seed phrases.
2.Targeted dApp Hijacking for Irreversible Damage
A truly sophisticated web3 threat actor would recognize that the ultimate impact isn’t just theft, but the erosion of trust in decentralized systems. Instead of a generic crypto-stealer, a more potent payload would have acted as a targeted weapon against specific, high-value Decentralized Applications (dApps).
- Context-Aware Payload Activation: The malware could have remained dormant until it detected it was running on the front-end of a major DeFi protocol, NFT marketplace, or cross-chain bridge. By checking the location.hostname, the malware could have activated a specific attack tailored to that dApp.
- Malicious Contract Redirection: Upon identifying a target like a major decentralized exchange, the malware would not just swap a recipient address. It would have insidiously replaced the protocol’s legitimate smart contract address in the front-end’s API calls with the address of a malicious, attacker-deployed contract. To the user, the interface would look identical, but all interactions would be routed through the attacker’s code.
- Irreversible Asset Destruction and Lockup: The goal of this malicious contract would be maximum, permanent damage rather than simple theft.
- NFT Burning: On an NFT marketplace, the malware could have tricked users into signing a transfer transaction that sends their high-value NFTs to the null address (0x00…), permanently destroying them.
- Permanent Fund Locking: For a lending protocol, the malicious contract could have been a “honeypot” with no withdrawal function. Users attempting to deposit collateral would have their funds permanently and irretrievably locked in the attacker’s contract.
Additional Info:
Validation, Containment, Eradication, and Recovery of Affected Packages
Validation & Identification: Is My Environment Affected?
- Check Lockfiles: The most reliable method is to check your project’s lockfiles (package-lock.json, lock, pnpm-lock.yaml) for any of the compromised package versions listed above. Since many of these are transitive dependencies, they may not appear in your package.json.
- Scan Source Code: Use command-line tools to search your node_modules directory for unique identifiers from the malicious code.
Bash
# Search for the unique obfuscated string identifier
grep -r “_0x112fa8” ./node_modules
- Use Security Scanners: Run tools like npm audit, Snyk, or other Software Composition Analysis (SCA) tools, which have been updated to flag these specific malicious versions.
Containment, Eradication, and Recovery Steps for affected packages
If a compromised package is found, follow these steps immediately:
- Containment:
- Isolate Affected Systems: Take any affected build servers, CI/CD runners, or developer machines offline to prevent further propagation.
- Rotate Credentials: Immediately rotate all secrets, API keys, tokens, and passwords present on affected machines, as the malware’s full capabilities may not be known.
- Eradication:
- Pin to a Safe Version: In your json, explicitly set the version of the affected dependency (and its parent dependencies) to a known-good version before the attack.
- Clear Caches: Completely clear all local and remote caches to prevent the compromised package from being re-fetched.
Bash
npm cache clean –force
3. Delete node_modules and Lockfiles: Remove the entire node_modules directory and the existing lockfile (package-lock.json or lock).
Bash
rm -rf node_modules package-lock.json
- Recovery:
- Perform a Clean Install: Run npm install (or yarn install) to generate a new, clean lockfile and node_modules directory based on the safe versions pinned in your json.
- Rebuild and Redeploy: Rebuild your application from this known-good state and redeploy it to all environments.
- Purge CDNs: If your application is served via a CDN, purge its cache to ensure end-users receive the clean version of the code.
Detection: Actionable Insights for Future Prevention
To detect similar attacks in the future, organizations should implement a multi-layered strategy:
- Pre-Publish/Pre-Install Scanning:
- Integrate automated static and dynamic analysis tools into your CI/CD pipeline. Configure them to scan for:
- High-Entropy Strings / Obfuscation: Flag packages with heavily obfuscated code, a common sign of malware.
- Network Calls: Alert on packages that make unexpected network connections, especially during installation (via lifecycle scripts).
- File System Access: Monitor for scripts that read sensitive files (e.g., SSH keys, environment variables).
- Behavioral Anomaly Detection:
- At runtime, monitor applications for anomalous behavior, such as attempts to hook into ethereum or proxy fetch and XMLHttpRequest.
- Implement Content Security Policies (CSP) to restrict where scripts can be loaded from and what network requests they can make.
- Integrate automated static and dynamic analysis tools into your CI/CD pipeline. Configure them to scan for:
- Dependency Monitoring:
- Use tools that monitor for changes in package metadata, such as a change in the package maintainer or a sudden, unexplained major version jump.
- Implement a “cooldown” period for new package releases, where new versions are held in a quarantined environment for a set time (e.g., 24-72 hours) before being used in production, allowing time for community detection of malicious activity.
- Threat Intelligence Integration:
- Subscribe to threat intelligence feeds specific to open-source ecosystems to receive real-time alerts about newly discovered vulnerabilities and compromised packages.
References
https://vercel.com/blog/critical-npm-supply-chain-attack-response-september-8-2025
https://thehackernews.com/2025/09/20-popular-npm-packages-with-2-billion.html
https://www.mend.io/blog/npm-supply-chain-attack-infiltrates-popular-packages/
https://snyk.io/blog/npm-supply-chain-attack-via-open-source-maintainer-compromise/
https://intel.arkm.com/explorer/entity/bb347405-06a1-4268-a901-4b4e17d93bfa
https://www.mexc.com/en-GB/news/largest-npm-attack-in-crypto-history-stole-less-than-50-seal/89759
https://www.ainvest.com/news/phishing-attack-hijacked-2-billion-npm-downloads-steal-crypto-2509/