A Node.js script to check your npm packages against the list of packages compromised in the Shai-Hulud 2.0 supply chain attack (November 2025).
Shai-Hulud 2.0 is a sophisticated self-replicating worm that compromised 796+ npm packages in November 2025. The malware:
- Steals credentials (GitHub tokens, npm tokens, AWS/GCP/Azure keys, SSH keys)
- Exfiltrates data to GitHub repositories
- Self-propagates by publishing malicious versions of packages
- Installs persistent backdoors via GitHub Actions runners
- Can delete user data if propagation fails
check-shai-hulud.js- The scanner scriptshai-hulud-2_0.csv- List of 538 compromised package versions
- Node.js (any recent version)
- Your project with
package.jsonand ideallypackage-lock.json
Navigate to your project directory and run:
node check-shai-hulud.js path/to/shai-hulud-2_0.csvnode check-shai-hulud.js path/to/shai-hulud-2_0.csv /path/to/your/project# If both files are in your project root
node check-shai-hulud.js ./shai-hulud-2_0.csv
# Check a different project
node check-shai-hulud.js ./shai-hulud-2_0.csv ~/projects/my-app- ✅ Reads the compromised packages database (CSV)
- ✅ Scans your
package-lock.json(orpackage.jsonas fallback) - ✅ Checks both direct and transitive (nested) dependencies
- ✅ Reports exact version matches against compromised packages
- ✅ Provides clear remediation steps if threats are found
✅ CLEAN: No compromised packages detected!
Scanned 247 package(s). Your project appears safe from this attack.
🚨 CRITICAL: 2 COMPROMISED PACKAGE(S) FOUND!
[1] posthog-node@5.13.3
Type: dependency
Direct dependency: Yes
[2] @asyncapi/parser@3.4.2
Type: dependency
Direct dependency: No (transitive)
STOP IMMEDIATELY and follow these steps:
-
Do NOT run
npm installuntil you've updated packages -
Remove infected files:
rm -rf node_modules package-lock.json npm cache clean --force
-
Update/remove compromised packages in
package.json -
Rotate ALL credentials:
- npm tokens
- GitHub Personal Access Tokens (PATs)
- AWS/GCP/Azure credentials
- SSH keys
- Any other secrets that may have been exposed
-
Check for malicious artifacts:
# Check for malicious files find . -name "setup_bun.js" -o -name "bun_environment.js" # Check for malicious workflows ls -la .github/workflows/ | grep -E "(discussion|formatter_)" # Check for unauthorized GitHub runners (requires gh CLI) gh api repos/{owner}/{repo}/actions/runners --jq '.runners[].name' | grep -i sha1hulud
-
Search for compromised repositories:
- Check your GitHub account for repos with description "Sha1-Hulud: The Second Coming"
- Look for repos with 18-character random alphanumeric names
- Check for repos with "-migration" suffix
-
Fresh install with safeguards:
npm install --ignore-scripts # Prevents postinstall/preinstall hooks npm audit
The script:
- Parses the CSV containing compromised package names and versions
- Reads your project's
package-lock.json(preferred) orpackage.json - Performs exact version matching (not just package name)
- Identifies both direct dependencies and transitive (nested) dependencies
- Exits with code 1 if compromised packages found (useful for CI/CD)
- Requires exact version match (won't catch if you have different versions)
- CSV must be kept up-to-date as new compromised packages are discovered
- Only checks npm packages (not yarn berry PnP, pnpm, or other package managers)
- CISA Alert on Shai-Hulud
- Wiz Research: Shai-Hulud 2.0
- Unit 42: Technical Analysis
- Datadog: IOCs and Detection
To update the compromised packages list:
- Add new entries to
shai-hulud-2_0.csvin format:package_name,version - Keep the header row:
package_name,package_version
This tool is provided as-is for security scanning purposes. Use freely.
Stay safe and keep your dependencies updated! 🛡️