A comprehensive security scanner for detecting the Shai-Hulud npm worm and similar supply chain attacks in your local repositories.
Shai-Hulud is a self-replicating worm targeting the npm ecosystem that injects malicious code into packages, steals developer and cloud tokens, and propagates via compromised maintainer accounts and GitHub workflows. First observed in mid-September 2025, it has rapidly spread across hundreds of npm packages.
- Propagation: Modifies
package.jsonto add maliciouspostinstallscripts - Execution: Runs
bundle.jsduring package installation - Data Theft: Harvests npm, GitHub, AWS, and GCP tokens
- Exfiltration: Creates public GitHub repos and uses GitHub Actions to leak data
- Lateral Movement: Uses stolen credentials to compromise additional packages
audit-tree.sh performs deep scanning of your local repositories to detect:
- β
Malicious
bundle.jsfiles with known hashes - β
Suspicious
postinstallscripts inpackage.json - β
The
shai-hulud-workflow.ymlGitHub Action - β
Exposed tokens in
.npmrcfiles - β
Webhook exfiltration URLs (specifically
webhook.site/bb8ca5f6-4175-45d2-b042-fc9ebb8170b7) - β
System-level infection files (
/tmp/processor.sh,/tmp/migrate-repos.sh) - β
Repositories with
shai-huludbranches - β
Suspicious
-migrationrepository suffixes
# Clone the repository
git clone https://github.com/yourusername/audit-tree.git
cd audit-tree
# Make the script executable
chmod +x audit-tree.sh# Scan current directory and all subdirectories
./audit-tree.sh
# Scan a specific directory
./audit-tree.sh /path/to/projects
# Generate JSON output for CI/CD pipelines
./audit-tree.sh . --json- zsh (default on macOS, available on Linux)
- git (for repository analysis)
- jq - For enhanced
package.jsonanalysis - ripgrep (rg) - For faster scanning of large codebases
- sha256sum or shasum - For file hash verification
The script will detect missing dependencies and continue with reduced functionality.
$ ./audit-tree.sh
π Enhanced NPM Worm Scanner - Checking for Shai-Hulud indicators
================================================================
Scanning directory: .
Started at: Thu 18 Sep 10:52:13 BST 2025
π¬ Checking for system-level indicators...
π Building file index and checking for suspicious files/directories...
β οΈ FOUND: bundle.js in a package root
Location: ./vulnerable-package/
π¨ CRITICAL: Hash matches known malicious bundle.js!
π¨ CRITICAL: Found malicious 'postinstall' script in ./package.json
Script: postinstall: "node bundle.js"
π Scanning all non-binary files for string indicators...
π¨ CRITICAL: Found known malicious webhook URL!
File: ./src/exfiltrate.js
Match: webhook.site/bb8ca5f6-4175-45d2-b042-fc9ebb8170b7
================================================================
π¨ Found 3 potential indicator(s). Manual review is required.
π Suspicious files requiring immediate manual review:
- ./vulnerable-package/bundle.js
- ./package.json
- ./src/exfiltrate.js$ ./audit-tree.sh . --json | jq
{
"scan_completed": "2025-09-18T09:52:13Z",
"scan_directory": ".",
"issues_found": 3,
"scanned_git_directories": 5,
"scanned_package_json": 12,
"suspicious_files": [
"./vulnerable-package/bundle.js",
"./package.json",
"./src/exfiltrate.js"
],
"missing_dependencies": [],
"tools_used": {
"grep": "rg",
"hash": "sha256sum"
}
}The script searches for these specific indicators:
- bundle.js with SHA-256:
46faab8ab153fae6e80e7cca38eab363075bb524edd79e42269217a083628f09 - .github/workflows/shai-hulud-workflow.yml
- /tmp/processor.sh and /tmp/migrate-repos.sh (system infection)
postinstallscripts executingnode bundle.js- Suspicious lifecycle hooks with
curl,wget, oreval() - Force-published packages with
npm publish --force
- Branches named shai-hulud
- Public repositories named Shai-Hulud containing
data.json - Repositories with -migration suffix (indicating exposed private code)
- Webhook URL:
webhook.site/bb8ca5f6-4175-45d2-b042-fc9ebb8170b7 - TruffleHog filesystem scans of root directory
# GitHub Actions example
- name: Scan for npm worm
run: |
chmod +x audit-tree.sh
if ! ./audit-tree.sh . --json > scan-results.json; then
echo "::error::Potential npm worm detected!"
cat scan-results.json | jq -r '.suspicious_files[]' | while read file; do
echo "::warning file=$file::Suspicious file detected"
done
exit 1
fi# Add to cron for daily scans
0 2 * * * /path/to/audit-tree.sh /home/projects --json >> /var/log/npm-worm-scan.log 2>&1-
Immediately rotate all credentials:
- npm tokens
- GitHub personal access tokens
- Cloud provider credentials (AWS, GCP, Azure)
-
Clean infected packages:
# Remove malicious files rm -f bundle.js rm -f .github/workflows/shai-hulud-workflow.yml # Remove malicious postinstall scripts npm pkg delete scripts.postinstall
-
Audit and revert packages:
# Check npm publish history npm view <package-name> time --json # Revert to clean version npm install <package-name>@<clean-version> --save-exact
-
Review GitHub repositories:
- Delete any "Shai-Hulud" or "-migration" repositories
- Check GitHub Actions logs for data exfiltration
- Review audit logs for unauthorized access
- Enable 2FA on npm and GitHub accounts
- Use granular access tokens with minimal permissions
- Implement package publishing restrictions
- Regular dependency audits:
npm audit - Lock file verification before deployments
- Monitor for unexpected package publishes
- Uses
ripgrepwhen available for 10x faster scanning - Excludes
node_modulesand.gitdirectories by default - Single-pass file indexing minimizes disk I/O
- Efficient pattern matching with fixed strings where possible
Contributions are welcome! Please submit:
- Additional IOCs from real-world detections
- Performance improvements
- Support for additional package managers (yarn, pnpm)
- YARA/Semgrep rule equivalents
- ReversingLabs: Shai-Hulud Worm Analysis
- Kaspersky: Supply Chain Attack Details
- UpGuard: Attack Explained
MIT License - See LICENSE file for details
This tool is provided for security auditing purposes only. Always verify findings manually before taking action. The authors are not responsible for any misuse or damage caused by this tool.
Stay safe out there! π‘οΈ If this tool helped you detect an infection, please consider sharing your experience (anonymized) to help improve detection patterns.