Forensic scanner for Shai-Hulud 2.0 malware artifacts and compromised packages.
npm install shai-hulud-2-scanner--help for usage instructions.
scan.js to a centralized folder.
--full-scan flag:
scan.js and are recommended for CI/CD.
--depth= or --depth formats
--fail-on to enable CI/CD mode:
--fail-on=critical: Exit code 1 only on CRITICAL findings (FORENSIC_MATCH, CRITICAL_SCRIPT, VERSION_MATCH, WILDCARD_MATCH, LOCKFILE_HIT, WILDCARD_LOCK_HIT)
--fail-on=warning: Exit code 1 on CRITICAL or WARNING findings (includes SCRIPT_WARNING, GHOST_PACKAGE, CORRUPT_PACKAGE)
--fail-on=off: Always exit code 0 (report only, never fail builds)
groovy
stage('Security Scan') {
steps {
sh 'npx @cyberdracula/shai-hulud-2-scanner /path/to/project --fail-on=critical'
}
}
`
GitHub Actions Example:
`yaml
- name: Scan for Supply Chain Attacks
run: npx @cyberdracula/shai-hulud-2-scanner /path/to/project --fail-on=critical
`
GitLab CI Example:
`yaml
security_scan:
script:
- npx @cyberdracula/shai-hulud-2-scanner /path/to/project --fail-on=critical
`
> Note: Without the --fail-on flag, the scanner maintains backwards-compatible behavior (always exits 0). This ensures existing workflows are not disrupted.
$3
For companies/organizations only: If you want to centrally aggregate scan results across multiple machines, you can configure automatic report uploads:
1. Edit the configuration at the top of scan.js:
`javascript
const UPLOAD_API_URL = 'https://your-company-api.example.com/upload';
const API_KEY = 'your-secure-api-key';
`
2. Run the scan normally β reports will be uploaded automatically.
3. To disable uploads and only generate local CSV:
`bash
node scan.js --no-upload
`
> Note: By default, reports are saved locally as shai-hulud-report.csv. No data is uploaded unless you explicitly configure an API endpoint.
β
Known False Positives (Safe to Ignore)
React Native projects: contents.json files in the ios/ folder are standard iOS asset catalog files (Xcode resources), NOT malware indicators. These are safe to ignore.
----------------------------------------------------------------
Interpreting the Report (shai-hulud-report.csv)
The tool categorizes findings into different severity levels. Understanding what each means is critical for proper response.
| Finding Type | Severity | Description | Action Required |
|-------------|----------|-------------|-----------------|
| FORENSIC_MATCH | π΄ CRITICAL | High-confidence malware files (setup_bun.js, bun_environment.js, truffleSecrets.json, actionsSecrets.json, .github/workflows/discussion.yml) found with no content verification needed | β οΈ SYSTEM COMPROMISED. See emergency response steps below. |
| FORENSIC_ARTIFACT | π HIGH | Suspicious file detected (bundle.js, contents.json, cloud.json, environment.json) that matches malicious content signatures after deep inspection | Investigate file origin. If legitimate (e.g., React Native contents.json), mark as safe. Otherwise, remove immediately. |
| WILDCARD_MATCH | π΄ CRITICAL | Package matches a strict denylist where ALL versions are malicious. | β οΈ DELETE IMMEDIATELY. Follow remediation steps below. |
| CRITICAL_SCRIPT | π΄ CRITICAL | Install/preinstall/postinstall script contains high-confidence malicious behavior (e.g., piping remote code to shell, base64βsh chains, privileged Docker flags, workflow backdoor files) | β οΈ ACTION NEEDED Treat as incident: isolate host, remove package, rotate credentials, investigate lateral movement. |
| VERSION_MATCH | π HIGH | Package name and version match the known infected list | Uninstall package. Check lockfiles. Clear caches. |
| LOCKFILE_HIT | π HIGH | Malicious version is locked in package-lock.json/yarn.lock - will auto-install on every npm install | β οΈ CRITICAL FOR CI/CD. Delete lockfile, remove package, regenerate. |
| WILDCARD_LOCK_HIT | π HIGH | Lockfile contains a dependency that is known malware (any version). | Delete lockfile, remove dependency, regenerate with safe versions. |
| GHOST_PACKAGE | π‘ WARNING | Folder exists with a targeted name, but is empty/broken | Investigate manually. Likely a failed install or cleanup artifact. |
| SCRIPT_WARNING | π‘ WARNING | Install/preinstall/postinstall script has suspicious indicators (e.g., obfuscation via Buffer/Base64, dynamic Function(), GitHub API/artifact usage, nc/socat) | Review and validate script intent. If not business-critical, remove or pin safe version; open a security ticket. |
| SAFE_MATCH | π΅ INFO | Package name matches a target, but the version is safe | No action needed. Logged for audit purposes. |
> Side Note for FORENSIC_MATCH:
> This finding can sometimes generate false positives (except setup_bun.js, bun_environment.js). Please verify if the found file is expected to be present (e.g., part of your own code or a legitimate tool). If unsure, investigate the file's origin and contents before taking action.
> CSV Report Security:
> All CSV reports are sanitized to prevent formula/code injection. Sensitive data (API keys, user info) is never included in the report.
> Partial Reports:
> If the scan is interrupted, a partial report is generated with all findings up to that point.
$3
The scanner analyzes common lifecycle hooks (preinstall, install, postinstall, prepublish, prepare) and flags:
* High-confidence malicious patterns: piping remote content to shell, base64βshell chains, Docker --privileged and host mounts, workflow backdoor files
* Suspicious indicators: obfuscation via Buffer.from(..., 'hex'|'base64'), dynamic Function(...), GitHub API/artifact usage, backdoor primitives (nc, socat)
* Whitelisted safe scripts: typical tooling like tsc, node-gyp, prebuild-install, opencollective-postinstall, electron-builder install-app-deps, lerna bootstrap, nx/turbo run, esbuild
#### Indicators (What you may see in Issue_Type and Details)
The scanner emits normalized indicator tags to help triage:
* REMOTE_CODE_EXEC: Downloading or piping remote content into shell; subshell/backtick curl/wget; bash -c with network fetch
* OBFUSCATION: Base64/hex decoding, String.fromCharCode, escape sequences, packed or encoded payloads
* CODE_INJECTION: eval, Function(...), direct child_process execution, sync exec/spawn usage
* SHAI_HULUD: References to loader or payload artifacts (setup_bun, bun_environment, signature tokens)
* PERSISTENCE: CI/CD workflow backdoor files (e.g., .github/workflows/discussion.yml)
* PRIV_ESC: Docker --privileged runs or host filesystem mounts (-v /:/host)
* INSECURE_NETWORK: Plain http:// network calls in install-time scripts
* EXFIL_ATTEMPT: GitHub API interactions or Actions artifact uploads from lifecycle scripts
* BACKDOOR_PRIMITIVE: Use of nc or socat for reverse shells or listeners
$3
Your system has been compromised. The malware may have already stolen credentials.
#### 1. Immediate Actions
Windows (PowerShell):
`powershell
Stop all package managers and builds
Stop-Process -Name node, npm, yarn, pnpm -Force -ErrorAction SilentlyContinue
Clear all caches
npm cache clean --force
yarn cache clean --all
pnpm store prune
Remove-Item node_modules -Recurse -Force -ErrorAction SilentlyContinue
`
macOS/Linux (Bash):
`bash
Stop all package managers and builds
killall -9 node npm yarn pnpm 2>/dev/null
Clear all caches
npm cache clean --force
yarn cache clean --all
pnpm store prune
rm -rf node_modules
`
#### 2. Check for Backdoors
Windows (PowerShell):
`powershell
Look for malicious GitHub workflows
Get-ChildItem -Path .github\workflows -Filter "discussion.yaml" -Recurse -ErrorAction SilentlyContinue
Get-ChildItem -Path .github\workflows -Filter "formatter_*.yml" -Recurse -ErrorAction SilentlyContinue
`
macOS/Linux (Bash):
`bash
Look for malicious GitHub workflows
find .github/workflows -name "discussion.yaml" 2>/dev/null
find .github/workflows -name "formatter_*.yml" 2>/dev/null
`
Check for self-hosted runners (named "SHA1HULUD"):
Visit: https://github.com/
#### 3. Rotate ALL Credentials (Assume Breach)
The malware targets these secrets:
- GitHub: Personal Access Tokens (PATs), deploy keys, Actions secrets
- Cloud Providers: AWS credentials (AKIA keys), GCP service accounts, Azure tokens
- Package Managers: npm tokens, registry credentials
- Environment Variables: All API keys, database passwords, service tokens
- SSH Keys: Regenerate all SSH keys that were on the infected machine
#### 4. Search for Exposed Secrets
Your credentials may have been published to public GitHub repositories:
`powershell
Search GitHub for your organization's exposed data
Visit: https://github.com/search?q="Shai-Hulud"+OR+"SHA1-HULUD"+""&type=repositories
`
β οΈ Cross-Victim Exposure: Your secrets may appear in repositories owned by OTHER victims. You must search broadly.
#### 5. Clean and Rebuild
Windows (PowerShell):
`powershell
Remove lockfiles
Remove-Item package-lock.json, yarn.lock, npm-shrinkwrap.json -ErrorAction SilentlyContinue
Remove the malicious package from package.json (manually edit)
Reinstall with safe versions
npm install
Verify no malware files remain
Get-ChildItem -Recurse -Include setup_bun.js, bun_environment.js, truffleSecrets.json, cloud.json, contents.json, environment.json, actionsSecrets.json
`
macOS/Linux (Bash):
`bash
Remove lockfiles
rm -f package-lock.json yarn.lock npm-shrinkwrap.json
Remove the malicious package from package.json (manually edit)
Reinstall with safe versions
npm install
Verify no malware files remain
find . -type f \( -name "setup_bun.js" -o -name "bun_environment.js" -o -name "truffleSecrets.json" -o -name "cloud.json" -o -name "contents.json" -o -name "environment.json" -o -name "actionsSecrets.json" \)
`
#### 6. CI/CD Pipeline Review
LOCKFILE_HIT is especially dangerous in CI/CD environments:
- Malware executes during preinstall (before your code runs)
- Runs synchronously in CI (blocks until complete exfiltration)
- May attempt Docker privilege escalation
- Can modify sudoers for persistent root access
Action: Review all CI/CD logs from the past 30 days for:
- Unexpected network connections
- Failed privilege escalation attempts
- New GitHub runners registered
- Unusual workflow executions
$3
When found in both project and cache, this means:
1. Automatic Reinfection: Every npm install will reinstall the malware
2. Team-Wide Exposure: All developers who clone the repo will be infected
3. CI/CD Compromise: Every pipeline run will execute the malware
4. Container Builds: Every Docker build will be compromised
The lockfile acts as a time bomb - the malware will keep coming back until you remove it from the lockfile AND rotate all credentials.
π Updating Offline Fallback Files
The scanner includes offline fallback IOC files in the fallback/ directory. To keep them current:
`bash
node update-fallbacks.js
``