If you installed a bad npm package
Scope: any npm package — direct or transitive — that turned out to be compromised.
Authoritative reference playbooks
Before this one, read whichever applies:
- Snyk — NPM Security Best Practices After the Shai-Hulud Attack — incident-response checklist tuned for 2025–2026 worms.
- Microsoft Security — Shai-Hulud 2.0 Guidance — detect, investigate, defend.
- StepSecurity — Active Supply Chain Attack: Malicious node-ipc — recent example with IOCs.
- CISA — Defending Against Software Supply Chain Attacks — framework-level.
Do this first (60 seconds)
# 1. Disconnect from the internet if you can (Wi-Fi off / VPN kill switch).
# This stops live exfiltration mid-flight.
# 2. Kill node processes that might still be exfiltrating.
pkill -9 node
pkill -9 npm
pkill -9 bun
pkill -9 yarn
pkill -9 pnpm
Now reconnect. The damage is mostly done at install-time; what matters next is rotation.
Triage
What got run?
The dangerous moment is postinstall execution. If you installed with --ignore-scripts, you're probably fine — just remove and reinstall clean.
# Confirm whether ignore-scripts was set
cat ~/.npmrc | grep ignore-scripts
cat .npmrc 2>/dev/null | grep ignore-scripts
Identify the bad package + version
# All copies in your tree (direct + transitive)
npm ls <bad-package> --all
# Or dump the lockfile
grep -B1 -A3 '"<bad-package>"' package-lock.json
Identify when it ran
ls -la node_modules/<bad-package>/package.json
# stat times tell you when the bad version landed
Rotate (in priority order)
Assume everything readable from your user account was exfiltrated. Rotate in this order — top items have the shortest exploitation window.
- npm token. → if-your-npm-token-leaked.md
- GitHub PAT. → if-your-github-pat-leaked.md
- Cloud credentials (AWS, GCP, Azure, Kubernetes). → rotating-cloud-credentials.md
- SSH keys. Generate new
~/.ssh/id_ed25519, replace public keys in GitHub/GitLab/servers, revoke old key everywhere it was authorized. - AI API keys. Anthropic, OpenAI, Google AI, OpenRouter, Replicate. Rotate via each vendor's console.
- Browser cookies / saved passwords. If the malware ran as your user, it could have read Chrome/Firefox storage. Sign out of high-value services (banking, email, GitHub, AWS) and force-revoke active sessions.
- Crypto wallets. If you have hot wallets (MetaMask, etc.) on this machine, move funds from a different device to a fresh wallet. Don't trust the compromised machine.
Clean
# Nuke the dependency tree
rm -rf node_modules package-lock.json yarn.lock pnpm-lock.yaml
# Reinstall with scripts disabled, then verify the bad package is gone
npm install --ignore-scripts
npm ls <bad-package>
If the bad version is still pulled in transitively, pin a known-good in overrides (npm) / resolutions (yarn/pnpm):
// package.json
"overrides": {
"<bad-package>": "<known-good-version>"
}
Verify — look for known worm signatures
# Shai-Hulud 2.0 bun-based execution
find ~ -name "setup_bun.js" -o -name "bun_environment.js" 2>/dev/null
# node-ipc forensic markers (May 2026)
find ~/.npm ~/.cache -name "node-ipc-*.tgz" -exec sh -c \
'tar -tvf "$1" 2>/dev/null | grep "1985"' _ {} \;
ps eww | grep "__ntw=1"
ls -la "${TMPDIR:-/tmp}"/nt-* 2>/dev/null
# Check GitHub for planted public repos (Shai-Hulud signature)
gh api /user/repos --paginate --jq '.[] | select(.created_at > "DATE_OF_INSTALL" or (.name | test("Shai-Hulud"; "i"))) | .full_name'
# Check npm for packages you didn't publish
npm whoami
npm access list packages
If you find traces — assume full machine compromise. Reimage the dev machine, don't just rotate secrets.
Detection signals to monitor for the next 7 days
Per Microsoft's Shai-Hulud 2.0 guidance:
- Outbound DNS to unusual domains (the node-ipc payload uses DNS exfil).
- New public repos in your GitHub account.
- New SSH keys / deploy keys in your account.
- Unexpected commits / pushes to your repos.
- Cloud billing anomalies (compute spikes from unfamiliar regions).
- npm 2FA challenge prompts you didn't initiate.
Document
Add to your team's issues.md:
- date, package, version, install timestamp
- which secrets were on disk
- what you rotated (with timestamps)
- whether you reimaged
You'll want this when the auditor / your CTO / your customers ask.
Prevention going forward
- prevention/npm-hardening.md —
--ignore-scripts, exact pins, release cooldown,npm ci, trusted publishing. - prevention/agent-sandboxing.md — install inside a devcontainer.