Shai-Hulud was a self-replicating worm that spread through the npm registry in September 2025. It stole developer credentials, used stolen npm tokens to publish infected versions of other packages, and compromised more than 500 packages. The lessons are about credentials: short-lived tokens, trusted publishing, phishing-resistant MFA, and lockfile discipline.
How did it work?
Per CISA's alert and Unit 42's analysis, the infected package versions carried a post-install script. On a developer machine or build server it searched for secrets: npm tokens in .npmrc files, GitHub personal access tokens, and cloud keys for AWS, Google Cloud and Azure.
It then did three things. It sent the credentials to an endpoint the actor controlled. It created a public GitHub repository named "Shai-Hulud" under the victim's account and pushed the stolen secrets there. And it used the stolen npm token to find other packages the victim maintained, inject the malicious code, and publish new versions. That last step is what made it a worm and not a one-off compromise.
Unit 42 reported the original access may have come from a phishing campaign that imitated npm and asked developers to update their MFA settings. It also said, with moderate confidence, that an LLM helped write part of the malicious script. Treat the phishing origin as the researchers' assessment, not a settled fact for every victim.
What is the timeline?
- 14 September 2025: GitHub says it was notified of the attack.
- 15 September 2025: StepSecurity publishes its report on the first compromised packages. Socket follows with updates on 16 September.
- 22 September 2025: GitHub announces its plan to harden npm. It had removed more than 500 compromised packages and blocked uploads containing the malware's indicators.
- 23 September 2025: CISA issues an alert and says over 500 packages were compromised.
- November 2025: Unit 42 reports a renewed campaign, "Shai-Hulud 2.0", wider in scope. It ran at pre-install instead of post-install, used new payload files, and exfiltrated to repositories described as "Sha1-Hulud: The Second Coming". Unit 42 reported over 25,000 malicious repositories across about 350 users, and a fallback that tried to destroy the user's home directory when it could not steal or send credentials.
What changed on the registry side?
GitHub said it would move npm publishing toward local publishing with required 2FA, granular tokens with a seven-day lifetime, and trusted publishing. It listed deprecating classic tokens, moving from TOTP to FIDO-based 2FA, and removing the option to bypass 2FA for local publishing. It described rolling these out gradually, so check current npm documentation for what is live today.
What should defenders learn?
Install scripts are code execution. Both waves ran during package installation. If your CI runs installs with broad credentials in the environment, the worm inherits them.
Credentials in the environment are the payload. The malware went hunting for tokens. A build job that holds a long-lived cloud key and a publish token is worth far more to an attacker than the source tree.
A clean scan on Monday is not a clean scan on Thursday. GitHub removed the compromised packages after it was notified, so the exposure window was bounded. Teams that pinned versions and reviewed lockfile changes had less to clean up.
Rotation is part of the response. CISA's first recommendation after dependency review was to rotate all developer credentials.
What to do
- Search lockfiles and artifact caches for the affected packages, including nested ones.
- Pin dependencies to versions published before the compromise window and review every lockfile diff.
- Rotate developer credentials, GitHub tokens, npm tokens and cloud keys if an affected version ever installed.
- Require phishing-resistant MFA on GitHub and npm accounts.
- Publish with trusted publishing instead of long-lived tokens.
- Run installs in CI with the minimum credentials, and consider disabling install scripts where your build allows it.
- Search your organization for unexpected public repositories named like the worm's, and audit GitHub Apps, OAuth apps and webhooks.
- Block outbound connections to webhook.site domains and watch egress logs, as CISA suggested.
For step 1, the Safeguard CLI can build an SBOM from a directory or read an existing SPDX or CycloneDX file, which gives you a searchable list of every package and version in your tree to check against the published lists of affected packages.
Quick check
Was every npm package affected?
No. CISA reported over 500 compromised packages in the first wave. The risk to you depends on whether an affected version was ever installed in your builds or on developer machines.
Is removing the package enough?
No. If the malicious version ran, assume the secrets it could read were taken and rotate them.
Sources
- CISA: Widespread Supply Chain Compromise Impacting npm Ecosystem, 23 September 2025
- GitHub: Our plan for a more secure npm supply chain, 22 September 2025
- Unit 42: "Shai-Hulud" Worm Compromises npm Ecosystem (updated November 2025)
- StepSecurity: Shai-Hulud self-replicating worm compromises 500+ npm packages
- Safeguard CLI
Last reviewed: 18 October 2026.