Shai-Hulud npm Supply Chain Worm
CriticalExecutive Summary
Shai-Hulud is the first known self-replicating worm in the npm ecosystem. It spreads via malicious preinstall/postinstall scripts, steals credentials, and automatically infects every package the victim can publish.
The good news: This attack is preventable. Disabling lifecycle scripts blocks the entire attack chain.
Attack Status: ACTIVE — Wave 2 ongoing. 800+ packages compromised, 25,000+ repositories exposed, 132M+ monthly downloads affected.
Critical Timeline Update
- November 5, 2025: npm disabled creation of new classic tokens
- November 19, 2025: npm revoked all classic tokens permanently
- If your CI/CD still uses classic tokens, it is already broken.
Understanding the Attack Surface
Where the Attack Executes
The malware runs wherever npm install executes. It is opportunistic — it harvests whatever credentials are available in that environment:
| Environment | Credentials at Risk | Monitoring Level |
|---|---|---|
| Developer workstations | ~/.npmrc, ~/.aws/credentials, git config, SSH keys | Often minimal |
| CI/CD pipelines | $NPM_TOKEN, $GITHUB_TOKEN, cloud IAM roles, secrets | Varies |
| Build servers | Service account tokens, automation credentials | Varies |
| Cloud instances | IMDS endpoint (169.254.169.254), instance roles | Usually better |
The malware explicitly probes AWS IMDS, GCP metadata endpoints, and Azure IMDS — demonstrating it expects to run in cloud/CI environments, not just developer machines.
Why Both CI/CD and Developer Machines Matter
CI/CD pipelines:
- Often have tokens with broad publish access
- May have access to production secrets
- Run
npm installon every build - IMDS provides cloud credentials without explicit configuration
Developer workstations:
- Often have long-lived tokens (never rotated)
- May have publish tokens stored in
~/.npmrc - Less likely to have egress filtering
- Less endpoint monitoring
- Developers may install arbitrary packages
Neither environment should be considered “safe” or “primary target.” The attack is opportunistic and effective in both.
The Propagation Problem
What makes Shai-Hulud uniquely dangerous is its self-replicating behavior:
Environment A (any) Environment B (any)
───────────────────── ─────────────────────
npm install executes │
│ │
▼ │
Malware harvests npm token │
│ │
▼ │
Publishes malware to all │
packages token can access ───────────┘
│ │
│ ▼
│ npm install executes
│ │
│ ▼
│ Malware harvests NEW token
│ │
│ ▼
│ Publishes to MORE packages
▼ ▼
EXPONENTIAL SPREAD ACROSS NPM ECOSYSTEMThe infection source is irrelevant. Whether it starts on a developer laptop or CI server, the worm spreads to all packages accessible by stolen tokens.
Developer Workstation Risk
| Risk Factor | Why It Matters |
|---|---|
| Long-lived npm tokens | ~/.npmrc tokens often never expire or rotate |
| Admin/sudo access | Developers can install any package without approval |
| Minimal egress filtering | Exfiltration to attacker C2 may go unblocked |
| Limited endpoint monitoring | Malicious postinstall execution may go undetected |
| Personal and work projects mixed | Side projects may pull in risky dependencies |
| Multiple publish permissions | Senior developers may have access to many packages |
Observed Impact
- One compromised user had access to 528 private repositories — all were made public
- Workflow logs exposed GitHub tokens, npm credentials, Atlassian keys, Datadog API keys
- 25,000+ repositories exposed within hours of Wave 2 starting
Immediate Mitigation Recommendations
Tier 1 — Immediate: Disable Lifecycle Scripts
This single action blocks the entire Shai-Hulud attack chain:
# .npmrc (all projects, all environments)
ignore-scripts=true
# Environment variable (prevents override)
export npm_config_ignore_scripts=trueCI/CD install commands with scripts disabled:
| Platform | Command |
|---|---|
| npm | npm ci --ignore-scripts |
| Yarn | yarn install --immutable --ignore-scripts |
| pnpm | pnpm install --frozen-lockfile --ignore-scripts |
| Bun | bun install --no-scripts |
Tier 2 — Short-Term: Token Rotation and Hardening
- Replace all classic npm tokens with granular tokens (max 90-day expiration).
- Enable Trusted Publishing (OIDC) where possible — eliminates stored secrets entirely.
- Enable npm provenance:
npm publish --provenance - Rotate all credentials:
| Credential Type | Action |
|---|---|
| npm tokens | Revoke all, create new granular tokens with minimal scope |
| GitHub PATs | Revoke all, create new fine-grained tokens |
| GitHub SSH keys | Remove and regenerate |
| AWS credentials | Deactivate, delete, create new |
| GCP service accounts | Generate new keys, delete old |
| Azure credentials | Reset via portal |
| CI/CD secrets | Rotate all |
| API keys | Regenerate via provider |
Tier 3 — Medium-Term: Detection and Monitoring
- Deploy install-time scanning (Socket, SafeDep vet/pmg, Snyk, Semgrep Supply Chain)
- Schedule daily SCA scans
- Enable egress filtering (allowlist preferred)
- Enable MFA on npm and GitHub (WebAuthn/passkey preferred)
- Add IMDS access monitoring — unexpected IMDS calls from CI jobs are a strong compromise indicator
Tier 4 — Strategic
- Pin dependencies to exact versions with lockfile-only installs in CI/CD
- Audit npm package publish history for unexpected version bumps
- Review GitHub audit logs for bulk token operations
- Implement AI-assisted dependency review for new packages entering your supply chain
Indicators of Compromise
| Indicator | Type |
|---|---|
webhook.site/bb8ca5f6-4175-45d2-b042-fc9ebb8170b7 | C2 exfiltration endpoint |
bun.sh/install | Bun runtime installer (used by malware) |
169.254.169.254 | AWS IMDS (legitimate, but unexpected access is suspicious) |
metadata.google.internal | GCP metadata (legitimate, but unexpected access is suspicious) |
GitHub Repository Indicators
| Pattern | Meaning |
|---|---|
Repository named Shai-Hulud | Exfiltration repository |
| Description: “Shai-Hulud Repository.” | Wave 1 indicator |
| Description: “Sha1-Hulud: The Second Coming.” | Wave 2 indicator |
| Description: “Shai-Hulud Migration” | Exposed private repository |
Branch: shai-hulud | Malicious workflow injection |
Runner name: SHA1HULUD | Backdoor self-hosted runner |
Files: data.json, cloud.json, truffleSecrets.json | Exfiltrated credentials |
Key Dates
| Date | Event |
|---|---|
| August 26–27, 2025 | s1ngularity/Nx attack (precursor) |
| September 15–18, 2025 | Shai-Hulud Wave 1 |
| October 13, 2025 | npm granular tokens: 7-day default, 90-day max |
| November 5, 2025 | npm classic token creation disabled |
| November 19, 2025 | npm classic tokens permanently revoked |
| November 21–24, 2025 | Shai-Hulud Wave 2 (ongoing) |
References
- SafeDep: Shai-Hulud Migration Response
- Wiz Research IOCs
- CISA: Widespread Supply Chain Compromise Impacting npm Ecosystem (2025)
- Socket Security Blog
- npm Official Blog
- GitHub Changelog