Shai-Hulud (Sept 2025): A Self-Spreading npm Worm That Steals Cloud Secrets
Facts in this article were checked against the sources listed below as of Oct 5, 2026.
Retrospective: this article looks back at events from September 2025, written in 2026 with the benefit of hindsight.
In mid-September 2025, security researchers disclosed a major compromise of the npm JavaScript package ecosystem. A self-replicating worm, publicly known as Shai-Hulud, had compromised more than 500 packages. On September 23, 2025, CISA issued an alert urging organizations to check their dependencies and rotate developer credentials.
- Initial compromiseAttackers gain access to npm maintainer accounts and publish infected package versions.
- Install-time executionInstalling an infected package runs malicious code on developer machines and CI runners.
- Credential harvestThe malware scans for GitHub personal access tokens and cloud keys for AWS, GCP and Azure.
- Public exposureStolen credentials are exfiltrated and uploaded to public GitHub repositories named Shai-Hulud.
- Self-propagationUsing stolen npm tokens, the worm publishes infected versions of other packages the victim maintains.
What set Shai-Hulud apart was automation. Each infection didn't just steal secrets; it used them to infect more packages — turning individual developer compromises into an ecosystem-wide event.
How it worked
According to CISA:
- After gaining initial access to maintainer accounts, the actor published package versions containing malware.
- When developers or CI systems installed an infected package, the malware ran and scanned the environment for sensitive credentials, targeting GitHub personal access tokens and API keys for AWS, GCP and Microsoft Azure.
- Harvested credentials were exfiltrated to an attacker-controlled endpoint and uploaded to a public GitHub repository named "Shai-Hulud" using the GitHub API — exposing them to anyone.
- The malware then authenticated to the npm registry as the compromised developer and injected code into other packages they maintained, spreading automatically.
CISA recommended reviewing dependencies and lockfiles, searching artifact repositories for cached malicious versions, pinning npm packages to known-safe releases from before September 16, 2025, and immediately rotating all developer credentials. A second, larger wave followed later in 2025.
Why it mattered
Developer machines and CI runners hold the keys. Cloud credentials, source control tokens and package publishing rights often live on the same laptop or build agent.
Install scripts run with your privileges. Installing a dependency can execute arbitrary code before anyone reviews it.
Public exposure accelerates abuse. Publishing stolen secrets to public repositories meant any attacker — not just the worm's operators — could use them.
Self-propagation changes the timeline. Defenders had hours, not weeks, before the infection spread to more packages.
What to do now
- Eliminate long-lived cloud keys on developer machines. Use IAM Identity Center (
aws sso login) for AWS and Entra ID sign-in for Azure CLI and PowerShell, so tokens are short-lived. Use OIDC federation for CI/CD instead of stored keys. - Use lockfiles and pin versions. Commit
package-lock.jsonor equivalents, usenpm ciin pipelines, and update dependencies through reviewed pull requests rather than automatically pulling the latest versions. - Restrict install scripts. Consider
--ignore-scriptsin CI where possible, and allow scripts only for packages that need them. - Use an internal registry or proxy that caches approved packages and can block known-malicious versions quickly.
- Protect maintainer and source control accounts with phishing-resistant MFA and fine-grained, short-lived tokens. Enable npm trusted publishing where available.
- Run EDR on developer machines and self-hosted CI runners.
- Make leak notifications reach responders. GitHub secret scanning and its partner program notify cloud providers when credentials appear publicly; AWS may notify you and apply a quarantine policy to exposed keys. Route those notifications to your on-call team.
- Practice rotation. Know how to rotate every developer and pipeline credential within a day.
How to detect a package-borne worm
- Package managers spawning unusual tools. Node.js or npm processes launching secret scanners, shells or network tools on developer machines and runners.
- New public repositories created under employee accounts, especially with unusual names.
- Unexpected package publishes from your organization's npm accounts.
- Cloud credential use from new locations shortly after dependency installs — in CloudTrail, Azure Activity logs and Entra sign-in logs.
- Secret scanning and provider leak alerts.
Common mistakes
- Keeping static cloud keys in
~/.aws/credentialsor environment variables on developer laptops. - Floating dependency versions that pull whatever was published most recently.
- Treating CI runners as trusted when they install untrusted code on every build.
- Rotating only the obvious secrets and missing tokens in tools, scripts and IDEs.
A developer workstation baseline
Supply-chain worms target developers because developers hold powerful access. A practical baseline for engineering devices:
- Company-managed devices with EDR, disk encryption and automatic updates.
- No long-lived cloud keys on disk; short-lived sessions through IAM Identity Center and Entra ID.
- Phishing-resistant MFA for source control, package registries and cloud consoles.
- Fine-grained, short-lived tokens for GitHub and npm, scoped to what each task needs.
- Separate environments — dev containers or VMs — for experimenting with unfamiliar packages and code.
- An internal package proxy with the ability to block malicious versions quickly.
- A tested process to rotate every developer credential within a day.
Why npm, and why now
Package ecosystems are attractive because a single popular package can reach thousands of organizations, and because publishing rights depend on maintainer accounts that may not be strongly protected. Shai-Hulud added automation: by reusing stolen publishing tokens, it spread without human effort. Registries have responded with stronger authentication requirements and trusted publishing, but consumers still need lockfiles, pinned versions, short-lived credentials and the ability to rotate quickly. The same techniques apply to PyPI, RubyGems and other ecosystems.
Questions for leadership
- Do our developers have long-lived cloud keys on their machines?
- Could we rotate every developer and pipeline credential within 24 hours?
- Would we know if our credentials appeared in a public repository?
Key takeaways
- Shai-Hulud compromised 500+ npm packages and stole GitHub tokens and AWS, GCP and Azure keys.
- Stolen secrets were published publicly, and the worm spread using stolen npm tokens.
- Short-lived credentials, pinned dependencies and restricted install scripts limit the damage.
- Make sure leak notifications reach responders and that rotation is practiced.
- Apply the same controls to PyPI, RubyGems and other package ecosystems your teams use.
- Treat CI runners as untrusted: they install third-party code on every build.
Sources
- How to Detect Leaked Cloud Credentials From Developer Packages How-To & Hardening
- Detecting npm Supply Chain Worm: Sentinel and GuardDuty Detections Detection & Response
- CIO Brief: Open-Source Worms and Your Cloud Keys CIO Briefings