The Sept 2025 npm Supply Chain Attack: chalk, debug & Crypto Stealers

Short answer: on September 8, 2025, a phishing email to npmjs.help compromised maintainer ~qix and briefly poisoned popular packages such as chalk and debug — libraries with a combined ~2 billion weekly downloads. The payload was a browser crypto-stealer, not a Node ransomware bomb. Aikido flagged it; npm pulled the versions within hours; reported theft stayed under about $1,000. Here is the sourced timeline, what to check, and the only secret-sharing lesson that actually fits.
Related education: share passwords securely · API key handoffs vs vaults.
Key takeaways
Maintainer phishing
Account takeover via fake npm support beat package crypto — MFA and phishing-resistant auth matter more than another scanner alone.
Browser-scoped payload
Malware rewrote wallet destinations in the browser. Backend-only Node services were a different risk profile than crypto front-ends.
Fast community response
Detection → maintainer confirm → npm takedown compressed into an afternoon (Snyk timeline). Downloads ≠ confirmed victims.
Credential hygiene
Protect npm tokens and keys like secrets — never paste them into persistent chat. One-time links help handoffs; SCA still required.
What was compromised (sourced)
Primary write-ups from Aikido Security, Snyk, and Sonatype agree on the core facts: attackers gained publishing rights to the ~qix npm account and shipped malicious versions of utility packages including [email protected], [email protected], [email protected], [email protected], [email protected], and related ANSI/color helpers. Aikido reported the set at 18 packages with more than 2 billion combined weekly downloads — a measure of ecosystem reach, not a count of infected end users.
Sonatype later tracked additional packages (including some duckdb / prebid-related publishes) under the same campaign IDs. Always verify against current advisory lists when remediating — the exact set expanded in the first 24–48 hours.
Timeline (8 September 2025, UTC)
Condensed from Snyk’s published timeline:
- ~13:00 — First detected malicious publishes
- 13:16 — Aikido intel feed alerts on malicious packages
- 14:16 — Maintainer alerted on social platforms
- 15:16 — Compromise confirmed; npm notified
- 17:17 — npm acknowledges and works removals
- 19:59 — npm reports impacted versions taken down
Phishing lure details reported across industry blogs: emails impersonating npm support from the lookalike domain npmjs.help, with urgency around account lockouts. That is social engineering against a high-value maintainer — not a novel npm protocol flaw.
Technical behavior (crypto stealer)
Aikido and follow-on analyses describe obfuscated browser JavaScript that:
- Hooks
fetchandXMLHttpRequestto inspect network responses - Hooks wallet APIs such as
window.ethereum(and related web3 surfaces) - Rewrites payment / approval destinations toward attacker-controlled addresses before signing
The malware stayed dormant unless crypto/web3 activity appeared in the browser context. That selectivity helped explain why many Node CLI users saw nothing unusual while crypto front-ends faced the real theft risk.
Financial impact — cite, don’t invent
Despite the download headlines, reported realized theft was small. CSO Online quoted Aikido’s Charlie Eriksen tracking approximately $970 to attacker wallets; Sygnia’s advisory summarized losses around $500. Treat those as reported ranges, not audited totals. Hardware-wallet users who verified destinations on-device remained largely protected against silent UI swaps.
Download volume is not victim count. Most installs never executed the browser payload in a wallet context during the short live window.
What to do if you may have installed bad versions
- Diff lockfiles against known bad versions listed by Aikido / Snyk / Sonatype
- Search built JS for the IOC marker shared by Sindre Sorhus:
_0x112fa8 - Pin to known-good versions, wipe
node_modulesand CI caches, clean rebuild front-end bundles - If you ship crypto UI, audit on-chain activity for the incident window
- Rotate npm tokens / GitHub PATs if there is any chance they were exposed on a compromised maintainer machine
Where secret-sharing hygiene actually helps
VanishingVault does not stop supply-chain malware. Dependency scanning, lockfiles, trusted publishing, and phishing-resistant MFA for maintainers do. Secret-sharing hygiene still matters at the edges of the same incident class:
- Do not paste npm tokens, cloud keys, or seed phrases into Slack/email forever
- Hand credentials to teammates with a one-time encrypted link instead of a persistent chat paste
- Keep long-lived machine secrets in a vault / OIDC flow — see API key management vs one-time secrets
Later 2026 campaigns (worms, CI hijacks, other namespace takeovers) continue the same theme: registry trust is brittle. This article stays anchored on the Sept 8, 2025 chalk/debug incident because inventing breach counts across every follow-on campaign helps nobody.
Frequently Asked Questions
What happened in the September 2025 npm chalk/debug attack?
On September 8, 2025, maintainer Josh Junon (npm ~qix) was phished via a fake npm support domain (npmjs.help). Attackers published malicious versions of widely used packages including chalk and debug. Aikido Security detected the malicious publishes; npm removed the bad versions within hours.
What did the malware do?
It was browser-side crypto-stealer code: when bundled into web apps, it hooked fetch/XMLHttpRequest and wallet APIs (e.g. window.ethereum) to rewrite cryptocurrency payment destinations before the user signed. It was not a general ransomware worm for Node servers.
How much money was stolen?
Public reporting put realized crypto theft in the low hundreds to about $1,000 (Aikido’s Charlie Eriksen was quoted tracking roughly $970; other write-ups cite ~$500). Do not confuse package download volume with confirmed victim count or losses.
How does this relate to secret sharing?
Only at the hygiene layer: npm tokens, GitHub PATs, and wallet seed phrases should never live forever in Slack or email. Use MFA on maintainer accounts, pin lockfiles, and hand off credentials with one-time encrypted links — not as a substitute for dependency scanning.
How do I check if I pulled a malicious build?
Sindre Sorhus shared a ripgrep IOC search for the obfuscated marker _0x112fa8 in JS. Also audit lockfiles against the known bad versions (e.g. [email protected], [email protected]) listed by Aikido, Snyk, and Sonatype, then clean install from known-good pins.
Hand off credentials without leaving them in chat history
Use VanishingVault for one-time secret links — then keep dependency security and MFA as separate, non-negotiable controls.
Create a one-time secret