UNPKG

tops-bmad

Version:

CLI tool to install BMAD workflow files into any project with integrated Shai-Hulud 2.0 security scanning

1,336 lines (1,031 loc) 48.7 kB
<p align="center"> <a href="https://github.com/marketplace/actions/shai-hulud-2-0-detector"><img src="https://img.shields.io/badge/GitHub%20Marketplace-Available-2ea44f?style=for-the-badge&logo=github" alt="GitHub Marketplace"></a> <img src="https://img.shields.io/badge/Supply%20Chain-Security-red?style=for-the-badge" alt="Supply Chain Security"> <img src="https://img.shields.io/badge/npm-Protected-green?style=for-the-badge&logo=npm" alt="npm Protected"> <img src="https://img.shields.io/badge/Community-Powered-orange?style=for-the-badge&logo=opensourceinitiative" alt="Community Powered"> </p> <h1 align="center">Shai-Hulud 2.0 Detector</h1> <p align="center"> <strong>Protect your projects from the Shai-Hulud 2.0 npm supply chain attack</strong> </p> <p align="center"> <a href="https://github.com/marketplace/actions/shai-hulud-2-0-detector">GitHub Marketplace</a><a href="#quick-start">Quick Start</a><a href="#installation">Installation</a><a href="#-help-us-protect-the-community">Report Package</a><a href="#configuration">Configuration</a> </p> --- > ## 🚨 Found a Compromised Package? Report It! > > **This project's effectiveness depends on community contributions.** If you discover a compromised package, please report it immediately: > > | Action | Link | > |--------|------| > | **Report Package** | [📦 Submit Package Report](https://github.com/gensecaihq/Shai-Hulud-2.0-Detector/issues/new?template=package-report.yml) | > | **Batch Submission** | [📋 Submit Multiple Packages](https://github.com/gensecaihq/Shai-Hulud-2.0-Detector/issues/new?template=batch-submission.yml) | > | **Report False Positive** | [❌ Flag Incorrect Detection](https://github.com/gensecaihq/Shai-Hulud-2.0-Detector/issues/new?template=false-positive.yml) | > | **Full Guide** | [📖 Package Database Guide](docs/PACKAGE_DATABASE.md) | > > **Every package you report helps protect millions of developers worldwide.** --- ## Table of Contents - [About the Attack](#about-the-attack) - [Quick Start](#quick-start) - [Detection Capabilities](#detection-capabilities) - [**Help Us Protect the Community**](#-help-us-protect-the-community) ⭐ - [Installation](#installation) - [GitHub Action (Recommended)](#github-action-recommended) - [Local CLI Usage](#local-cli-usage) - [CI/CD Integration](#cicd-integration) - [Usage Guide](#usage-guide) - [Basic Scanning](#basic-scanning) - [Advanced Configuration](#advanced-configuration) - [Monorepo Support](#monorepo-support) - [SARIF Reports](#sarif-reports) - [Using Action Outputs](#using-action-outputs) - [Configuration](#configuration) - [Inputs Reference](#inputs-reference) - [Outputs Reference](#outputs-reference) - [Environment Variables](#environment-variables) - [Supported File Types](#supported-file-types) - [Understanding Results](#understanding-results) - [Affected Packages Database](#affected-packages-database) - [Automated Daily Updates](#automated-daily-updates) - [Why Version Precision Matters](#why-version-precision-matters) - [Indicators of Compromise](#indicators-of-compromise) - [Incident Response Guide](#incident-response-guide) - [FAQ](#faq) - [Contributing](#contributing) - [Acknowledgments](#acknowledgments) - [Thanks](#thanks) - [License](#license) --- ## About the Attack On **November 24, 2025**, a sophisticated supply chain attack dubbed **"Shai-Hulud 2.0"** (also known as "The Second Coming") compromised the npm ecosystem in one of the largest coordinated attacks on open-source software. ### Attack Statistics | Metric | Value | |--------|-------| | Compromised Packages | **790+** unique packages | | Monthly Downloads Affected | **132+ million** | | Malicious GitHub Repos Created | **25,000+** | | Compromised GitHub Users | **350+** | | Attack Start Time | Nov 24, 2025 03:16 GMT | ### Major Organizations Affected - **Zapier** - Integration platform - **ENS Domains** - Ethereum Name Service - **PostHog** - Product analytics - **AsyncAPI** - API specification - **Postman** - API development - **Voiceflow** - Conversational AI - **BrowserBase** - Browser automation - **Oku UI** - Vue components ### How the Attack Works ``` ┌─────────────────────────────────────────────────────────────────┐ │ ATTACK FLOW DIAGRAM │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ 1. npm install 2. preinstall hook 3. Download │ │ ───────────────► ─────────────────────► ──────────────────► │ │ setup_bun.js Bun runtime │ │ │ │ 4. Execute payload 5. Credential theft 6. Exfiltrate │ │ ───────────────────► ──────────────────► ─────────────────► │ │ bun_environment.js TruffleHog scan GitHub repos │ │ │ │ 7. Self-propagate 8. Create runner 9. Destroy │ │ ────────────────────► ─────────────────► ─────────────────► │ │ Infect 100+ pkgs "SHA1HULUD" Wipe on failure │ │ │ └─────────────────────────────────────────────────────────────────┘ ``` **Detailed Attack Steps:** 1. **Package Installation** - Victim runs `npm install` with compromised dependency 2. **Lifecycle Hook Execution** - `preinstall` or `postinstall` script triggers 3. **Bun Runtime Download** - `setup_bun.js` downloads the Bun JavaScript runtime 4. **Payload Execution** - `bun_environment.js` runs the malicious payload 5. **Credential Harvesting** - Uses TruffleHog to scan for exposed secrets 6. **Data Exfiltration** - Uploads stolen credentials to attacker-controlled GitHub repos 7. **Self-Propagation** - Attempts to infect up to 100 additional npm packages 8. **Persistence** - Creates self-hosted GitHub runners named "SHA1HULUD" 9. **Destructive Failsafe** - Wipes home directory if authentication fails --- ## Quick Start Get protected in **under 2 minutes**: ### Step 1: Create Workflow File Create `.github/workflows/shai-hulud-check.yml` in your repository: ```yaml name: Shai-Hulud 2.0 Security Check on: push: branches: [main, master] pull_request: branches: [main, master] jobs: security-check: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: gensecaihq/Shai-Hulud-2.0-Detector@v2 with: fail-on-critical: true ``` ### Step 2: Commit and Push ```bash git add .github/workflows/shai-hulud-check.yml git commit -m "Add Shai-Hulud 2.0 security scanning" git push ``` ### Step 3: Check Results View scan results in the Actions tab of your repository. --- ## Detection Capabilities This detector goes beyond simple package name matching to provide comprehensive threat detection: ### Precise Version Matching The detector uses **semver (semantic versioning)** to accurately identify only the specific vulnerable versions of each package: ``` Example: kill-port package ├── kill-port@2.0.1 → ✅ SAFE (not affected) ├── kill-port@2.0.2 → ❌ COMPROMISED └── kill-port@2.0.3 → ❌ COMPROMISED ``` This significantly reduces false positives by: - Matching exact versions listed in the compromised database - Supporting semver ranges (e.g., `>=1.0.0 <2.0.0`) - Properly handling version constraints from lockfiles ### Critical Risk Detection | Check | Description | |-------|-------------| | **Compromised Packages** | Scans against database of 790+ known compromised packages | | **Malicious Scripts** | Detects `setup_bun.js`, `bun_environment.js` in postinstall/preinstall hooks | | **SHA256 Hash Matching** | 🆕 Verifies file hashes against known malware signatures from Datadog IOC database | | **TruffleHog Activity** | Identifies credential scanning patterns and TruffleHog downloads | | **Malicious Runners** | Detects SHA1HULUD GitHub Actions self-hosted runner references | | **Runner Installation** | 🆕 Finds `.dev-env/` directories and runner tarballs used by the attack | | **Workflow Triggers** | 🆕 Detects `on: discussion` workflow triggers used for command injection backdoors | | **Secrets Exfiltration** | Finds `actionsSecrets.json`, `truffleSecrets.json`, `cloud.json`, `environment.json` files | | **Shai-Hulud Repos** | Identifies git remotes/repos named "Shai-Hulud" | ### Medium Risk Detection | Check | Description | |-------|-------------| | **Webhook Exfiltration** | Detects `webhook.site` endpoints and known malicious UUIDs | | **Suspicious Branches** | Flags git branches named "shai-hulud" | | **Dangerous Scripts** | Identifies `curl|sh`, `wget|sh`, `eval`, base64 decode patterns | ### Low Risk Detection | Check | Description | |-------|-------------| | **Namespace Warnings** | Alerts on packages from affected namespaces (@ctrl, @asyncapi, etc.) with semver ranges | ### Disclaimer > **This tool is for DETECTION purposes only.** It does not: > - Automatically remove or quarantine malicious code > - Patch, fix, or remediate compromised packages > - Prevent future supply chain attacks > - Guarantee detection of all compromised packages > > All findings should be manually verified. Take appropriate remediation steps including credential rotation, dependency updates, and forensic analysis. --- ## 🌍 Help Us Protect the Community <p align="center"> <strong>🔑 THE SUCCESS OF THIS PROJECT DEPENDS ON YOU!</strong> </p> The Shai-Hulud 2.0 attack is evolving, and new compromised packages are being discovered regularly. **Our crowdsourced package database is only as good as the community that maintains it.** ### Why Your Contribution Matters ``` ┌─────────────────────────────────────────────────────────────────┐ │ │ │ YOU DISCOVER ───► YOU REPORT ───► WE ADD IT │ │ a bad package via GitHub to database │ │ │ │ │ │ │ ▼ │ │ │ │ MILLIONS OF ◄─── DETECTOR ◄─── REPOS ARE │ │ devs protected scans projects now protected │ │ │ └─────────────────────────────────────────────────────────────────┘ ``` ### How to Report Packages | What You Found | How to Report | Time Required | |----------------|---------------|---------------| | **Single compromised package** | [📦 Package Report Form](https://github.com/gensecaihq/Shai-Hulud-2.0-Detector/issues/new?template=package-report.yml) | ~2 minutes | | **Multiple packages** | [📋 Batch Submission Form](https://github.com/gensecaihq/Shai-Hulud-2.0-Detector/issues/new?template=batch-submission.yml) | ~5 minutes | | **False positive** | [❌ False Positive Form](https://github.com/gensecaihq/Shai-Hulud-2.0-Detector/issues/new?template=false-positive.yml) | ~2 minutes | ### What Makes a Good Report? **Minimum evidence needed** (at least one): - ✅ Package contains `setup_bun.js` or `bun_environment.js` - ✅ File hash matches known malicious hash - ✅ Suspicious `postinstall` script that downloads external code - ✅ Published during attack window (Nov 24, 2025) - ✅ Security advisory from npm/GitHub - ✅ Analysis from security researcher ### Quick Report Template Found a bad package? Copy this to create an issue: ```markdown **Package:** @scope/package-name **npm:** https://www.npmjs.com/package/@scope/package-name **Severity:** critical **Evidence:** - [ ] Contains setup_bun.js - [ ] Contains bun_environment.js - [ ] Suspicious postinstall script - [ ] Other: [describe] **How I found it:** [Your discovery method] ``` ### For Security Researchers If you're doing systematic analysis and finding multiple packages: 1. **Use our [Batch Submission Form](https://github.com/gensecaihq/Shai-Hulud-2.0-Detector/issues/new?template=batch-submission.yml)** for efficiency 2. **Read the full [Package Database Guide](docs/PACKAGE_DATABASE.md)** for detailed instructions 3. **Consider submitting a PR** directly to `compromised-packages.json` for faster integration 4. **We'll credit you** in our acknowledgments! ### Database Statistics | Metric | Value | |--------|-------| | Total Packages | **795+** | | Data Sources | **7 security vendors** | | Update Frequency | **Daily (automated)** | | Version Precision | **Specific versions only** | | Last Updated | See `compromised-packages.json` | > **📖 Full Documentation:** [docs/PACKAGE_DATABASE.md](docs/PACKAGE_DATABASE.md) > > **🔄 Auto-Updated:** Database syncs daily from [Datadog Consolidated IOCs](https://github.com/DataDog/indicators-of-compromise/tree/main/shai-hulud-2.0) > > **🙏 Thank you to everyone who contributes. Together, we're making npm safer for everyone.** --- ## Installation ### GitHub Action (Recommended) The easiest way to use Shai-Hulud Detector is as a GitHub Action. **Now available on the [GitHub Marketplace](https://github.com/marketplace/actions/shai-hulud-2-0-detector)!** #### Minimal Setup ```yaml - uses: gensecaihq/Shai-Hulud-2.0-Detector@v2 ``` #### Full Setup with All Options ```yaml - uses: gensecaihq/Shai-Hulud-2.0-Detector@v2 with: fail-on-critical: true fail-on-high: false fail-on-any: false scan-lockfiles: true scan-node-modules: false output-format: text working-directory: '.' ``` ### Local CLI Usage You can also run the detector locally for development or CI systems without GitHub Actions: #### Using npx (No Installation) ```bash # Clone and run git clone https://github.com/gensecaihq/Shai-Hulud-2.0-Detector.git cd Shai-Hulud-2.0-Detector npm install npm run build ``` #### Set Options There are two ways to set the options, either via CLI arguments or by setting environment variables. ❗Make sure to add the working directory option to the path of the project you want to scan. All other options are set to the below defaults and thus optional. Set the `--working-directory="/path/to/your/project"` flag when running the script or set the `INPUT_WORKING_DIRECTORY="/path/to/your/project"` environment variable like listed below. ##### Via CLI arguments (option 1) ```bash node dist/index.js --working-directory="/path/to/your/project" [options] Options: --fail-on-critical=true --fail-on-high=false --fail-on-any=false --scan-lockfiles=true --scan-node-modules=false --output-format="json" --working-directory="/path/to/your/project" ``` ##### Via Environment Variables (option 2) **Bash** ```bash export INPUT_FAIL_ON_CRITICAL=true export INPUT_FAIL_ON_HIGH=false export INPUT_FAIL_ON_ANY=false export INPUT_SCAN_LOCKFILES=true export INPUT_SCAN_NODE_MODULES=false export INPUT_OUTPUT_FORMAT="json" export INPUT_WORKING_DIRECTORY="/path/to/your/project" node dist/index.js ``` **Powershell** ```powershell $Env:INPUT_FAIL_ON_CRITICAL="true" $Env:INPUT_FAIL_ON_HIGH="false" $Env:INPUT_FAIL_ON_ANY="false" $Env:INPUT_SCAN_LOCKFILES="true" $Env:INPUT_SCAN_NODE_MODULES="true" $Env:INPUT_OUTPUT_FORMAT="json" $Env:INPUT_WORKING_DIRECTORY="/path/to/your/project" node dist/index.js ``` ### CI/CD Integration #### GitLab CI ```yaml # .gitlab-ci.yml shai-hulud-scan: image: node:20 stage: test script: - git clone https://github.com/gensecaihq/Shai-Hulud-2.0-Detector.git /tmp/detector - cd /tmp/detector && npm ci - | export INPUT_FAIL_ON_CRITICAL=true export INPUT_WORKING_DIRECTORY=$CI_PROJECT_DIR node /tmp/detector/dist/index.js only: changes: - package.json - package-lock.json - yarn.lock ``` #### Jenkins Pipeline ```groovy // Jenkinsfile pipeline { agent any stages { stage('Security Scan') { steps { sh ''' git clone https://github.com/gensecaihq/Shai-Hulud-2.0-Detector.git /tmp/detector cd /tmp/detector && npm ci export INPUT_FAIL_ON_CRITICAL=true export INPUT_WORKING_DIRECTORY=${WORKSPACE} node /tmp/detector/dist/index.js ''' } } } } ``` #### Azure DevOps ```yaml # azure-pipelines.yml trigger: paths: include: - package.json - package-lock.json pool: vmImage: 'ubuntu-latest' steps: - task: NodeTool@0 inputs: versionSpec: '20.x' - script: | git clone https://github.com/gensecaihq/Shai-Hulud-2.0-Detector.git /tmp/detector cd /tmp/detector && npm ci export INPUT_FAIL_ON_CRITICAL=true export INPUT_WORKING_DIRECTORY=$(Build.SourcesDirectory) node /tmp/detector/dist/index.js displayName: 'Shai-Hulud Security Scan' ``` #### CircleCI ```yaml # .circleci/config.yml version: 2.1 jobs: security-scan: docker: - image: cimg/node:20.0 steps: - checkout - run: name: Shai-Hulud Security Scan command: | git clone https://github.com/gensecaihq/Shai-Hulud-2.0-Detector.git /tmp/detector cd /tmp/detector && npm ci export INPUT_FAIL_ON_CRITICAL=true export INPUT_WORKING_DIRECTORY=$(pwd) node /tmp/detector/dist/index.js workflows: main: jobs: - security-scan ``` --- ## Usage Guide ### Basic Scanning #### Scan on Every Push ```yaml name: Security Scan on: [push] jobs: scan: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: gensecaihq/Shai-Hulud-2.0-Detector@v2 ``` #### Scan Only Dependency Files ```yaml name: Security Scan on: push: paths: - '**/package.json' - '**/package-lock.json' - '**/yarn.lock' - '**/pnpm-lock.yaml' pull_request: paths: - '**/package.json' - '**/package-lock.json' - '**/yarn.lock' - '**/pnpm-lock.yaml' jobs: scan: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: gensecaihq/Shai-Hulud-2.0-Detector@v2 ``` #### Scheduled Daily Scans ```yaml name: Daily Security Scan on: schedule: - cron: '0 0 * * *' # Run at midnight UTC workflow_dispatch: # Allow manual trigger jobs: scan: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: gensecaihq/Shai-Hulud-2.0-Detector@v2 with: fail-on-any: true ``` ### Advanced Configuration #### Block PRs with Compromised Dependencies ```yaml name: PR Security Gate on: pull_request: types: [opened, synchronize, reopened] jobs: security-gate: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Scan for Shai-Hulud 2.0 id: scan uses: gensecaihq/Shai-Hulud-2.0-Detector@v1 with: fail-on-critical: true fail-on-high: true - name: Comment on PR if affected if: failure() uses: actions/github-script@v7 with: script: | github.rest.issues.createComment({ issue_number: context.issue.number, owner: context.repo.owner, repo: context.repo.repo, body: '## ⚠️ Security Alert: Shai-Hulud 2.0 Attack Detected\n\nThis PR contains dependencies compromised in the Shai-Hulud 2.0 supply chain attack.\n\n**Action Required:** Remove or update the affected packages before merging.' }) ``` #### Strict Mode - Fail on Any Detection ```yaml - uses: gensecaihq/Shai-Hulud-2.0-Detector@v2 with: fail-on-any: true ``` #### Warning Mode - Report but Don't Fail ```yaml - uses: gensecaihq/Shai-Hulud-2.0-Detector@v2 with: fail-on-critical: false fail-on-high: false fail-on-any: false ``` ### Monorepo Support The detector automatically scans subdirectories for package files (up to 5 levels deep). #### Scan Entire Monorepo ```yaml - uses: gensecaihq/Shai-Hulud-2.0-Detector@v2 with: working-directory: '.' scan-lockfiles: true ``` #### Scan Specific Package ```yaml - uses: gensecaihq/Shai-Hulud-2.0-Detector@v2 with: working-directory: './packages/frontend' ``` #### Matrix Strategy for Multiple Packages ```yaml jobs: scan: runs-on: ubuntu-latest strategy: matrix: package: [frontend, backend, shared, cli] steps: - uses: actions/checkout@v4 - uses: gensecaihq/Shai-Hulud-2.0-Detector@v2 with: working-directory: './packages/${{ matrix.package }}' ``` ### SARIF Reports Generate SARIF reports for GitHub Security tab integration: #### Basic SARIF Output ```yaml - uses: gensecaihq/Shai-Hulud-2.0-Detector@v2 with: output-format: sarif - uses: github/codeql-action/upload-sarif@v4 if: always() with: sarif_file: shai-hulud-results.sarif ``` #### Full Security Integration ```yaml name: Security Analysis on: [push, pull_request] jobs: analyze: runs-on: ubuntu-latest permissions: security-events: write contents: read steps: - uses: actions/checkout@v4 - name: Shai-Hulud Scan uses: gensecaihq/Shai-Hulud-2.0-Detector@v1 with: output-format: sarif fail-on-critical: false # Don't fail, just report - name: Upload to GitHub Security uses: github/codeql-action/upload-sarif@v4 if: always() with: sarif_file: shai-hulud-results.sarif category: shai-hulud-detector ``` ### Using Action Outputs Access scan results for conditional logic or notifications: ```yaml - name: Run Scan id: scan uses: gensecaihq/Shai-Hulud-2.0-Detector@v1 with: fail-on-critical: false output-format: json - name: Process Results run: | echo "Status: ${{ steps.scan.outputs.status }}" echo "Affected packages: ${{ steps.scan.outputs.affected-count }}" echo "Scan time: ${{ steps.scan.outputs.scan-time }}ms" - name: Send Slack Notification if: steps.scan.outputs.status == 'affected' uses: slackapi/slack-github-action@v1 with: payload: | { "text": "⚠️ Shai-Hulud 2.0 Alert: ${{ steps.scan.outputs.affected-count }} compromised packages detected in ${{ github.repository }}" } env: SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }} ``` --- ## Configuration ### Inputs Reference | Input | Description | Type | Default | |-------|-------------|------|---------| | `fail-on-critical` | Fail workflow if critical severity packages are found | `boolean` | `true` | | `fail-on-high` | Fail workflow if high or critical severity packages are found | `boolean` | `false` | | `fail-on-any` | Fail workflow if any compromised packages are found | `boolean` | `false` | | `scan-lockfiles` | Scan lockfiles for transitive dependencies | `boolean` | `true` | | `scan-node-modules` | Scan node_modules directory (slower, more thorough) | `boolean` | `false` | | `output-format` | Output format: `text`, `json`, or `sarif` | `'text' \| 'json' \| 'sarif'` | `text` | | `working-directory` | Directory to scan (relative to repository root) | `string` | `.` | ### Outputs Reference | Output | Description | Example | |--------|-------------|---------| | `affected-count` | Number of compromised packages detected | `3` | | `security-findings-count` | Number of security findings (scripts, runners, etc.) | `2` | | `status` | Overall scan status | `clean` or `affected` | | `scan-time` | Scan duration in milliseconds | `156` | | `results` | JSON array of detected packages | `[{"package":"posthog-node",...}]` | | `security-findings` | JSON array of security findings | `[{"type":"suspicious-script",...}]` | | `sarif-file` | Path to generated SARIF file (when output-format is sarif) | `shai-hulud-results.sarif` | ### CLI Arguments When running locally or in non-GitHub CI systems: | Variable | Maps To | Type | Default |----------|---------|---------|---------| | `--fail-on-critical` | `fail-on-critical` input | `boolean` | `true` | | `--fail-on-high` | `fail-on-high` input | `boolean` | `false` | | `--fail-on-any` | `fail-on-any` input | `boolean` | `false` | | `--scan-lockfiles` | `scan-lockfiles` input | `boolean` | `true` | | `--scan-node-modules` | `scan-node-modules` input | `boolean` | `false` | | `--output-format` | `output-format` input | `'text' \| 'json' \| 'sarif'` | `text` | | `--working-directory` | `working-directory` input | `string` | `.` | ### Environment Variables When running locally or in non-GitHub CI systems: | Variable | Maps To | Type | Default |----------|---------|---------|---------| | `INPUT_FAIL_ON_CRITICAL` | `fail-on-critical` input | `boolean` | `true` | | `INPUT_FAIL_ON_HIGH` | `fail-on-high` input | `boolean` | `false` | | `INPUT_FAIL_ON_ANY` | `fail-on-any` input | `boolean` | `false` | | `INPUT_SCAN_LOCKFILES` | `scan-lockfiles` input | `boolean` | `true` | | `INPUT_SCAN_NODE_MODULES` | `scan-node-modules` input | `boolean` | `false` | | `INPUT_OUTPUT_FORMAT` | `output-format` input | `'text' \| 'json' \| 'sarif'` | `text` | | `INPUT_WORKING_DIRECTORY` | `working-directory` input | `string` | `.` | --- ## Supported File Types | File | Format | Direct Deps | Transitive Deps | |------|--------|-------------|-----------------| | `package.json` | JSON | ✅ | ❌ | | `package-lock.json` | JSON (v1, v2, v3) | ✅ | ✅ | | `yarn.lock` | Yarn custom format | ❌ | ✅ | | `npm-shrinkwrap.json` | JSON | ✅ | ✅ | | `pnpm-lock.yaml` | YAML | 🚧 Coming soon | 🚧 | --- ## Understanding Results ### Output Formats #### Text Output (Default) ``` ============================================================ SHAI-HULUD 2.0 SUPPLY CHAIN ATTACK DETECTOR ============================================================ STATUS: AFFECTED (2 package(s) found) AFFECTED PACKAGES: ------------------------------------------------------------ [CRITICAL] posthog-node@5.13.3 (direct) Location: package.json [CRITICAL] @asyncapi/parser@3.4.2 (transitive) Location: package-lock.json ------------------------------------------------------------ Files scanned: 2 Scan time: 67ms Database version: 2.0.0 ============================================================ IMMEDIATE ACTIONS REQUIRED: 1. Do NOT run npm install until packages are updated 2. Rotate all credentials (npm, GitHub, AWS, etc.) 3. Check for unauthorized GitHub self-hosted runners named "SHA1HULUD" 4. Audit GitHub repos for "Shai-Hulud: The Second Coming" description ``` #### JSON Output ```json { "totalDependencies": 150, "affectedCount": 2, "cleanCount": 148, "results": [ { "package": "posthog-node", "version": "5.13.3", "severity": "critical", "isDirect": true, "location": "package.json" }, { "package": "@asyncapi/parser", "version": "3.4.2", "severity": "critical", "isDirect": false, "location": "package-lock.json" } ], "scannedFiles": ["package.json", "package-lock.json"], "scanTime": 67 } ``` ### Severity Levels | Level | Description | Action | |-------|-------------|--------| | **CRITICAL** | Confirmed compromised package from the attack | Remove immediately | | **HIGH** | Suspected compromised or related package | Investigate and remove | | **MEDIUM** | Package from affected organization | Monitor closely | | **LOW** | Potentially related package | Review when possible | ### Direct vs Transitive - **Direct**: Package is listed in your `package.json` - **Transitive**: Package is a dependency of one of your dependencies --- ## Affected Packages Database The detector includes a database of **795+ unique packages** identified in the attack, with **precise version matching** to minimize false positives. | Organization | Count | Key Packages | |--------------|-------|--------------| | AsyncAPI | 36 | `@asyncapi/cli`, `@asyncapi/parser`, `@asyncapi/generator` | | PostHog | 62 | `posthog-node`, `posthog-js`, `@posthog/nextjs`, `@posthog/plugin-server` | | ENS Domains | 46 | `@ensdomains/ensjs`, `@ensdomains/thorin`, `@ensdomains/ui` | | Zapier | 16 | `zapier-platform-core`, `zapier-platform-cli`, `@zapier/ai-actions` | | Voiceflow | 57 | `@voiceflow/common`, `@voiceflow/sdk-runtime`, `@voiceflow/api-sdk` | | Postman | 17 | `@postman/tunnel-agent`, `@postman/mcp-server`, `@postman/csv-parse` | | BrowserBase | 7 | `@browserbasehq/stagehand`, `@browserbasehq/mcp`, `@browserbasehq/sdk-functions` | | Oku UI | 41 | `@oku-ui/primitives`, `@oku-ui/dialog`, `@oku-ui/toast` | | Others | 513 | Various community packages | ### Automated Daily Updates The package database is **automatically updated daily** from the [Datadog Consolidated IOCs](https://github.com/DataDog/indicators-of-compromise/tree/main/shai-hulud-2.0), which aggregates data from **7 security vendors**: | Source | Description | |--------|-------------| | **[Datadog Security Labs](https://securitylabs.datadoghq.com)** | SHA256 hash IOCs & malware analysis | | **[Wiz](https://www.wiz.io)** | Threat investigation & attack analysis | | **[HelixGuard](https://helixguard.ai)** | Malware analysis and IOC identification | | **[ReversingLabs](https://www.reversinglabs.com)** | Software supply chain security | | **[Socket.dev](https://socket.dev)** | npm security monitoring | | **[StepSecurity](https://www.stepsecurity.io)** | GitHub Actions security | | **[Koi Security](https://koi.security)** | Supply chain threat intelligence | ### How Updates Work ``` ┌─────────────────────────────────────────────────────────────────┐ │ DAILY UPDATE PROCESS │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ 00:00 UTC Fetch consolidated Parse CSV & │ │ Daily ────► IOCs from Datadog ────► extract versions ────► │ │ │ │ Update Create PR Merge │ │ ──► compromised- ────► for review ────► (after approval) │ │ packages.json │ │ │ └─────────────────────────────────────────────────────────────────┘ ``` - **Automated Workflow**: Runs daily at 00:00 UTC via GitHub Actions - **Manual Trigger**: Can be triggered manually via workflow dispatch - **PR-based Updates**: Changes create a Pull Request for review before merging - **Version Precision**: Only specific compromised versions are flagged (no wildcards) ### Why Version Precision Matters Previous versions flagged ALL versions of a package. Now only specific compromised versions are detected: ``` Example: @asyncapi/parser ├── @asyncapi/parser@3.4.0 → ✅ SAFE (published Oct 2024, pre-attack) ├── @asyncapi/parser@3.4.1 → ❌ COMPROMISED (attack version) └── @asyncapi/parser@3.4.2 → ❌ COMPROMISED (attack version) ``` This eliminates false positives for: - Pre-attack versions (published before Nov 24, 2025) - Post-remediation clean versions ### Manual Database Update To manually trigger a database update: ```bash # Via GitHub Actions UI # Go to Actions → "Update IOC Database" → Run workflow # Or locally node scripts/update-ioc-database.js ``` Check `compromised-packages.json` for the full list with version information. --- ## Indicators of Compromise ### Malicious Files If you find these files in your project or `node_modules`, you may be compromised: | File | SHA-1 Hash | SHA-256 Hash | Purpose | |------|------------|--------------|---------| | `setup_bun.js` | `d1829b47...` | `a3894003ad1d293ba96d77881ccd2071...` | Downloads Bun runtime | | `bun_environment.js` | `d60ec97e...` | Multiple variants (6+ hashes) | Executes malicious payload (10MB+ obfuscated) | | `actionsSecrets.json` | - | - | Stolen GitHub Actions secrets (double Base64 encoded) | | `trufflehog_output.json` | - | - | TruffleHog credential scan results | | `cloud.json` | - | - | Stores stolen cloud credentials | | `contents.json` | - | - | Contains exfiltrated data | | `environment.json` | - | - | Holds environment variables | | `truffleSecrets.json` | - | - | TruffleHog scan results | ### Runner Installation Artifacts The attack installs rogue GitHub Actions runners. Check for: | Artifact | Location | Description | |----------|----------|-------------| | `.dev-env/` | `$HOME/.dev-env/` | Runner installation directory | | `actions-runner-linux-x64-2.330.0.tar.gz` | Various | Specific runner version used by attack | | `.config/gcloud/application_default_credentials.json` | `$HOME/` | Targeted credential file | | `.npmrc` | `$HOME/` | Targeted npm credentials | ### Malicious Workflows Check `.github/workflows/` for these suspicious patterns: | Pattern | Description | |---------|-------------| | `discussion.yaml` or `discussion.yml` | Injected workflow for remote execution | | `formatter_*.yml` | Malicious workflow with random suffix (e.g., `formatter_abc123.yml`) | | `on: discussion` trigger | Command injection backdoor trigger (🆕 v2.0.0) | These workflows typically use `SHA1HULUD` self-hosted runners to execute malicious code. **New in v2.0.0:** The detector now scans workflow files for `on: discussion` triggers, which are used by the attack to create command injection backdoors that persist even after the initial infection is cleaned. ### GitHub Indicators Search your organization for: - Self-hosted runners named `SHA1HULUD` - Repositories with description containing `Shai-Hulud: The Second Coming` --- ## Incident Response Guide ### If You're Affected #### Immediate Actions (First 15 Minutes) 1. **STOP** - Do not run `npm install` or any build commands 2. **Isolate** - Disconnect affected systems from network if possible 3. **Document** - Note timestamps, affected systems, and what was run 4. **Alert** - Notify your security team #### Containment (First Hour) ```bash # 1. Check for malicious files find ./node_modules -name "setup_bun.js" -o -name "bun_environment.js" # 2. Check for malicious workflows ls -la .github/workflows/ | grep -E "(discussion|formatter_)" # 3. Check for unauthorized runners (requires gh CLI) gh api repos/{owner}/{repo}/actions/runners --jq '.runners[].name' | grep -i sha1hulud ``` #### Credential Rotation Checklist | Service | Action | Priority | |---------|--------|----------| | npm | Revoke and regenerate tokens | 🔴 Critical | | GitHub | Rotate PATs, OAuth tokens, App keys | 🔴 Critical | | AWS | Rotate access keys, invalidate sessions | 🔴 Critical | | GCP | Rotate service account keys | 🔴 Critical | | Azure | Regenerate service principal credentials | 🔴 Critical | | Docker Hub | Reset access tokens | 🟡 High | | Database | Change passwords, rotate connection strings | 🟡 High | | Third-party APIs | Regenerate API keys | 🟡 High | | SSH | Regenerate keys if stored in repo | 🟠 Medium | #### Clean Installation ```bash # 1. Remove existing node_modules rm -rf node_modules package-lock.json # 2. Clear npm cache npm cache clean --force # 3. Audit package.json manually # Remove any compromised packages # 4. Fresh install with audit npm install --ignore-scripts # Prevent postinstall hooks npm audit # 5. Run security scan npx gensecaihq/Shai-Hulud-2.0-Detector ``` --- ## FAQ ### General Questions **Q: Is this a real attack?** A: Yes. The Shai-Hulud 2.0 attack occurred on November 24, 2025, and compromised hundreds of npm packages. **Q: How do I know if I'm affected?** A: Run this detector on your project. If it reports affected packages, you may have been compromised. **Q: What if I already ran npm install?** A: Follow the [Incident Response Guide](#incident-response-guide) immediately. Assume credentials are compromised. ### Technical Questions **Q: Does this scan my actual code?** A: No. It only scans `package.json`, lockfiles, and optionally `node_modules` for known compromised package names. **Q: Will this slow down my CI/CD?** A: No. Typical scan time is under 100ms. The detector is optimized for speed. **Q: Does this work with private registries?** A: Yes. The detector reads local files and doesn't need registry access. **Q: Can I use this with Yarn 2/3 (Berry)?** A: Yarn Classic lockfiles are supported. Yarn Berry (PnP) support is coming soon. ### False Positives **Q: What if a package is flagged incorrectly?** A: [Open an issue](https://github.com/gensecaihq/Shai-Hulud-2.0-Detector/issues) with details. We'll investigate and update the database. **Q: What about patched versions?** A: The detector uses semver matching to flag only specific compromised versions. Safe versions of a package are not flagged. Check `compromised-packages.json` for version details. --- ## Contributing We welcome contributions! Here's how you can help: > **Want to report a compromised package?** See our detailed [Package Database Contribution Guide](docs/PACKAGE_DATABASE.md) for step-by-step instructions on submitting packages via GitHub Issues or Pull Requests. ### Quick Links | Action | Link | |--------|------| | Report compromised package | [Package Report Issue](https://github.com/gensecaihq/Shai-Hulud-2.0-Detector/issues/new?template=package-report.yml) | | Report false positive | [False Positive Issue](https://github.com/gensecaihq/Shai-Hulud-2.0-Detector/issues/new?template=false-positive.yml) | | Batch submission | [Batch Submission Issue](https://github.com/gensecaihq/Shai-Hulud-2.0-Detector/issues/new?template=batch-submission.yml) | | Contribution guide | [CONTRIBUTING.md](CONTRIBUTING.md) | | Package database guide | [docs/PACKAGE_DATABASE.md](docs/PACKAGE_DATABASE.md) | ### Reporting Issues - **Compromised Packages**: Use the [Package Report](https://github.com/gensecaihq/Shai-Hulud-2.0-Detector/issues/new?template=package-report.yml) template - **False Positives**: Use the [False Positive](https://github.com/gensecaihq/Shai-Hulud-2.0-Detector/issues/new?template=false-positive.yml) template - **Multiple Packages**: Use the [Batch Submission](https://github.com/gensecaihq/Shai-Hulud-2.0-Detector/issues/new?template=batch-submission.yml) template - **Bugs**: Open an issue with reproduction steps ### Development Setup ```bash # 1. Fork and clone git clone https://github.com/YOUR_USERNAME/Shai-Hulud-2.0-Detector.git cd Shai-Hulud-2.0-Detector # 2. Install dependencies npm install # 3. Make changes to src/ # 4. Build npm run build # 5. Test locally export INPUT_WORKING_DIRECTORY=/path/to/test/project node dist/index.js ``` ### Pull Request Process 1. Fork the repository 2. Create a feature branch (`git checkout -b feature/amazing-feature`) 3. Make your changes 4. Run `npm run build` to compile 5. Test your changes 6. Commit (`git commit -m 'Add amazing feature'`) 7. Push (`git push origin feature/amazing-feature`) 8. Open a Pull Request ### Code Style - TypeScript with strict mode - Use meaningful variable names - Add comments for complex logic - Follow existing patterns in the codebase ### Updating Package Database > **Full Guide:** See [docs/PACKAGE_DATABASE.md](docs/PACKAGE_DATABASE.md) for detailed instructions, evidence requirements, and submission templates. **Quick steps to add a package:** 1. **Via GitHub Issue** (Easiest): - Use the [Package Report](https://github.com/gensecaihq/Shai-Hulud-2.0-Detector/issues/new?template=package-report.yml) template - Fill in package details and evidence - Maintainers will review and add 2. **Via Pull Request** (For contributors): ```bash # Fork and clone the repo git checkout -b add-package/package-name # Edit compromised-packages.json - add to packages array: { "name": "@scope/package-name", "severity": "critical", "affectedVersions": ["*"] } # Build and submit npm run build git commit -am "feat(db): add @scope/package-name" git push && gh pr create ``` **Evidence required:** At least one of - malicious file found, hash match, suspicious script, security advisory, or maintainer compromise confirmation. --- ## Acknowledgments ### Security Researchers This project builds on the excellent work of security researchers who identified and analyzed the Shai-Hulud 2.0 attack: | Organization | GitHub | Contribution | |-------------|--------|--------------| | **[Wiz](https://www.wiz.io)** | [@wiz-sec](https://github.com/wiz-sec) | Comprehensive threat investigation & aftermath analysis | | **[Datadog Security Labs](https://securitylabs.datadoghq.com)** | [@DataDog](https://github.com/DataDog) | SHA256 hash IOCs & detailed malware analysis | | **[Aikido Security](https://www.aikido.dev)** | [@AikidoSec](https://github.com/AikidoSec) | Initial detection and package database | | **[Postman](https://www.postman.com)** | [@postmanlabs](https://github.com/postmanlabs) | Post-mortem analysis & package response | | **[PostHog](https://posthog.com)** | [@PostHog](https://github.com/PostHog) | Attack timeline & incident response | | **[HelixGuard](https://helixguard.ai)** | [@helixguard](https://github.com/helixguard) | Malware analysis and IOC identification | ### Research & Analysis - [Wiz.io - Shai-Hulud 2.0 Investigation](https://www.wiz.io/blog/shai-hulud-2-0-ongoing-supply-chain-attack) - [Wiz.io - Shai-Hulud 2.0 Aftermath Analysis](https://www.wiz.io/blog/shai-hulud-2-0-aftermath-ongoing-supply-chain-attack) - [Datadog Security Labs - npm Worm Analysis](https://securitylabs.datadoghq.com/articles/shai-hulud-2.0-npm-worm/) - [Datadog IOC Repository](https://github.com/DataDog/indicators-of-compromise/tree/main/shai-hulud-2.0) - [Aikido Security - Shai-Hulud Strikes Again](https://www.aikido.dev/blog/shai-hulud-strikes-again-hitting-zapier-ensdomains) - [Postman Engineering - npm Supply Chain Attack](https://blog.postman.com/engineering/shai-hulud-2-0-npm-supply-chain-attack/) - [PostHog - Attack Post-Mortem](https://posthog.com/blog/nov-24-shai-hulud-attack-post-mortem) - [HelixGuard - Malicious SHA1HULUD Analysis](https://helixguard.ai/blog/malicious-sha1hulud-2025-11-24) ### Open Source Tools - [GitHub Actions](https://github.com/features/actions) - CI/CD platform - [ncc](https://github.com/vercel/ncc) - TypeScript compilation - [TruffleHog](https://github.com/trufflesecurity/trufflehog) - Secret scanning (used by attackers, ironic) ### Community Thanks to everyone who reported affected packages, tested the detector, and helped spread awareness about this attack. --- ## Thanks A huge thank you to all the community members who have contributed to this project through code, issue reports, and discussions: | | Contributor | Contributions | |---|-------------|---------------| | <img src=https://github.com/albe.png width=32 height=32 alt=@albe> | [@albe](https://github.com/albe) | Code contributions, Pull requests | | <img src=https://github.com/alokemajumder.png width=32 height=32 alt=@alokemajumder> | [@alokemajumder](https://github.com/alokemajumder) | Code contributions, Issue reports, Pull requests | | <img src=https://github.com/buggedcom.png width=32 height=32 alt=@buggedcom> | [@buggedcom](https://github.com/buggedcom) | Discussions | | <img src=https://github.com/gaellafond.png width=32 height=32 alt=@gaellafond> | [@gaellafond](https://github.com/gaellafond) | Issue reports | | <img src=https://github.com/Gaurav0.png width=32 height=32 alt=@Gaurav0> | [@Gaurav0](https://github.com/Gaurav0) | Issue reports | | <img src=https://github.com/jeis4wpi.png width=32 height=32 alt=@jeis4wpi> | [@jeis4wpi](https://github.com/jeis4wpi) | Issue reports | | <img src=https://github.com/julia-infocaster.png width=32 height=32 alt=@julia-infocaster> | [@julia-infocaster](https://github.com/julia-infocaster) | Code contributions, Pull requests | | <img src=https://github.com/linhungsam.png width=32 height=32 alt=@linhungsam> | [@linhungsam](https://github.com/linhungsam) | Discussions | | <img src=https://github.com/luca-cond.png width=32 height=32 alt=@luca-cond> | [@luca-cond](https://github.com/luca-cond) | Discussions | | <img src=https://github.com/maxie7.png width=32 height=32 alt=@maxie7> | [@maxie7](https://github.com/maxie7) | Code contributions, Discussions, Pull requests | | <img src=https://github.com/sampov2.png width=32 height=32 alt=@sampov2> | [@sampov2](https://github.com/sampov2) | Discussions | | <img src=https://github.com/seezee.png width=32 height=32 alt=@seezee> | [@seezee](https://github.com/seezee) | Issue reports | | <img src=https://github.com/topsinfonimesh.png width=32 height=32 alt=@topsinfonimesh> | [@topsinfonimesh](https://github.com/topsinfonimesh) | Discussions | Your contributions help protect millions of developers worldwide. 🙏 *This section is automatically updated weekly.* --- ## License This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details. ``` MIT License Copyright (c) 2025 gensecaihq Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ``` --- ## Security Policy ### Reporting Vulnerabilities If you discover a security vulnerability in this detector tool itself, please report it responsibly: 1. **Do NOT** open a public issue 2. Email security concerns to the maintainers 3. Allow 48 hours for initial response 4. Coordinate disclosure timeline ### Scope This tool is for **defensive security purposes only**. It: - Detects known compromised packages - Does NOT guarantee detection of all variants - Does NOT protect against future attacks - Should be used alongside other security measures --- <p align="center"> <strong>Stay safe. Protect your supply chain. 🛡️</strong> </p> <p align="center"> <a href="https://github.com/gensecaihq/Shai-Hulud-2.0-Detector">⭐ Star this repo</a><a href="https://github.com/gensecaihq/Shai-Hulud-2.0-Detector/issues">Report Bug</a><a href="https://github.com/gensecaihq/Shai-Hulud-2.0-Detector/issues">Request Feature</a> </p>