Skip to content

Detect npm packages compromised in the Shai-Hulud 2.0 supply chain attack (Nov 2025). Scans for 790+ malicious packages, suspicious scripts, TruffleHog activity, SHA1HULUD runners, and secrets exfiltration. GitHub Action with SARIF support.

License

Notifications You must be signed in to change notification settings

gensecaihq/Shai-Hulud-2.0-Detector

Use this GitHub action with your project
Add this Action to an existing workflow or create a new one
View on Marketplace

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

13 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

GitHub Marketplace Supply Chain Security npm Protected Community Powered

Shai-Hulud 2.0 Detector

Protect your projects from the Shai-Hulud 2.0 npm supply chain attack

GitHub Marketplace β€’ Quick Start β€’ Installation β€’ Report Package β€’ Configuration


🚨 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
Batch Submission πŸ“‹ Submit Multiple Packages
Report False Positive ❌ Flag Incorrect Detection
Full Guide πŸ“– Package Database Guide

Every package you report helps protect millions of developers worldwide.


Table of Contents


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:

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@v1
        with:
          fail-on-critical: true

Step 2: Commit and Push

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:

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
TruffleHog Activity Identifies credential scanning patterns and TruffleHog downloads
Malicious Runners Detects SHA1HULUD GitHub Actions self-hosted runner references
Secrets Exfiltration Finds actionsSecrets.json files with stolen credentials
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

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

πŸ”‘ THE SUCCESS OF THIS PROJECT DEPENDS ON YOU!

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 ~2 minutes
Multiple packages πŸ“‹ Batch Submission Form ~5 minutes
False positive ❌ False Positive Form ~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:

**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 for efficiency
  2. Read the full Package Database Guide 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 Count
Total Packages 790+
Organizations 50+
Contributors Growing!
Last Updated See compromised-packages.json

πŸ“– Full Documentation: docs/PACKAGE_DATABASE.md

πŸ™ 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!

Minimal Setup

- uses: gensecaihq/Shai-Hulud-2.0-Detector@v1

Full Setup with All Options

- uses: gensecaihq/Shai-Hulud-2.0-Detector@v1
  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)

# Clone and run
git clone https://github.com/gensecaihq/Shai-Hulud-2.0-Detector.git
cd Shai-Hulud-2.0-Detector
npm install
node dist/index.js

Environment Variables for Local Use

# Set inputs via environment variables
export INPUT_FAIL-ON-CRITICAL=true
export INPUT_SCAN-LOCKFILES=true
export INPUT_OUTPUT-FORMAT=json
export INPUT_WORKING-DIRECTORY=/path/to/your/project

node dist/index.js

CI/CD Integration

GitLab CI

# .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

// 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

# 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

# .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

name: Security Scan
on: [push]

jobs:
  scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: gensecaihq/Shai-Hulud-2.0-Detector@v1

Scan Only Dependency Files

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@v1

Scheduled Daily Scans

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@v1
        with:
          fail-on-any: true

Advanced Configuration

Block PRs with Compromised Dependencies

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

- uses: gensecaihq/Shai-Hulud-2.0-Detector@v1
  with:
    fail-on-any: true

Warning Mode - Report but Don't Fail

- uses: gensecaihq/Shai-Hulud-2.0-Detector@v1
  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

- uses: gensecaihq/Shai-Hulud-2.0-Detector@v1
  with:
    working-directory: '.'
    scan-lockfiles: true

Scan Specific Package

- uses: gensecaihq/Shai-Hulud-2.0-Detector@v1
  with:
    working-directory: './packages/frontend'

Matrix Strategy for Multiple Packages

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@v1
        with:
          working-directory: './packages/${{ matrix.package }}'

SARIF Reports

Generate SARIF reports for GitHub Security tab integration:

Basic SARIF Output

- uses: gensecaihq/Shai-Hulud-2.0-Detector@v1
  with:
    output-format: sarif

- uses: github/codeql-action/upload-sarif@v4
  if: always()
  with:
    sarif_file: shai-hulud-results.sarif

Full Security Integration

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:

- 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 string 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

Environment Variables

When running locally or in non-GitHub CI systems:

Variable Maps To Example
INPUT_FAIL-ON-CRITICAL fail-on-critical input true
INPUT_FAIL-ON-HIGH fail-on-high input false
INPUT_FAIL-ON-ANY fail-on-any input false
INPUT_SCAN-LOCKFILES scan-lockfiles input true
INPUT_OUTPUT-FORMAT output-format input json
INPUT_WORKING-DIRECTORY working-directory input /app

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] [email protected] (direct)
         Location: package.json
  [CRITICAL] @asyncapi/[email protected] (transitive)
         Location: package-lock.json

------------------------------------------------------------
  Files scanned: 2
  Scan time: 67ms
  Database version: 1.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

{
  "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 790 unique packages identified in the attack:

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 508 Various community packages

Database Updates

The package database is updated when:

  • New compromised packages are identified
  • False positives are reported and verified
  • Organizations release remediated versions

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 Purpose
setup_bun.js d1829b4708126dcc7bea7437c04d1f10eacd4a16 Downloads Bun runtime
bun_environment.js d60ec97eea19fffb4809bc35b91033b52490ca11 Executes malicious payload (10MB+ obfuscated)
actionsSecrets.json - Stolen GitHub Actions secrets
cloud.json - Stores stolen cloud credentials
contents.json - Contains exfiltrated data
environment.json - Holds environment variables
truffleSecrets.json - TruffleHog scan results

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)

These workflows typically use SHA1HULUD self-hosted runners to execute malicious code.

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)

# 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

# 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 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 with details. We'll investigate and update the database.

Q: What about patched versions? A: Currently, all versions are flagged. We're working on version-specific detection.


Contributing

We welcome contributions! Here's how you can help:

Want to report a compromised package? See our detailed Package Database Contribution Guide for step-by-step instructions on submitting packages via GitHub Issues or Pull Requests.

Quick Links

Action Link
Report compromised package Package Report Issue
Report false positive False Positive Issue
Batch submission Batch Submission Issue
Contribution guide CONTRIBUTING.md
Package database guide docs/PACKAGE_DATABASE.md

Reporting Issues

Development Setup

# 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 for detailed instructions, evidence requirements, and submission templates.

Quick steps to add a package:

  1. Via GitHub Issue (Easiest):

    • Use the Package Report template
    • Fill in package details and evidence
    • Maintainers will review and add
  2. Via Pull Request (For contributors):

    # 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:

  • Aikido Security - Initial detection and detailed analysis
  • Wiz.io - Comprehensive threat investigation
  • HelixGuard - Malware analysis and IOC identification

Research & Analysis

Open Source Tools

Community

Thanks to everyone who reported affected packages, tested the detector, and helped spread awareness about this attack.


License

This project is licensed under the MIT License - see the 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

Stay safe. Protect your supply chain. πŸ›‘οΈ

⭐ Star this repo β€’ Report Bug β€’ Request Feature