What the npm Worm Wave of 2025 Should Change About How You Ship
Cybersecurity
September 2025 brought self-replicating worms across npm publisher accounts. Stolen tokens, malicious updates pushed to neighbouring packages, billions of downloads in the blast radius. If your CI runs npm install on every build and trusts the lockfile, you are downwind of this attack class.
By Arjun Raghavan, Security & Systems Lead, BIPI · October 8, 2025 · 8 min read
September 2025 brought the most aggressive npm supply-chain attack the ecosystem has seen at scale. A self-replicating worm — informally tagged Shai-Hulud by the researchers who first traced it — propagated through dozens of compromised publisher accounts, harvested npm tokens from CI environments, and used those tokens to publish malicious updates to other packages owned by the same publishers. The blast radius reached hundreds of packages and billions of cumulative weekly downloads. A lot of teams ran build pipelines that pulled the poisoned versions before npm could yank them.
If your CI runs npm install on every build and trusts whatever the lockfile resolves, you are exposed to this attack class. The defences exist but are non-default. Here is what we tell clients to change.
The 2025 attack pattern in 90 seconds
Older npm attacks were targeted: an attacker compromises one maintainer's account through credential reuse or phishing, publishes a malicious version of one package, and waits for downloads. The 2025 wave is structurally different.
- Worm enters via a typosquat or a previously compromised package being installed somewhere with publish access.
- Postinstall script executes during npm install. The script does not do anything malicious in the foreground. It quietly searches the local environment for npm tokens — .npmrc files, NPM_TOKEN env vars, GitHub Actions secrets exposed via environment.
- Tokens get exfiltrated to attacker-controlled infrastructure.
- Attacker enumerates which other packages those tokens have publish access to. Most npm publishers maintain multiple packages with the same token.
- Worm publishes new patch versions of every reachable package, with the same payload embedded in postinstall.
- Each downstream npm install of any of those packages re-triggers steps 2-5.
The result is exponential propagation. A single compromised package becomes 50 compromised packages within a week. Each of those triggers more compromise as CI pipelines worldwide install them. The defender's window is hours, not days.
Why postinstall scripts are still the issue
npm install runs three lifecycle scripts by default: preinstall, install, and postinstall. Any package in your dependency tree (direct or transitive) can declare any of them. The script runs with the same privileges as the install — which is usually your CI user, which usually has access to a lot of secrets.
npm has known this is a problem for a decade. The flag --ignore-scripts has existed forever. Almost nobody uses it because some legitimate packages need their install scripts. The result is a default that is convenient for legitimate use and equally convenient for attackers.
Five things to change this quarter
- Set npm config 'ignore-scripts=true' in CI by default. Add an explicit allowlist for the few packages that actually need install scripts. Most projects need zero exceptions.
- Use OIDC for npm publish in CI. Eliminate long-lived NPM_TOKEN secrets. GitHub Actions has supported this for npm since 2024. The token is short-lived, scoped, and unstealable from the local filesystem.
- Lockfile audits on every PR. Automated tooling that compares the new lockfile against the old, surfacing any new packages or version bumps. A human reviews unfamiliar additions before merge.
- Use socket.dev, Snyk, or your provider's package-vetting layer. These tools maintain near-real-time databases of known-bad packages and flag them at install time. Free tiers exist. The detection latency on Shai-Hulud was hours; the tools that flagged it were already deployed at the teams that did not get hit.
- Run a private npm registry mirror that pins approved versions. Even a 24-hour cache delay between the public registry and your registry buys you the window between worm publish and worm yank.
npm tokens: the operational hygiene that matters
If your CI uses a long-lived NPM_TOKEN, that token is a single point of failure for every package you publish. Treat it the way you would treat an AWS root key.
- Rotate quarterly. If you have not rotated this year, you have already failed the basics.
- Granular tokens scoped to specific packages. npm supports this; most teams do not use it.
- Different tokens for different repos. One leaked token should not authorise publish to your entire org.
- Migrate to OIDC. The tokens that survive are short-lived, generated per workflow run.
- If you read or print the token in a CI step (logs, error output), assume it has leaked.
What package signing fixes (and does not)
npm provenance, built on Sigstore, lets publishers attach cryptographic attestations to their packages. The attestation states 'this package was built from this commit, by this CI workflow, in this repo.' Consumers can verify the chain.
Provenance prevents an attacker from publishing a package that does not match the expected build chain. It does NOT prevent the legitimate publisher from being compromised and publishing a malicious version through the legitimate build chain. Shai-Hulud-style attacks ship through the publisher's own credentials, so the provenance is technically valid.
Provenance does help with detection: an unexpected publisher CI account, a build from a fork, an attestation from an unusual repo — these are signals the consumer can flag automatically. Adopt it. It is not a silver bullet but it raises the floor.
Closing
The npm worm wave of 2025 will not be the last. The economics are too favourable: low cost to the attacker, exponential blast radius, low detection rate. Every team that runs npm install on every CI build is a target. The defence is layered and operational — not a single tool, but a posture. Treat every dependency as untrusted. Treat every install script as hostile until proven otherwise. Rotate tokens like AWS keys. The teams that do this are the ones that wake up after the next worm and find their pipelines clean.
Read more field notes, explore our services, or get in touch at info@bipi.in. Privacy Policy · Terms.