Skip to main content

On September 8, 2025, the npm ecosystem faced its most damaging supply chain attack to date. With one phishing email, an NPM Package Compromised gave attackers access to 18 high-profile JavaScript libraries maintained by Josh Junon (npm username: qix). Together, these packages account for over 2.6 billion weekly downloads.

The compromise wasn’t the result of zero-day exploits or advanced malware implants. It was a straightforward phishing campaign that tricked a maintainer into handing over credentials and 2FA codes. From there, attackers slipped crypto-stealing code into packages used across thousands of projects.

This post breaks down what happened, how the attack worked, which packages were affected, what the malware did, and most importantly, what the community can learn from it.

How the Phishing Attack Worked

It started with an email that looked ordinary enough. On September 4, 2025, attackers registered npmjs.help, a domain crafted to mimic npm’s official npmjs.com, and began sending messages disguised as support notices.

The email used classic phishing tactics:

  • Urgency: claimed a “mandatory 2FA update” was required within 48 hours.
  • Fear: warned that accounts would be locked starting September 10.
  • Impersonation: copied npm’s branding and even included a fake verification checkmark.

npm package compromised

“The phishing email that compromised the maintainer account. Notice the spoofed domain, the urgency tactic, and the malicious link to a fake login page.”

Maintainer Josh Junon received one of these messages on his phone. On a small screen, the difference between npmjs.help and npmjs.com was almost invisible. He tapped the link, landed on what looked like the npm login page, and entered his username, password, and TOTP code.

Why it Worked

  • npm accounts don’t yet enforce phishing-resistant 2FA like WebAuthn.
  • Phone usage increases risk: small screens, autofill quirks, and multitasking make malicious pages harder to spot.
  • The ecosystem still relies heavily on single maintainers, leaving no safety net when one person is compromised.

The Packages that Were Hit

These weren’t fringe utilities. The attackers gained control of libraries like chalk, debug, and ansi-styles, which are buried deep in the dependency trees of frameworks and CLI tools.

Package NameWeekly Downloads (M)Use CaseCompromised Version(s)
ansi-styles371.41Terminal styling codes6.2.2
debug357.6Debugging utility4.4.2
chalk299.99CLI string styling5.6.1
supports-color287.1Terminal color detection9.5.1
strip-ansi261.17Removes ANSI codes7.2.1
ansi-regex243.64Regex for ANSI sequences6.1.1
wrap-ansi197.99Text wrapping8.1.1, 9.0.1
color-convert193.5Color conversions2.1.1
color-name191.71Color lookups1.2.1
is-arrayish73.8Checks for array-like objects0.4.1
slice-ansi59.8Slices styled strings5.1.1
error-ex47.17Enhanced error handling1.4.1
color-string27.48Parses color strings1.10.2
simple-swizzle26.26Argument handling0.2.3
has-ansi12.1Checks for ANSI codes3.1.1
supports-hyperlinks19.2Terminal hyperlink detection3.1.1
chalk-template3.9Template literals for chalk0.5.1
backslash0.26Escape handling0.1.1

Total weekly downloads: ~2.6 billion.

Because many of these are dependencies of dependencies, any project running npm install during the compromise window could have pulled the malicious code without realizing it.

Inside the Malicious Code

The payload wasn’t designed for server-side takeovers. Instead, it was a crypto clipper targeting browser contexts where web3 wallets are active.

How it Operated

  • API hooking: It intercepted functions like fetch, XMLHttpRequest, and wallet APIs (window.ethereum, window.solana).
  • Address swapping: Detected cryptocurrency addresses, then swapped them with attacker-controlled ones using Levenshtein distance to keep them visually similar.
  • Chains targeted: Ethereum, Bitcoin, Solana, Tron, Litecoin, Bitcoin Cash.
  • Obfuscation: String encoding, variable renaming, and dead code to evade scanners.

Why it Wasn’t Worse

Security researchers called it a missed opportunity for the attackers. Instead of installing backdoors or exfiltrating secrets, they narrowed in on crypto transactions. Actual stolen funds amounted to under $50, mostly in minor tokens.

Timeline of the NPM Package Compromised Incident

  • Sept 4: Phishing domain registered.
  • Sept 8 (morning): Emails sent. Junon’s account compromised.
  • Sept 8 (9–11:30 AM ET): Malicious versions published.
  • Sept 8 (afternoon): Maintainer and researchers detect the issue. Mackenzie Jackson posts a public alert. Socket and Aikido flag packages.
  • Sept 8 (evening): npm begins removing compromised versions. GitHub advisories released (initially overbroad).
  • Sept 9: Most packages yanked. npm audit signatures updated.

The window of exposure lasted only a few hours, but that was enough to potentially affect millions of installs.

The Real Impact

  • Financial loss: ~$50 in ETH and memecoins.
  • Potential exposure: Any fresh install or update during the window.
  • Community fallout: Renewed scrutiny of npm security, single-maintainer risks, and dependency sprawl.

What Developers Should Do Now

Detect and clean up

  • Scan repos for malware signatures, e.g.:
    rg -u –max-columns=80 _0x112fa8
  • Run npm audit (updated with new advisories).
  • Check package-lock.json for affected versions.

Mitigation

  • Pin known safe versions:
    “overrides”: {

  “chalk”: “5.3.0”,

  “debug”: “4.3.4”,

  “strip-ansi”: “7.1.0”

}

  • Avoid blind auto-updates from bots without review.

Prevention

  • Use phishing-resistant 2FA (hardware keys, WebAuthn).
  • Never log in through email links—type the domain directly.
  • Audit dependency chains and reduce reliance on micro-packages where possible.

What the Ecosystem Must Address

This incident reignited calls for npm and similar registries to adopt:

  • Code signing for all published packages.
  • Human review of updates to libraries with >1M downloads.
  • Provenance statements to track builds.
  • Shared maintainer ownership for critical packages.

The npm compromise showed how one phished login can ripple across billions of downloads. The attackers walked away with almost nothing, but the incident exposed just how fragile the software supply chain really is.

This isn’t about one maintainer or one registry. It’s about the reality that dependencies you didn’t even know you had can become liabilities overnight. The difference between chaos and control comes down to how quickly you can see, validate, and respond to exposures.

That’s why continuous exposure management matters. It catches the fallout before it spreads, turning billion-download breaches into contained incidents.

Want to see how continuous exposure management can safeguard your software supply chain? Book a free demo with Strobes today

Shubham Jha

Shubham is a Senior Content Marketing Specialist who trades in ones and zeros for words and wit. With a solid track record, he combines technical proficiency with creative flair. Currently focused on cybersecurity, he excels at turning complex security concepts into clear, engaging narratives. His passion for technology and storytelling makes him adept at bringing intricate data to life.

Close Menu