The worm that taught the supply chain to replicate itself
Summary
- Shai-Hulud was the first self-replicating npm worm: each infected package stole credentials and used them to publish the worm into the maintainer's other packages.
- The November wave reached ~25,000 malicious repositories and carried a destructive dead-man's switch.
- What an external scan would have shown for any website: which third-party scripts you load, whether CSP and Subresource Integrity are in place, and lookalike script domains.
On this page
For most of its history, a software supply-chain attack needed a human at the wheel: compromise a package, wait, watch it spread as developers update. In the autumn of 2025, the npm ecosystem watched that assumption die. A worm learned to do the spreading by itself.
A bad few months for npm install
The escalation came in waves, each nastier than the last.
In late August, attackers compromised the popular Nx build tool (tracked as CVE-2025-10894) in what researchers called the first AI-weaponized supply-chain attack: the malware actually invoked locally installed AI coding assistants — Claude Code, Gemini CLI, Amazon Q — and asked them to hunt for secrets on disk. It harvested an estimated 2,349 distinct secrets from more than a thousand developer machines and dumped them into public repositories in the victims’ own GitHub accounts.
A couple of weeks later, the maintainer of chalk and debug — packages with,
between them and their siblings, more than two billion downloads a week — was
phished through a lookalike domain, npmjs.help, that had been registered just
three days before the attack. The attacker published malicious versions
carrying a browser-side crypto-wallet drainer. The reach was staggering; Wiz
estimated the bad code touched something like 10% of cloud environments during the
roughly two-hour window. The actual theft? Researchers tracked it at around
$600. The damage was not the loot. It was the demonstration that two billion
weekly downloads can be turned hostile in sixteen minutes.
Shai-Hulud: the part that moves on its own
Then, on 15 September 2025, came Shai-Hulud — named, fittingly, after the sand
worms of Dune. This was the first self-replicating npm worm. Its payload, run
on install, used the secret-scanning tool TruffleHog to find credentials on the
host; with a stolen npm token it would authenticate as that developer, locate
their other packages, inject itself, and republish them. Each infection
manufactured the next. Patient zero was @ctrl/tinycolor, a package with millions
of weekly downloads; within 24 hours roughly 200 packages were carrying it.
The November sequel, “Sha1-Hulud: The Second Coming,” was built to hurt more.
It moved its trigger from postinstall to preinstall, so it ran before an
install could even fail. It installed the Bun runtime to execute its payload
outside the monitoring tuned for Node.js. It registered infected machines as
GitHub Actions runners for persistence. And it carried a dead-man’s switch: if it
could neither exfiltrate nor propagate, it attempted to wipe the user’s home
directory. Datadog and Wiz converged on roughly 750-800 unique poisoned
packages and more than 25,000 malicious repositories, with confirmed
trojanized packages from organizations including Zapier, ENS, PostHog, Postman,
and AsyncAPI.
The one that explains your website
Most of the above is a developer’s problem. But there is a version of this attack
that lands on anyone with a website, and it has a name everyone learned in 2024:
polyfill.io. For years, hundreds of thousands of sites loaded a small
JavaScript shim from cdn.polyfill.io with a plain <script> tag. In February
2024 the domain and its GitHub account were sold. By June, the new owner was using
that same trusted URL to serve malware — conditionally, to mobile users,
suppressing itself when it detected an administrator looking. Sansec reported more
than 100,000 affected sites; Censys still counted 384,773 hosts loading the
script in early July. The script the sites had embedded years ago did not change.
Its owner did.
That is the through-line from Shai-Hulud to polyfill: the code your site loads from somebody else is part of your attack surface, and “we added it years ago and it still works” is not the reassurance it sounds like.
What the outside view would have shown
You cannot audit npm’s internals from outside someone’s website. But the web-facing version of supply-chain risk is remarkably visible from the outside, and it is exactly what an external review of a site looks at:
- What you load, and from where. Every third-party
<script src>is a trust relationship. An outside-in inventory of those origins — and whether any of them point at a parked, expired, or recently-transferred domain — is the polyfill early-warning system. - Content-Security-Policy. A strict
script-srcallowlist would have blocked the polyfill injection from exfiltrating anywhere it pleased. The absence of a CSP, or a CSP riddled withunsafe-inline, is itself a finding. See HTTP security headers, explained . - Subresource Integrity. A third-party script tag with an
integrity=hash fails safe: if the file changes, the browser refuses to run it. The polyfill attack would have broken the page instead of robbing the visitor. Missing SRI on external resources is a clean, measurable gap. - Lookalike domains.
npmjs.help, registered three days before it was used, is the same signal as a freshly minted domain that resembles your brand. Watching for those is cheap and high-value.
The 2025 worms were a wake-up call for how software is built. The quieter lesson, for everyone who merely runs a site, is that your dependencies have a public face — and that face can be reviewed from the outside before it turns on you. That review is what zmam.ai is built to do.
Sources
- Nx, “s1ngularity post-mortem”: https://nx.dev/blog/s1ngularity-postmortem
- Wiz, “Shai-Hulud npm supply chain attack”: https://www.wiz.io/blog/shai-hulud-npm-supply-chain-attack
- Datadog Security Labs, “Shai-Hulud 2.0 npm worm”: https://securitylabs.datadoghq.com/articles/shai-hulud-2.0-npm-worm/
- Aikido, “npm debug and chalk packages compromised”: https://www.aikido.dev/blog/npm-debug-and-chalk-packages-compromised
- Sansec, “Polyfill supply chain attack”: https://sansec.io/research/polyfill-supply-chain-attack
- Censys, “Polyfill.io supply chain attack”: https://censys.com/blog/july-2-polyfill-io-supply-chain-attack-digging-into-the-web-of-compromised-domains/
— reads