Skip to content
/ dont-be-shy-hulud Public template

πŸͺ± NPM Worm Defense Guide: Detection, remediation & prevention for Shai-Hulud 2.0 and beyond!

License

Notifications You must be signed in to change notification settings

miccy/dont-be-shy-hulud

πŸͺ± Don't Be Shy, Hulud

Don't Be Shy, Hulud Banner

Incident Response & Protection Guide for npm Supply Chain Attacks Defense guide for detection & remediation against npm supply-chain worms | Shai-Hulud 2.0 (November 2025) and future threats

npm version License: MIT GitHub release GitHub Stars PRs Welcome CodeRabbit PR Reviews

⚠️ CRITICAL: Dead Man's Switch Warning

πŸ”΄ Shai-Hulud 2.0 contains a destructive fallback mechanism!

If the malware cannot exfiltrate data or propagate (no GitHub/npm token, blocked network), it will OVERWRITE AND DELETE ALL WRITABLE FILES IN YOUR HOME DIRECTORY.

❌ DO NOT:

  • Forcefully disconnect from the internet without backup
  • Block all network traffic immediately
  • Kill suspicious processes without proper isolation

βœ… INSTEAD:

  1. Backup first β€” If possible, copy critical data before any action
  2. Selective network isolation β€” Block outbound except GitHub API
  3. Evidence collection β€” Preserve logs before cleanup
  4. Follow remediation carefully β€” See docs/REMEDIATION.md

This is not theoretical β€” the wiper code has been confirmed by multiple security researchers.


🚨 URGENT: npm Token Deadline β€” December 9, 2025

npm is revoking ALL legacy (classic) tokens on December 9, 2025 as a direct response to Shai-Hulud attacks.

Check Your Tokens Now:

npm token list

Migration Options:

Option 1: Trusted Publishing (Recommended)

# .github/workflows/publish.yml
- uses: actions/setup-node@v4
  with:
    registry-url: 'https://registry.npmjs.org'
- run: npm publish --provenance --access public
  env:
    NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

Option 2: Granular Tokens

  • Max lifetime: 90 days (default 7 days)
  • Scope to specific packages only
  • Enable IP allowlist if possible

πŸ“š npm Token Migration Guide


⚑ Quick Start

If you suspect you're compromised, run this immediately:

# One-liner β€” no installation needed
npx hulud

Or scan a specific directory:

npx hulud scan /path/to/your/project

CLI Commands

npx hulud                # Scan current directory
npx hulud scan .         # Same as above
npx hulud check          # Quick check (alias for scan .)
npx hulud scan --all     # Scan all detected dev directories
npx hulud scan --system  # Scan system locations (~/.npm, ~/.bun, etc.)
npx hulud scan --deep    # Deep scan of entire HOME (slow!)
npx hulud suspend        # Safely freeze malicious processes (SIGSTOP)
npx hulud info           # Show attack info and IOCs
npx hulud --help         # Show all options

Scan options:

  • --all β€” Auto-detect and scan Dev, Projects, Code, repos, src, workspace
  • --system β€” Scan ~/.npm, ~/.bun, ~/.config, ~/.cache, npm global
  • --deep β€” Deep scan of entire HOME directory (slow!)
  • --dry-run β€” Preview what would be scanned
  • --parallel N β€” Number of parallel jobs (default: 4)

Alternative: Clone and Run

git clone https://github.com/miccy/dont-be-shy-hulud.git
cd dont-be-shy-hulud
./scripts/detect.sh /path/to/your/project

πŸ“– Table of Contents

What is Shai-Hulud 2.0?

Shai-Hulud 2.0 (aka "The Second Coming") is a self-propagating npm worm discovered on November 24, 2025. It represents a significant evolution in supply chain attacks.

Attack Timeline

Date Event Source
Aug 27, 2025 S1ngularity/Nx GitHub token theft (precursor) Unit42
Sep 15, 2025 Shai-Hulud v1 discovered (postinstall-based) Aikido
Sep 23, 2025 CISA Advisory issued CISA
Nov 5, 2025 npm disables new classic token creation GitHub
Nov 21-23, 2025 Shai-Hulud 2.0 packages uploaded Multiple
Nov 24, 2025 03:16 UTC First detection (go-template, AsyncAPI) Wiz
Nov 24, 2025 04:11 UTC PostHog packages compromised PostHog
Nov 24, 2025 05:09 UTC Postman packages compromised Postman
Nov 24, 2025 Peak: 1,000 new repos every 30 minutes Datadog
Nov 25, 2025 800+ packages, 25,000+ repos, 1,200+ orgs, 20M+ weekly downloads Wiz, Check Point
Nov 25, 2025 Secondary phase detected ("Continued Coming") Wiz
Nov 26, 2025 GitHub reduces public malicious repos to ~300 GitHub
Dec 02, 2025 Community detection tools matured (don't-be-shy-hulud v1.5.0 released) Community
Dec 9, 2025 npm legacy token revocation deadline npm

Key Differences from v1

Feature v1 (September) v2 (November)
Execution Phase postinstall preinstall
Exfiltration Webhook endpoint GitHub repos
Runtime Node.js Bun
Fallback None Dead-man switch (wipe data)
Persistence None GitHub Actions backdoor
Propagation ~500 packages 800+ packages (20M+ downloads)

How It Works

flowchart TD
    subgraph INFECTION["1. Initial Infection"]
        A[Compromised npm package] --> B[preinstall script executes]
        B --> C[Drops setup_bun.js + bun_environment.js]
    end

    subgraph PAYLOAD["2. Payload Execution"]
        C --> D[Installs Bun runtime]
        D --> E[Runs 10MB+ obfuscated payload]
    end

    subgraph HARVEST["3. Credential Harvesting"]
        E --> F[~/.npmrc - npm tokens]
        E --> G[~/.aws, ~/.azure, ~/.config/gcloud]
        E --> H[Environment variables]
        E --> I[GitHub Actions secrets]
        E --> J[TruffleHog scan for secrets]
    end

    subgraph EXFIL["4. Exfiltration"]
        F & G & H & I & J --> K[Creates public GitHub repo]
        K --> L["Description: Sha1-Hulud: The Second Coming"]
        K --> M["Random 18-char name: [0-9a-z]{18}"]
    end

    subgraph PROPAGATE["5. Propagation"]
        L --> N[Uses stolen npm token]
        N --> O[Publishes infected versions]
        O --> P[Up to 100 packages per victim]
        P --> Q[Cross-victim token reuse]
    end

    subgraph PERSIST["6. Persistence"]
        Q --> R[GitHub Actions workflow backdoor]
        R --> S[Triggered via repository discussions]
    end

    subgraph FALLBACK["7. Dead Man's Switch"]
        T{Exfiltration blocked?}
        T -->|Yes| U[πŸ’€ Wipes user data]
        T -->|No| V[βœ… Attack continues]
    end

    S --> T
    Q --> T

    style INFECTION fill:#ff6b6b,color:#fff
    style PAYLOAD fill:#feca57,color:#000
    style HARVEST fill:#48dbfb,color:#000
    style EXFIL fill:#ff9ff3,color:#000
    style PROPAGATE fill:#54a0ff,color:#fff
    style PERSIST fill:#5f27cd,color:#fff
    style FALLBACK fill:#ee5a24,color:#fff
Loading
πŸ“‹ Text version (for terminals without Mermaid support)
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                    SHAI-HULUD 2.0 ATTACK FLOW                   β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                 β”‚
β”‚  1. INITIAL INFECTION                                           β”‚
β”‚     └── Compromised npm package with preinstall script          β”‚
β”‚         └── Drops: setup_bun.js + bun_environment.js            β”‚
β”‚                                                                 β”‚
β”‚  2. PAYLOAD EXECUTION                                           β”‚
β”‚     └── Installs Bun runtime (evades Node.js monitoring)        β”‚
β”‚         └── Runs 10MB+ obfuscated payload                       β”‚
β”‚                                                                 β”‚
β”‚  3. CREDENTIAL HARVESTING                                       β”‚
β”‚     β”œβ”€β”€ ~/.npmrc (npm tokens)                                   β”‚
β”‚     β”œβ”€β”€ ~/.aws/, ~/.azure/, ~/.config/gcloud/                   β”‚
β”‚     β”œβ”€β”€ Environment variables                                   β”‚
β”‚     β”œβ”€β”€ GitHub Actions secrets                                  β”‚
β”‚     └── TruffleHog scan for secrets in codebase                 β”‚
β”‚                                                                 β”‚
β”‚  4. EXFILTRATION                                                β”‚
β”‚     └── Creates public GitHub repo with stolen data             β”‚
β”‚         β”œβ”€β”€ Description: "Sha1-Hulud: The Second Coming"        β”‚
β”‚         └── Random 18-char name: [0-9a-z]{18}                   β”‚
β”‚                                                                 β”‚
β”‚  5. PROPAGATION                                                 β”‚
β”‚     β”œβ”€β”€ Uses stolen npm token to publish infected versions      β”‚
β”‚     β”œβ”€β”€ Up to 100 packages per victim                           β”‚
β”‚     └── Cross-victim: uses other victims' tokens                β”‚
β”‚                                                                 β”‚
β”‚  6. PERSISTENCE                                                 β”‚
β”‚     └── GitHub Actions workflow backdoor                        β”‚
β”‚         └── Triggered via repository discussions                β”‚
β”‚                                                                 β”‚
β”‚  7. FALLBACK (if blocked)                                       β”‚
β”‚     └── Dead-man switch: wipes user data                        β”‚
β”‚                                                                 β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Am I Affected?

Quick Check

# Check for IOC files
find . -name "setup_bun.js" -o -name "bun_environment.js" 2>/dev/null

# Check for malicious workflows
find . -path "*/.github/workflows/*" -name "*.yml" -exec grep -l "SHA1HULUD\|self-hosted" {} \;

# Check npm cache
npm cache ls 2>/dev/null | grep -E "(setup_bun|bun_environment)"

High-Risk Packages

If you use any of these packages, immediately audit your lockfile:

Package Risk Notes
@postman/tunnel-agent πŸ”΄ Critical 27% of environments
posthog-node πŸ”΄ Critical 25% of environments
posthog-js πŸ”΄ Critical 15% of environments
@asyncapi/specs πŸ”΄ Critical 20% of environments
@asyncapi/openapi-schema-parser πŸ”΄ Critical 17% of environments
@zapier/* πŸ”΄ Critical Multiple packages
@ensdomains/* πŸ”΄ Critical Multiple packages
@postman/postman-mcp-cli 🟠 High MCP tooling
zapier-sdk 🟠 High
angulartics2 🟠 High
koa2-swagger-ui 🟠 High
tinycolor2 🟠 High v4.1.2 specifically (note: tinycolor2, not tinycolor)
ngx-bootstrap 🟠 High Angular bootstrap components
@zapier/zapier-sdk πŸ”΄ Critical v0.15.5-0.15.7

For full IOC database with detailed indicators, see IOC Lists below and ioc/malicious-packages.json.

Immediate Actions

πŸ”΄ If Compromised

# 1. STOP - Don't run npm install on any project
# 2. Disconnect from network if possible

# 3. Check for exfiltration repos on your GitHub
# Search: https://github.com/search?q=Sha1-Hulud+user%3AYOUR_USERNAME

# 4. Revoke ALL tokens immediately
npm token revoke $(npm token ls --json | jq -r '.[].key')

# 5. Rotate credentials
# See: docs/REMEDIATION.md

🟠 Preventive (Not Yet Confirmed Compromised)

# 1. Freeze npm updates
# Add to .npmrc:
echo "ignore-scripts=true" >> ~/.npmrc

# 2. Clear caches
rm -rf node_modules
npm cache clean --force
# or for bun:
rm -rf node_modules bun.lockb
bun pm cache rm

# 3. Pin dependencies to known clean versions
# Use dates before Nov 21, 2025

Detection Scripts

Full System Scan

./scripts/detect.sh ~

Project-Only Scan

./scripts/detect.sh /path/to/project

CI/CD Integration

# .github/workflows/security-scan.yml
name: Shai-Hulud Detection
on: [push, pull_request]

jobs:
  scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Run Shai-Hulud Detector
        run: |
          curl -sSL https://raw.githubusercontent.com/miccy/dont-be-shy-hulud/main/scripts/detect.sh | bash -s -- .

Remediation Guide

See docs/REMEDIATION.md for detailed steps.

Quick Remediation

# 1. Identify affected packages
./scripts/detect.sh . --output affected.txt

# 2. Roll back to clean versions
npm install package-name@version-before-nov-21

# 3. Regenerate lockfile
rm package-lock.json
npm install --ignore-scripts

# 4. Verify
npm audit
./scripts/detect.sh .

Hardening Your Environment

npm/bun Configuration

# ~/.npmrc - Recommended settings
ignore-scripts=true
audit=true
fund=false

⚠️ Critical: Bun Users Must Read This

Bun has a known bug: The .npmrc setting ignore-scripts=true does NOT work reliably!

Bun prioritizes its internal trustedDependencies allowlist over .npmrc settings. This means lifecycle scripts may still execute even with ignore-scripts=true in your config.

❌ This is NOT reliable in Bun:

# ~/.npmrc or .npmrc
ignore-scripts=true

βœ… ALWAYS use CLI flag:

bun install --ignore-scripts

In CI/CD:

- name: Install dependencies (Bun)
  run: bun install --ignore-scripts  # REQUIRED flag

Why This Matters: Shai-Hulud 2.0 specifically installs Bun runtime as an evasion technique because most security tools only monitor Node.js processes.

Renovate Configuration

See configs/renovate-secure.json for a hardened Renovate config that:

  • Disables automerge for npm packages
  • Increases stabilityDays to 7
  • Requires security review labels
  • Blocks preinstall/postinstall changes

πŸ‘‰ For a shared preset you can use across all repos, see miccy/renovate-config:

{ "extends": ["github>miccy/renovate-config"] }

This shared preset includes:

  • 7-day stabilityDays and minimumReleaseAge
  • npm:unpublishSafe protection
  • Warnings on Shai-Hulud affected packages
  • No automerge for production dependencies

GitHub Settings

See docs/GITHUB-HARDENING.md for:

  • Branch protection rules
  • Actions security settings
  • Secret scanning configuration
  • Code scanning setup

Tool Configuration

Socket.dev

See configs/socket.yml for recommended configuration.

Dependabot

See configs/dependabot.yml for secure settings.

GitHub Actions

See docs/GITHUB-HARDENING.md for lockdown guide.

IOC Lists

Official Sources

Source URL
Datadog github.com/DataDog/indicators-of-compromise
Wiz Research wiz-sec-public/wiz-research-iocs
Tenable tenable/shai-hulud-second-coming-affected-packages
SafeDep safedep/shai-hulud-migration-response
Cobenian Cobenian/shai-hulud-detect

File IOCs

File Purpose Hash (SHA-256)
setup_bun.js Loader/dropper Various
bun_environment.js Main payload (~10MB) Various
actionsSecrets.json Exfil data (double base64) N/A
.github/workflows/formatter_*.yml Backdoor workflow N/A

Behavioral IOCs

  • GitHub repos with description: Sha1-Hulud: The Second Coming
  • GitHub repos with random 18-character names matching pattern: [0-9a-z]{18}
  • GitHub Actions runners named SHA1HULUD
  • Files: cloud.json, contents.json, environment.json, truffleSecrets.json
  • .truffler-cache directory
  • Bun installation in unexpected locations

Resources

Official Advisories

Vendor Reports

Detection Tools

πŸ’¬ Community

Have questions, found new IOCs, or want to share your experience?

Roadmap

This project is under active development. See our detailed ROADMAP.md for:

  • βœ… Completed features
  • 🚧 Work in progress
  • πŸ“‹ Planned improvements
  • 🀝 Contribution opportunities

Want to help? Pick any unchecked item from the roadmap and submit a PR!

Contributing

Contributions welcome! Please read CONTRIBUTING.md first.

Priority Areas (see ROADMAP.md for details)

  • SIGSTOP suspend script (critical for safe malware handling)
  • Expanded IOC database (800+ packages)
  • Stack-specific documentation (Expo, Bun, Tauri)
  • Network IOCs and file hashes
  • SARIF output format

πŸ› οΈ Repository Maintenance

Language Selection

This repository comes with bilingual documentation (English/Czech). To keep only one language:

# Keep only English (removes cs/ folder)
./scripts/set-language.sh en

# Keep only Czech (promotes cs/ files to root)
./scripts/set-language.sh cs

You can also do this via GitHub Actions: Go to Actions -> Set Repository Language -> Run workflow.

VS Code Integration

This project includes VS Code tasks. Press Cmd+Shift+P -> Tasks: Run Task to easily run:

  • πŸ›‘οΈ Quick Audit
  • πŸ” Full Audit
  • 🧹 Set Language

License

MIT License - See LICENSE for details.


πŸ™ Credits

This guide compiles research from multiple security teams:

  • Aikido Security (initial detection)
  • Socket.dev, Datadog, Wiz, GitLab, Palo Alto Networks Unit 42
  • GitGuardian, SafeDep, Tenable
  • The broader security community

Stay safe. Rotate your secrets. Pin your dependencies. πŸ›‘οΈ


πŸ›  Built by @miccy out of hatred for Worms 🀬