On September 8, 2025, the JavaScript ecosystem experienced what is now considered the largest supply chain attack in npm history. A sophisticated phishing campaign led to the compromise of a trusted maintainer’s account, resulting in the injection of cryptocurrency-stealing malware into 18+ foundational npm packages. These packages collectively accounted for over 2 billion weekly downloads, affecting millions of applications globally—from personal projects to enterprise-grade systems.

Figure 1: Josh Junon posts about the incident.

Following the discovery of the breach, the npm team began removing several of the malicious package versions published by the attackers, including the compromised debug package, which alone sees over 357 million downloads each week.

Initial Compromise: A Phishing Attack with Devastating Reach

The attack began when Josh Junon, a prolific open-source maintainer known as Qix-, received a phishing email impersonating npm support. The email, sent from [email protected] (a domain registered just three days earlier), warned that his account would be locked unless he updated his 2FA credentials within 48 hours.

Under pressure and during what he described as a “panicky morning,” Junon clicked the link and entered his credentials. This gave the attackers full access to his npm account. Within minutes, they began publishing malicious versions of his packages.

Figure 2: The phishing email.

Infrastructure

The threat actor opened a new domain – “npmjs.help” on September 5th, 3 days before the event occurred. At the time of writing, this domain is no longer accessible, but records show that it once resolved to 185.7.81.108.

This email contained a link to https://www.npmjs[.]help/settings/qix/tfa/manageTfa?action=setup-totp, which loaded content from two attacker-controlled BunnyCDN buckets: static-mw-host.b-cdn[.]net and img-data-backup.b-cdn[.]net.

One of the scripts loaded was the credential stealer, which can be found here. This is a simple script which stores the provided username, password, and 2FA code, and sends it to a remote host at websocket-api2.publicvm[.]com.

Figure 3: Whois record.

Reports from recipients of the phishing message indicate that the campaign also targeted other package maintainers and developers who shared the same email domain or address format.

Figure 4: Other maintainers received the phishing email as well.

Affected Packages

The compromised packages included some of the most widely used utilities in the JavaScript ecosystem:

  • backslash (0.26m downloads per week)
  • chalk-template (3.9m downloads per week)
  • supports-hyperlinks (19.2m downloads per week)
  • has-ansi (12.1m downloads per week)
  • simple-swizzle (26.26m downloads per week)
  • color-string (27.48m downloads per week)
  • error-ex (47.17m downloads per week)
  • color-name (191.71m downloads per week)
  • is-arrayish (73.8m downloads per week)
  • slice-ansi (59.8m downloads per week)
  • color-convert (193.5m downloads per week)
  • wrap-ansi (197.99m downloads per week)
  • ansi-regex (243.64m downloads per week)
  • supports-color (287.1m downloads per week)
  • strip-ansi (261.17m downloads per week)
  • chalk (299.99m downloads per week)
  • debug (357.6m downloads per week)
  • ansi-styles (371.41m downloads per week)

These packages are deeply embedded in thousands of other npm modules, creating a massive blast radius.

Malware Behaviour: A Sophisticated Crypto Heist

The injected malware was browser-specific and designed to steal cryptocurrency in two primary ways:

  1. Passive Address Replacement
  • The malware hooked browser functions like fetch, XMLHttpRequest, and window.ethereum.
  • It scanned for cryptocurrency wallet addresses in network traffic.
  • When detected, it replaced them with attacker-controlled addresses using visually similar strings to avoid detection.
  1. Active Transaction Hijacking
  • For users with browser wallets (e.g., MetaMask, Phantom), the malware intercepted transaction requests before signing.
  • It modified the destination address in real time, while still displaying the original address to the user.

A deep dive into the obfuscated malware injected into several popular NPM packages reveals a highly sophisticated browser-based attack targeting cryptocurrency transactions. The malicious code was engineered to intercept outgoing wallet transactions and covertly replace the destination address with one controlled by the attacker. This substitution is made deceptively subtle by using the Levenshtein distance algorithm to select attacker-controlled addresses that closely resemble the original, making manual detection difficult.

According to Charlie Eriksen from Aikido Security, the malware functions as a multi-layered interceptor. It hijacks both network traffic and application APIs, including window.fetch, XMLHttpRequest, and window.ethereum.request, as well as other wallet provider interfaces. This enables it to manipulate both the data being sent and the responses received, effectively rewriting transaction details in real time.

The payload begins by verifying it’s running in a browser environment (typeof window !== ‘undefined’) and then hooks into critical APIs. If a user visits a site that includes the compromised code and has a connected wallet (e.g., MetaMask or Phantom), the malware can intercept and alter transactions before they are signed. While developers aren’t the primary targets, they can still be affected if they connect wallets while testing or browsing affected sites.

Targeted Cryptocurrencies:
  • Bitcoin (Legacy & SegWit)
  • Ethereum
  • Tron
  • Litecoin
  • Bitcoin Cash
Timeline of Events
  • Sept 5: Attackers register npmjs.help domain.
  • Sept 8, 13:00 UTC: Phishing email sent to Junon.
  • 13:16 UTC: First malicious package published.
  • 13:21 UTC: Aikido Security detects anomaly.
  • 14:16 UTC: Public disclosure begins.
  • Evening: npm starts removing malicious versions.
  • Sept 9: Some packages (e.g., simple-swizzle) still compromised.
Detection & Response

Aikido Security detected the attack within 5 minutes of the first malicious package being published. Their systems flagged unusual behavior in build pipelines, including ReferenceError: fetch is not defined—a result of the malware trying to run in Node.js environments.

Vercel, a major platform affected by the attack, identified 76 projects using compromised packages and purged their build caches. They also issued guidance to affected customers and rebuilt clean versions of all impacted applications.

Recommendations

For developers & teams:

  • Use npm ci instead of npm install to enforce lockfile integrity.
  • Pin package versions using overrides in package.json.
  • Audit dependencies regularly with tools like npm audit, Snyk, or Socket.dev.
  • Review lockfile changes in pull requests.
  • Enable 2FA with hardware keys for all maintainer accounts.

For end users:

  • Verify all crypto transactions before signing.
  • Use hardware wallets for large holdings.
  • Monitor wallet activity for anomalies.
  • Update applications using affected packages.
Indicators of Compromise

Malicious URLs

http://npmjs.help/

https://uixie.npmjs.help/

https://npmjs.help/

http://[email protected]/

https://www.npmjs.help/

Domain

npmjs.help

IP

185.7.81.108

Email

[email protected]

You may also like