Shai-Hulud npm worm — original wave (September 2025)
TL;DR
On 2025-09-15, the first self-replicating npm worm — Shai-Hulud — was discovered. ~200 packages compromised, including @ctrl/tinycolor (2.2M weekly), ngx-bootstrap (300k weekly), and several CrowdStrike-owned packages. The worm stole GitHub/npm/AWS/GCP credentials, then re-published itself into every other package owned by each compromised maintainer.
What happened
The worm's flow:
- Execute via postinstall. Each compromised package had a
postinstallhook that ranbundle.js. - Steal credentials. Scan filesystem for GitHub tokens,
~/.npmrc, AWS/GCP creds. - Leak via private repos → public. Flip the maintainer's private repos to public, exposing source + any committed secrets.
- Publish to a
Shai-HuludGitHub repo. Stolen creds uploaded as base64 JSON. - Replicate. Use stolen npm tokens to enumerate every other package the maintainer owns; publish new versions of each with the worm injected.
This was the first time the npm community saw worm-style self-propagation. Named after the Dune sandworms.
Am I affected?
# Check the canonical first-infection package
npm ls @ctrl/tinycolor --all
npm ls ngx-bootstrap --all
npm ls ng2-file-upload --all
Full IOC lists are maintained by the sources below — cross-reference your lockfile against them.
# Was a "Shai-Hulud" repo planted on your GitHub?
gh api /user/repos --paginate --jq '.[] | select(.name | test("Shai-Hulud"; "i")) | .full_name'
If you are affected
→ playbooks/if-you-installed-a-bad-npm-package.md → playbooks/if-your-github-pat-leaked.md → playbooks/if-your-npm-token-leaked.md
Prevention
→ prevention/npm-hardening.md → prevention/credential-hygiene.md