A Bash tool that helps you spot known traces of the September 2025 through March 2026 npm supply-chain attacks—including the Shai-Hulud self-replicating worm, the chalk/debug crypto-theft incident, the "Shai-Hulud: The Second Coming" fake Bun runtime attack, the February 2026 SANDWORM_MODE campaign, and the March 2026 axios supply chain compromise. It cross-checks 1,703+ confirmed bad package versions across multiple campaigns and checks for the most relevant red flags in your project.
Covers multiple npm supply chain attacks from September 2025 through March 2026:
- Scope: 18+ packages with 2+ billion weekly downloads
- Attack: Cryptocurrency wallet address replacement in browsers
- Duration: ~2 hours before detection
- Packages: chalk, debug, ansi-styles, color-, supports-, and others
- Method: XMLHttpRequest hijacking to steal crypto transactions
- Scope: 517+ packages across multiple namespaces
- Attack: Credential harvesting and self-propagation
- Method: Uses Trufflehog to scan for secrets, publishes stolen data to GitHub
- Propagation: Self-replicates using stolen npm tokens
- Packages: @ctrl/, @crowdstrike/, @operato/*, and many others
- Scope: 300+ packages with millions of weekly downloads
- Attack: Fake Bun runtime installation with credential harvesting
- Method: Uses fake
setup_bun.jspreinstall hook to download and execute TruffleHog - Exfiltration: Creates GitHub Actions runners named "SHA1HULUD" and repositories with "Sha1-Hulud: The Second Coming" descriptions
- Packages: @zapier/, @posthog/, @asyncapi/, @postman/, @ensdomains/*, and many others
- Files:
setup_bun.js,bun_environment.js(10MB+ obfuscated payload),actionsSecrets.json(double Base64 encoded) - Workflow:
.github/workflows/formatter_*.ymlfiles using SHA1HULUD runners
- Scope: Continuation of Second Coming attack with renamed files
- Attack: Same fake Bun runtime technique with obfuscated file names
- Method: Uses
bun_installer.jsandenvironment_source.js(renamed fromsetup_bun.jsandbun_environment.js) - Exfiltration: Obfuscated JSON files for staging stolen credentials:
3nvir0nm3nt.json,cl0vd.json,c9nt3nts.json,pigS3cr3ts.json - Packages: @vietmoney/react-big-calendar (versions 0.26.0-0.26.2)
- Repo Description: "Goldox-T3chs: Only Happy Girl"
- Scope: 19 confirmed malicious npm packages + workflow propagation IoCs
- Attack: Typosquatted AI toolchain packages and poisoned CI workflow distribution
- Method: Malicious GitHub Action
ci-quality/code-quality-check@v1injects.github/workflows/quality.yml - Threat actor aliases:
official334,javaorg - Packages:
claud-code,cloude-code,cloude,opencraw,veim,yarsg, and others - Source: Socket.dev analysis
- Scope: Compromised axios maintainer account publishes malicious versions with RAT dropper
- Attack: Injected
plain-crypto-jsdependency delivers cross-platform Remote Access Trojan - Method: Postinstall hook runs obfuscated
setup.jsthat drops platform-specific RAT; beacons every 60s - C2:
sfrclak.com(142.11.206.73:8000) - Packages:
axios@1.14.1,axios@0.30.4,plain-crypto-js@4.2.1 - Attacker accounts:
nrwise(nrwise@proton.me), hijackedjasonsaayman(ifstap@proton.me) - Anti-forensics: Dropper overwrites its own package.json version from 4.2.1 to 4.2.0
- Source: StepSecurity analysis
# Clone the repository
git clone https://github.com/Cobenian/shai-hulud-detect
cd shai-hulud-detect
# Make the script executable
chmod +x shai-hulud-detector.sh
# Scan your project for Shai-Hulud indicators
./shai-hulud-detector.sh /path/to/your/project
# For comprehensive security scanning
./shai-hulud-detector.sh --paranoid /path/to/your/project
# Save findings to a log file for review or CI/CD artifacts
./shai-hulud-detector.sh --save-log report.log /path/to/your/project
# Check exit code for CI/CD integration
./shai-hulud-detector.sh /path/to/your/project
echo "Exit code: $?" # 0=clean, 1=high-risk, 2=medium-riskCI/CD Integration: The script returns appropriate exit codes (0=clean, 1=high-risk, 2=medium-risk) for seamless integration into automated security pipelines.
- Malicious workflow files:
shai-hulud-workflow.ymlfiles in.github/workflows/(September 2025),formatter_*.ymlfiles using SHA1HULUD runners (November 2025), and SANDWORM_MODE workflow IoCs includingci-quality/code-quality-check@v1and poisonedquality.ymlworkflow references (February 2026) - Known malicious file hashes: Files matching any of 7 SHA-256 hashes from different Shai-Hulud worm variants (V1-V7), sourced from Socket.dev's comprehensive attack analysis
- November 2025 Bun attack files:
setup_bun.js/bun_installer.js(fake Bun runtime installer) andbun_environment.js/environment_source.js(10MB+ obfuscated credential harvesting payload) - Obfuscated exfiltration files:
3nvir0nm3nt.json,cl0vd.json,c9nt3nts.json,pigS3cr3ts.json(Golden Path variant - stolen credentials staged for exfiltration) - Compromised package versions: Specific versions of 1,703+ packages from multiple attacks (September 2025 through March 2026)
- Suspicious postinstall hooks: Package.json files with postinstall scripts containing curl, wget, eval commands, or fake Bun installation (
"preinstall": "node setup_bun.js") - Trufflehog activity: Files containing trufflehog references, credential scanning patterns, or November 2025 enhanced patterns (automated TruffleHog download and execution)
- Shai-Hulud repositories: Git repositories named "Shai-Hulud" (used for data exfiltration) or with "Sha1-Hulud: The Second Coming" or "Goldox-T3chs: Only Happy Girl" descriptions
- Secrets exfiltration files:
actionsSecrets.jsonfiles with double Base64 encoded credentials (November 2025) - SHA1HULUD GitHub Actions runners: GitHub Actions workflows using malicious runners for credential theft
- SANDWORM_MODE workflow IoCs: Workflow files containing
ci-quality/code-quality-check@v1, actor aliases (official334,javaorg), or related propagation module references - Axios supply chain attack IoCs: C2 domain
sfrclak.com/ IP142.11.206.73, XOR keyOrDeR_7077,plain-crypto-jsdependency (malicious RAT dropper), and filesystem persistence artifacts (March 2026)
- Suspicious content patterns: References to
webhook.siteand the malicious endpointbb8ca5f6-4175-45d2-b042-fc9ebb8170b7 - Suspicious git branches: Branches named "shai-hulud"
- Semver pattern matching: Packages that could become compromised during
npm updatedue to caret (^) or tilde (~) version patterns
- Namespace warnings: Packages from namespaces known to be affected (@ctrl, @crowdstrike, @art-ws, @ngx, @nativescript-community) but at safe versions
The script loads a list of the compromised packages from an external file (compromised-packages.txt) which contains:
- 1,703+ confirmed compromised package versions with exact version numbers (September 2025 through March 2026 campaigns)
- 18+ affected namespaces for broader detection of packages from compromised maintainer accounts
Important: The Shai-Hulud attack was self-replicating, meaning new compromised packages may still be discovered. The compromised packages list is stored in compromised-packages.txt for easy maintenance:
- Format:
package_name:version(one per line) - Comments: Lines starting with
#are ignored - Updates: The file can be updated as new compromised packages are discovered
- Fallback: If the file is missing, the script uses a core embedded list
Check these security advisories regularly for newly discovered compromised packages:
- StepSecurity Blog - Original comprehensive analysis
- Semgrep Security Advisory - Detailed technical analysis
- JFrog Security Research - Ongoing detection of new packages
- Wiz Security Blog - Attack analysis with package appendix
- Socket.dev Blog - CrowdStrike package analysis
- Socket.dev Blog - SANDWORM_MODE AI toolchain poisoning campaign
- HelixGuard - Second Coming analysis
- StepSecurity Blog - March 2026 axios supply chain compromise
- Check the security advisories above for new compromised packages
- Add them to
compromised-packages.txtin the formatpackage_name:version - Test the script to ensure detection works
- Consider contributing updates back to this repository
Coverage Note: Multiple campaigns from September 2025 through March 2026 affected 1,703+ packages total. Our detection aims to provide comprehensive coverage across the Shai-Hulud worm (517+ packages), Chalk/Debug crypto theft (26+ packages), "Shai-Hulud: The Second Coming" fake Bun runtime attack (1,100+ packages), the Golden Path variant, the February 2026 SANDWORM_MODE campaign, and the March 2026 axios supply chain compromise.
Core Mode (Default)
- Focuses specifically on Shai-Hulud attack indicators
- Recommended for most users checking for this specific threat
- Clean, focused output with minimal false positives
Paranoid Mode (--paranoid)
- Includes all core Shai-Hulud detection PLUS additional security checks
- Adds typosquatting detection and network exfiltration pattern analysis
- Important: Paranoid features are general security tools, not specific to Shai-Hulud
- May produce more false positives from legitimate code
- Useful for comprehensive security auditing
Semver Range Checking (--check-semver-ranges)
- Checks if package.json semver ranges (^, ~) could resolve to compromised versions
- Reports LOW risk in both cases (informational warning about latent risk)
- Useful for identifying latent risk in private npm caches that may still have malicious versions
- macOS or Unix-like system
- Bash 5.0 or newer (required for associative arrays and performance features)
- macOS:
brew install bashthen run with/opt/homebrew/bin/bash ./shai-hulud-detector.sh - Linux: Most modern distributions include Bash 5.x by default
- Check your version:
bash --version
- macOS:
- Standard Unix tools:
find,grep,shasum
The script automatically selects the fastest available grep tool in this priority order:
- git grep (default) - Uses a DFA-based regex engine with no backtracking, fastest for our patterns (~40% faster than ripgrep)
- ripgrep (fallback) - Also DFA-based, excellent performance
- grep (last resort) - May experience catastrophic backtracking on complex patterns
You can override the auto-selection with flags:
--use-git-grep- Force git grep--use-ripgrep- Force ripgrep--use-grep- Force standard grep
Why git grep is default: Our testing shows git grep is ~40% faster than ripgrep on large codebases. Both use DFA-based regex engines that avoid the catastrophic backtracking that causes standard grep to hang on complex patterns.
✅ No indicators of Shai-Hulud compromise detected.
Your system appears clean from this specific attack.
The script will show:
- 🚨 HIGH RISK: Definitive indicators of compromise
⚠️ MEDIUM RISK: Suspicious patterns requiring manual review- Summary: Count of issues found
- Immediate action required
- Update or remove compromised packages
- Review and remove malicious workflow files
- Scan for credential theft
- Consider full system audit
- Manual investigation needed
- Review flagged files for legitimacy
- Check if webhook.site usage is intentional
- Verify git branch purposes
The script returns specific exit codes to enable proper CI/CD pipeline integration:
- Exit Code 0: Clean system - no significant security findings
- Exit Code 1: High-risk findings detected - immediate action required
- Exit Code 2: Medium-risk findings detected - manual investigation needed
- name: Security Scan with Shai-Hulud Detector
run: |
chmod +x ./shai-hulud-detector.sh
./shai-hulud-detector.sh .
# Pipeline will automatically fail on exit codes 1 or 2security_scan:
script:
- chmod +x ./shai-hulud-detector.sh
- ./shai-hulud-detector.sh .
# Job fails automatically on non-zero exit codesstage('Security Scan') {
steps {
sh '''
chmod +x ./shai-hulud-detector.sh
./shai-hulud-detector.sh .
'''
}
// Build fails automatically on non-zero exit codes
}#!/bin/bash
./shai-hulud-detector.sh .
exit_code=$?
case $exit_code in
0) echo "✅ Security scan passed - no issues found" ;;
1) echo "🚨 CRITICAL: High-risk security issues found - blocking deployment"
exit 1 ;;
2) echo "⚠️ WARNING: Medium-risk issues found - review required"
# Could choose to continue with warnings
;;
esacUse --save-log FILE to save all detected file paths to a structured log file:
./shai-hulud-detector.sh --save-log findings.log /path/to/projectThe log file contains file paths grouped by severity level:
# HIGH
/path/to/malicious-workflow.yml
/path/to/compromised-package.json
# MEDIUM
/path/to/suspicious-content.js
# LOW
/path/to/namespace-warning.json
This format is designed for:
- CI/CD artifacts: Store scan results as build artifacts for review
- Programmatic parsing: Easy to parse with simple scripts
- Full coverage: Includes ALL findings without display truncation
The repository includes a comprehensive test suite with 32 test cases. Use the automated test runner to validate all cases:
# Run the full test suite (recommended)
./run-tests.sh
# The test suite validates expected exit codes and risk levels for all test cases
# Exit codes: 0=clean, 1=high-risk, 2=medium-riskYou can also run individual test cases manually:
# Test on clean project (should show no issues)
./shai-hulud-detector.sh test-cases/clean-project
# Test on infected project (should show multiple issues)
./shai-hulud-detector.sh test-cases/infected-project
# Test November 2025 "Shai-Hulud: The Second Coming" attack (should show HIGH risk for all new patterns)
./shai-hulud-detector.sh test-cases/november-2025-attack
# Test on mixed project (should show medium risk issues)
./shai-hulud-detector.sh test-cases/mixed-project
# Test namespace warnings (should show LOW risk namespace warnings only)
./shai-hulud-detector.sh test-cases/namespace-warning
# Test semver matching (should show MEDIUM risk for packages that could match compromised versions)
./shai-hulud-detector.sh test-cases/semver-matching
# Test legitimate crypto libraries (should show MEDIUM risk only)
./shai-hulud-detector.sh test-cases/legitimate-crypto
# Test chalk/debug attack patterns (should show HIGH risk compromised packages + MEDIUM risk crypto patterns)
./shai-hulud-detector.sh test-cases/chalk-debug-attack
# Test common crypto libraries (should not trigger HIGH risk false positives)
./shai-hulud-detector.sh test-cases/common-crypto-libs
# Test legitimate XMLHttpRequest modifications (should show LOW risk only)
./shai-hulud-detector.sh test-cases/xmlhttp-legitimate
# Test malicious XMLHttpRequest with crypto patterns (should show HIGH risk crypto theft + MEDIUM risk XMLHttpRequest patterns)
./shai-hulud-detector.sh test-cases/xmlhttp-malicious
# Test lockfile false positive (should show no issues despite other package having compromised version)
./shai-hulud-detector.sh test-cases/lockfile-false-positive
# Test actual compromised package in lockfile (should show HIGH risk)
./shai-hulud-detector.sh test-cases/lockfile-compromised
# Test packages with safe lockfile versions (should show LOW risk with lockfile protection message)
./shai-hulud-detector.sh test-cases/lockfile-safe-versions
# Test mixed lockfile scenario (should show HIGH risk for compromised + LOW risk for safe)
./shai-hulud-detector.sh test-cases/lockfile-comprehensive-test
# Test packages without lockfile (should show MEDIUM risk for potential update risks)
./shai-hulud-detector.sh test-cases/no-lockfile-test
# Test typosquatting detection with paranoid mode (should show MEDIUM risk typosquatting warnings)
./shai-hulud-detector.sh --paranoid test-cases/typosquatting-project
# Test network exfiltration detection with paranoid mode (should show HIGH risk credential harvesting + MEDIUM risk network patterns)
./shai-hulud-detector.sh --paranoid test-cases/network-exfiltration-project
# Test clean project with paranoid mode (should show no issues - verifies no false positives)
./shai-hulud-detector.sh --paranoid test-cases/clean-project
# Test semver wildcard parsing (should correctly handle 4.x, 1.2.x patterns without errors)
./shai-hulud-detector.sh test-cases/semver-wildcards
# Test discussion workflow detection (should show CRITICAL risk for malicious discussion-triggered workflows)
./shai-hulud-detector.sh test-cases/discussion-workflows
# Test SANDWORM_MODE workflow IOC detection (should show HIGH risk for poisoned ci-quality action usage)
./shai-hulud-detector.sh test-cases/sandworm-mode-workflow
# Test axios supply chain attack IOC detection (should show HIGH risk for C2, XOR key, plain-crypto-js)
./shai-hulud-detector.sh test-cases/axios-attack
# Test GitHub Actions runner detection (should show CRITICAL risk for SHA1HULUD self-hosted runners)
./shai-hulud-detector.sh test-cases/github-actions-runners
# Test file hash verification (should validate benign files against malicious hashes)
./shai-hulud-detector.sh test-cases/hash-verification
# Test destructive pattern detection (should show CRITICAL risk for data destruction commands)
./shai-hulud-detector.sh test-cases/destructive-patternsThe --paranoid flag enables additional security checks beyond Shai-Hulud-specific detection:
- Typosquatting Detection: Identifies packages with names similar to popular packages (e.g., "raect" instead of "react", "lodsh" instead of "lodash")
- Network Exfiltration Patterns: Detects suspicious domains (webhook.site, pastebin.com), hardcoded IP addresses, WebSocket connections to external endpoints
- Enhanced Security Auditing: Useful for comprehensive project security reviews
Note: Paranoid mode may produce more false positives from legitimate code patterns, so review findings carefully.
The script performs these checks:
- Package Database Loading: Loads 1,703+ compromised packages from
compromised-packages.txtinto O(1) lookup maps - Workflow Detection: Searches for
shai-hulud-workflow.ymlfiles (September 2025),formatter_*.ymlfiles with SHA1HULUD runners (November 2025), SANDWORM_MODE workflow IoCs (February 2026), and axios supply chain attack IoCs (March 2026) - Hash Verification: Calculates SHA-256 hashes against 7 known malicious bundle.js variants (V1-V7)
- Package Analysis: Parses
package.jsonfiles for compromised versions and affected namespaces - Semver Range Checking (opt-in with
--check-semver-ranges): Checks if version ranges could resolve to compromised versions - Postinstall Hook Detection: Identifies suspicious postinstall/preinstall scripts containing curl, wget, eval, or fake Bun patterns
- Content Scanning: Searches for suspicious URLs, webhook endpoints, and malicious patterns
- Cryptocurrency Theft Detection: Identifies wallet replacement patterns, XMLHttpRequest hijacking, and crypto theft functions
- Trufflehog Activity Detection: Looks for credential scanning tools and secret harvesting patterns
- Git Analysis: Checks for suspicious branch names ("shai-hulud")
- Repository Detection: Identifies "Shai-Hulud", "Second Coming", and "Goldox-T3chs" repository patterns
- November 2025 Bun Attack Detection: Identifies
setup_bun.js/bun_installer.jsandbun_environment.js/environment_source.jsattack files - GitHub Actions Runner Detection: Identifies malicious SHA1HULUD runners
- Discussion Workflow Detection: Identifies workflows that trigger on discussion events (stealth persistence)
- Destructive Payload Detection: Identifies destructive fallback patterns (
rm -rf,fs.rmSync, etc.) - Lockfile Integrity Checking: Analyzes package-lock.json, yarn.lock, and pnpm-lock.yaml for compromised packages
- Typosquatting Detection (paranoid mode): Identifies packages with names similar to popular packages
- Network Exfiltration Detection (paranoid mode): Detects suspicious domains and hardcoded IPs
- Obfuscated Exfiltration Detection: Identifies Golden Path variant staging files (
3nvir0nm3nt.json,cl0vd.json, etc.)
- Hash Detection: Only detects files with exact matches to the 7 known malicious hashes
- Package Versions: Detects specific compromised versions; new variants may not be detected until the package list is updated
- False Positives: Legitimate use of webhook.site, Trufflehog, or postinstall hooks may trigger alerts
- Worm Evolution: New variants may emerge with different signatures
- Semver Ranges: The
--check-semver-rangesflag is informational only; compromised versions are largely unpublished from npm
This script is for detection only. It does not:
- Automatically remove malicious code
- Fix compromised packages
- Prevent future attacks
Always verify findings manually and take appropriate remediation steps.
- StepSecurity Blog: CTRL, tinycolor and 40 NPM packages compromised
- JFrog: New compromised packages in largest npm attack in history
- Aikido: NPM debug and chalk packages compromised
- Semgrep Security Advisory: NPM packages using secret scanning tools to steal credentials
- Aikido: S1ngularity-nx attackers strike again
- Aikido: Shai-Hulud strikes again - The Golden Path
- Socket: Ongoing supply chain attack targets CrowdStrike npm packages
- Ox Security: NPM 2.0 hack: 40+ npm packages hit in major supply chain attack
- Phoenix Security: NPM tinycolor compromise
We welcome contributions to improve any of the code, documentation, tests and packages covered.
-
Fork the repository on GitHub, then clone your fork:
git clone https://github.com/YOUR_USERNAME/shai-hulud-detect.git cd shai-hulud-detect -
Update the package list
- Add new packages to
compromised-packages.txtin the formatpackage_name:version - Include a source/reference for where you found the compromised package
- Add new packages to
-
Test your changes
./run-tests.sh # All 37 tests should pass -
Submit a Pull Request
- Push to your fork and open a PR against the upstream repository
- Include the source of the information (security advisory, blog post, etc.)
- Bug fixes: Report and fix issues with detection accuracy
- New IoCs: Add detection for additional indicators of compromise
- Documentation: Improve clarity and add examples
- Test cases: Add new test scenarios for edge cases
- Verify sources: Only add packages confirmed by reputable security firms
- Test thoroughly: Ensure changes don't break existing functionality
- Document changes: Update relevant documentation and changelog
- Follow patterns: Match existing code style and organization
- Security first: Never include actual malicious code in test cases
If you can't submit a PR, you can still help by reporting new compromised packages:
- Open an issue with the title "New compromised package: [package-name]"
- Include the package name, version, and source of information
- Provide links to security advisories or reports
- We'll review and add verified packages to the detection list
For a complete list of changes and version history, see the CHANGELOG.md.
This project is licensed under the MIT License - see the LICENSE file for details.
