gensecaihq/Shai-Hulud-2.0-Detector
GitHub: gensecaihq/Shai-Hulud-2.0-Detector
针对Shai-Hulud 2.0供应链攻击的专项检测工具,精准识别790余个被篡改的npm包及恶意凭证窃取脚本。
Stars: 121 | Forks: 34
Shai-Hulud 2.0 检测器
保护您的项目免受 Shai-Hulud 2.0 npm 供应链攻击
GitHub Marketplace • 快速开始 • 安装 • 报告软件包 • 配置
## 目录 - [关于攻击](#about-the-attack) - [快速开始](#quick-start) - [检测能力](#detection-capabilities) - [**帮助我们保护社区**](#-help-us-protect-the-community) ⭐ - [安装](#installation) - [GitHub Action(推荐)](#github-action-recommended) - [本地 CLI 使用](#local-cli-usage) - [CI/CD 集成](#cicd-integration) - [使用指南](#usage-guide) - [基础扫描](#basic-scanning) - [高级配置](#advanced-configuration) - [Monorepo 支持](#monorepo-support) - [SARIF 报告](#sarif-reports) - [使用 Action 输出](#using-action-outputs) - [配置](#configuration) - [输入参考](#inputs-reference) - [输出参考](#outputs-reference) - [环境变量](#environment-variables) - [支持的文件类型](#supported-file-types) - [理解结果](#understanding-results) - [受影响软件包数据库](#affected-packages-database) - [自动化每日更新](#automated-daily-updates) - [为什么版本精确性很重要](#why-version-precision-matters) - [入侵指标](#indicators-of-compromise) - [事件响应指南](#incident-response-guide) - [常见问题](#faq) - [贡献](#contributing) - [致谢](#acknowledgments) - [感谢](#thanks) - [许可证](#license) ## 关于攻击 在 **2025 年 11 月 24 日**,一场名为 **"Shai-Hulud 2.0"**(也称为 "The Second Coming")的复杂供应链攻击入侵了 npm 生态系统,这是针对开源软件的最大规模协同攻击之一。 ### 攻击统计 | 指标 | 数值 | |--------|-------| | 被入侵的软件包 | **790+** 个独立软件包 | | 受影响的月下载量 | **1.32 亿+** | | 创建的恶意 GitHub 仓库 | **25,000+** | | 被入侵的 GitHub 用户 | **350+** | | 攻击开始时间 | 2025 年 11 月 24 日 03:16 GMT | ### 受影响的主要组织 - **Zapier** - 集成平台 - **ENS Domains** - 以太坊域名服务 - **PostHog** - 产品分析 - **AsyncAPI** - API 规范 - **Postman** - API 开发 - **Voiceflow** - 对话式 AI - **BrowserBase** - 浏览器自动化 - **Oku UI** - Vue 组件 ### 攻击如何运作 ``` ┌─────────────────────────────────────────────────────────────────┐ │ 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 │ │ │ └─────────────────────────────────────────────────────────────────┘ ``` **详细攻击步骤:** 1. **软件包安装** - 受害者运行带有受感染依赖项的 `npm install` 2. **生命周期钩子执行** - `preinstall` 或 `postinstall` 脚本被触发 3. **Bun 运行时下载** - `setup_bun.js` 下载 Bun JavaScript 运行时 4. **Payload 执行** - `bun_environment.js` 运行恶意 Payload 5. **凭证窃取** - 使用 TruffleHog 扫描暴露的密钥 6. **数据渗透** - 将窃取的凭证上传到攻击者控制的 GitHub 仓库 7. **自我传播** - 尝试感染多达 100 个额外的 npm 软件包 8. **持久化** - 创建名为 "SHA1HULUD" 的自托管 GitHub Runner 9. **破坏性故障保护** - 如果身份验证失败,则擦除主目录 ## 快速开始 在 **2 分钟内**获得保护: ### 第 1 步:创建工作流文件 在您的仓库中创建 `.github/workflows/shai-hulud-check.yml`: ``` 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 ``` ### 第 2 步:提交并推送 ``` git add .github/workflows/shai-hulud-check.yml git commit -m "Add Shai-Hulud 2.0 security scanning" git push ``` ### 第 3 步:检查结果 在您仓库的 Actions 标签页查看扫描结果。 ## 检测能力 此检测器超越了简单的软件包名称匹配,提供全面的威胁检测: ### 精确版本匹配 检测器使用 **semver(语义化版本控制)** 仅准确识别每个软件包的特定易受攻击版本: ``` Example: kill-port package ├── kill-port@2.0.1 → ✅ SAFE (not affected) ├── kill-port@2.0.2 → ❌ COMPROMISED └── kill-port@2.0.3 → ❌ COMPROMISED ``` 这通过以下方式显著减少了误报: - 匹配被入侵数据库中列出的确切版本 - 支持 semver 范围(例如 `>=1.0.0 <2.0.0`) - 正确处理来自 lockfile 的版本约束 ### 严重风险检测 | 检查项 | 描述 | |-------|-------------| | **被入侵的软件包** | 根据包含 790+ 个已知被入侵软件包的数据库进行扫描 | | **恶意脚本** | 在 postinstall/preinstall 钩子中检测 `setup_bun.js`、`bun_environment.js` | | **SHA256 哈希匹配** | 🆕 根据来自 Datadog IOC 数据库的已知恶意软件签名验证文件哈希 | | **TruffleHog 活动** | 识别凭证扫描模式和 TruffleHog 下载 | | **恶意 Runner** | 检测 SHA1HULUD GitHub Actions 自托管 Runner 引用 | | **Runner 安装** | 🆕 查找攻击使用的 `.dev-env/` 目录和 Runner 压缩包 | | **工作流触发器** | 🆕 检测用于命令注入后门的 `on: discussion` 工作流触发器 | | **密钥渗透** | 查找 `actionsSecrets.json`、`truffleSecrets.json`、`cloud.json`、`environment.json` 文件 | | **Shai-Hulud 仓库** | 识别名为 "Shai-Hulud" 的 git 远程/仓库 | ### 中等风险检测 | 检查项 | 描述 | |-------|-------------| | **Webhook 渗透** | 检测 `webhook.site` 端点和已知恶意 UUID | | **可疑分支** | 标记名为 "shai-hulud" 的 git 分支 | | **危险脚本** | 识别 `curl|sh`、`wget|sh`、`eval`、base64 解码模式 | ### 低风险检测 | 检查项 | 描述 | |-------|-------------| | **命名空间警告** | 对来自受影响命名空间(@ctrl、@asyncapi 等)且带有 semver 范围的软件包发出警告 | ### 免责声明 ## 🌍 帮助我们保护社区🔑 此项目的成功取决于您!
Shai-Hulud 2.0 攻击正在演变,新的被入侵软件包不断被发现。**我们的众包软件包数据库的质量取决于维护它的社区。** ### 为什么您的贡献很重要 ``` ┌─────────────────────────────────────────────────────────────────┐ │ │ │ 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 │ │ │ └─────────────────────────────────────────────────────────────────┘ ``` ### 如何报告软件包 | 您发现了什么 | 如何报告 | 所需时间 | |----------------|---------------|---------------| | **单个被入侵软件包** | [📦 软件包报告表单](https://github.com/gensecaihq/Shai-Hulud-2.0-Detector/issues/new?template=package-report.yml) | ~2 分钟 | | **多个软件包** | [📋 批量提交表单](https://github.com/gensecaihq/Shai-Hulud-2.0-Detector/issues/new?template=batch-submission.yml) | ~5 分钟 | | **误报** | [❌ 误报表单](https://github.com/gensecaihq/Shai-Hulud-2.0-Detector/issues/new?template=false-positive.yml) | ~2 分钟 | ### 什么构成一份好的报告? **所需的最低证据**(至少一项): - ✅ 软件包包含 `setup_bun.js` 或 `bun_environment.js` - ✅ 文件哈希与已知恶意哈希匹配 - ✅ 可疑的 `postinstall` 脚本下载外部代码 - ✅ 在攻击窗口期(2025 年 11 月 24 日)发布 - ✅ 来自 npm/GitHub 的安全公告 - ✅ 安全研究人员的分析 ### 快速报告模板 发现了不良软件包?复制此内容创建 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] ``` ### 致安全研究人员 如果您正在进行系统分析并发现多个软件包: 1. **使用我们的 [批量提交表单](https://github.com/gensecaihq/Shai-Hulud-2.0-Detector/issues/new?template=batch-submission.yml)** 以提高效率 2. **阅读完整的 [软件包数据库指南](docs/PACKAGE_DATABASE.md)** 获取详细说明 3. **考虑直接提交 PR** 到 `compromised-packages.json` 以便更快整合 4. **我们将在致谢中感谢您!** ### 数据库统计 | 指标 | 数值 | |--------|-------| | 软件包总数 | **795+** | | 数据来源 | **7 家安全供应商** | | 更新频率 | **每日(自动)** | | 版本精度 | **仅特定版本** | | 最后更新 | 见 `compromised-packages.json` | ## 安装 ### GitHub Action(推荐) 使用 Shai-Hulud 检测器的最简单方法是作为 GitHub Action。**现已在 [GitHub Marketplace](https://github.com/marketplace/actions/shai-hulud-2-0-detector) 上线!** #### 最小设置 ``` - uses: gensecaihq/Shai-Hulud-2.0-Detector@v2 ``` #### 包含所有选项的完整设置 ``` - 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: '.' allowlist-path: '.shai-hulud-allowlist.json' ignore-allowlist: false warn-on-allowlist: false ``` ### 本地 CLI 使用 您也可以在本地运行检测器,用于开发或不使用 GitHub Actions 的 CI 系统: #### 使用 npx(无需安装) ``` # 克隆并运行 git clone https://github.com/gensecaihq/Shai-Hulud-2.0-Detector.git cd Shai-Hulud-2.0-Detector ``` #### 设置选项 有两种设置选项的方法:通过 CLI 参数或设置环境变量。 ❗ 确保将工作目录选项添加到您要扫描的项目路径中。 所有其他选项均设置为以下默认值,因此是可选的。 运行脚本时设置 `--working-directory="/path/to/your/project"` 标志,或像下面列出的那样设置 `INPUT_WORKING_DIRECTORY="/path/to/your/project"` 环境变量。 ##### 通过 CLI 参数(选项 1) ``` 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" --allowlist-path=".shai-hulud-allowlist.json" --ignore-allowlist=false --warn-on-allowlist=false ``` ##### 通过环境变量(选项 2) **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" export INPUT_ALLOWLIST_PATH=".shai-hulud-allowlist.json" export INPUT_IGNORE_ALLOWLIST=false export INPUT_WARN_ON_ALLOWLIST=false node dist/index.js ``` **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" $Env:INPUT_ALLOWLIST_PATH=".shai-hulud-allowlist.json" $Env:INPUT_IGNORE_ALLOWLIST="false" $Env:INPUT_WARN_ON_ALLOWLIST="false" node dist/index.js ``` ### CI/CD 集成 #### 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 ``` ## 使用指南 ### 基础扫描 #### 每次推送时扫描 ``` name: Security Scan on: [push] jobs: scan: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: gensecaihq/Shai-Hulud-2.0-Detector@v2 ``` #### 仅扫描依赖文件 ``` 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 ``` #### 计划每日扫描 ``` 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 ``` ### 高级配置 #### 阻止包含被入侵依赖项的 PR ``` 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.' }) ``` #### 严格模式 - 检测到任何内容即失败 ``` - uses: gensecaihq/Shai-Hulud-2.0-Detector@v2 with: fail-on-any: true ``` #### 警告模式 - 报告但不失败 ``` - uses: gensecaihq/Shai-Hulud-2.0-Detector@v2 with: fail-on-critical: false fail-on-high: false fail-on-any: false ``` #### 排除发现/误报(允许列表) 如果检测器发现了您确定是误报的内容,您可以创建一个名为 `.shai-hulud-allowlist.json` 的允许列表文件,结构如下: ``` [ { "type": "shai-hulud-repo", "titleContains": "Shai-Hulud reference", "locationContains": ".github/workflows", "comment": "Self-reference: This repository IS the Shai-Hulud detector, so references to itself in workflows are expected" }, { "type": "shai-hulud-repo", "titleContains": "Shai-Hulud reference", "locationContains": "action.yml", "comment": "Self-reference: Action metadata file references the action name" } ] ``` 此架构中描述了可用于匹配发现项的允许列表属性完整列表: ``` interface AllowlistEntry { /** Finding type to match (e.g., 'suspicious-script', 'compromised-package') */ type?: SecurityFindingType; /** Severity level to match */ severity?: 'critical' | 'high' | 'medium' | 'low'; /** Exact title match */ title?: string; /** Substring match on title */ titleContains?: string; /** Exact location/file path match */ location?: string; /** Substring match on location */ locationContains?: string; /** Substring match on evidence field */ evidenceContains?: string; /** Exact SHA256 hash match, used for file and script contents */ sha256?: string; /** Documentation comment (not used in matching) */ comment?: string; } ``` 如果您使用了被检测到的自定义 pre-/postinstall 脚本,将其加入允许列表的最安全方法是使用 `sha256` 属性来匹配确切的脚本内容哈希(可能带有位置匹配器)。 ``` [ { "type": "suspicious-script", "sha256": "4118fdd78455decc4d9c8a8d3f3eca4548b4e73ff50f994a5bb6ef90676949ad", "comment": "Custom install script used for internal setup" } ] ``` 如果您使用的是现有 `.shai-hulud-allowlist.json` 以外的文件,请配置 Action 使用该允许列表: ``` - uses: gensecaihq/Shai-Hulud-2.0-Detector@v2 with: allowlist-path: '.custom-allowlist.json' ``` 您也可以选择完全忽略允许列表(不推荐)或仍然对允许列表中的发现发出警告: ``` - uses: gensecaihq/Shai-Hulud-2.0-Detector@v2 with: ignore-allowlist: false warn-on-allowlist: true ``` ### Monorepo 支持 检测器会自动扫描子目录以查找软件包文件(最深 5 层)。 #### 扫描整个 Monorepo ``` - uses: gensecaihq/Shai-Hulud-2.0-Detector@v2 with: working-directory: '.' scan-lockfiles: true ``` #### 扫描特定软件包 ``` - uses: gensecaihq/Shai-Hulud-2.0-Detector@v2 with: working-directory: './packages/frontend' ``` #### 多软件包的矩阵策略 ``` 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 报告 生成 SARIF 报告以便集成 GitHub Security 标签页: #### 基础 SARIF 输出 ``` - 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 ``` #### 完整安全集成 ``` 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 ``` ### 使用 Action 输出 访问扫描结果以进行条件逻辑处理或通知: ``` - 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 }} ``` ## 配置 ### 输入参考 | 输入 | 描述 | 类型 | 默认值 | |---------------------|---------------------------------------------------------------------------------|-------------------------------|------------------------------| | `fail-on-critical` | 如果发现严重级别的软件包则使工作流失败 | `boolean` | `true` | | `fail-on-high` | 如果发现高或严重级别的软件包则使工作流失败 | `boolean | `false` | | `fail-on-any` | 如果发现任何被入侵的软件包则使工作流失败 | `boolean` | `false` | | `scan-lockfiles` | 扫描 lockfile 以查找传递依赖 | `boolean` | `true` | | `scan-node-modules` | 扫描 node_modules 目录(较慢,更彻底) | `boolean` | `false` | | `output-format` | 输出格式:`text`、`json` 或 `sarif` | `'text' \| 'json' \| 'sarif'` | `text` | | `working-directory` | 要扫描的目录(相对于仓库根目录) | `string` | `.` | | `allowlist-path` | 用于忽略发现的允许列表文件路径,相对于工作目录 | `string` | `.shai-hulud-allowlist.json` | | `ignore-allowlist` | 忽略允许列表并报告所有发现 | `boolean` | `false` | | `warn-on-allowlist` | 对允许列表中的发现发出警告而不是忽略 | `boolean` | `false` | ### 输出参考 | 输出 | 描述 | 示例 | |---------------------------|------------------------------------------------------------|--------------------------------------| | `affected-count` | 检测到的被入侵软件包数量 | `3` | | `security-findings-count` | 安全发现数量(脚本、Runner 等) | `2` | | `status` | 整体扫描状态 | `clean` 或 `affected` | | `scan-time` | 扫描持续时间(毫秒) | `156` | | `results` | 检测到的软件包 JSON 数组 | `[{"package":"posthog-node",...}]` | | `security-findings` | 安全发现 JSON 数组 | `[{"type":"suspicious-script",...}]` | | `sarif-file` | 生成的 SARIF 文件路径(当 output-format 为 sarif 时) | `shai-hulud-results.sarif` | ### CLI 参数 在本地或非 GitHub CI 系统中运行时: | 变量 | 映射到 | 类型 | 默认值 | |-----------------------|---------------------------|-------------------------------|------------------------------| | `--fail-on-critical` | `fail-on-critical` 输入 | `boolean` | `true` | | `--fail-on-high` | `fail-on-high` 输入 | `boolean` | `false` | | `--fail-on-any` | `fail-on-any` 输入 | `boolean` | `false` | | `--scan-lockfiles` | `scan-lockfiles` 输入 | `boolean` | `true` | | `--scan-node-modules` | `scan-node-modules` 输入 | `boolean` | `false` | | `--output-format` | `output-format` 输入 | `'text' \| 'json' \| 'sarif'` | `text` | | `--working-directory` | `working-directory` 输入 | `string` | `.` | | `--allowlist-path` | `allowlist-path` 输入 | `string` | `.shai-hulud-allowlist.json` | | `--ignore-allowlist` | `ignore-allowlist` 输入 | `boolean` | `false` | | `--warn-on-allowlist` | `warn-on-allowlist` 输入 | `boolean` | `false` | ### 环境变量 在本地或非 GitHub CI 系统中运行时: | 变量 | 映射到 | 类型 | 默认值 | |---------------------------|---------------------------|-------------------------------|------------------------------| | `INPUT_FAIL_ON_CRITICAL` | `fail-on-critical` 输入 | `boolean` | `true` | | `INPUT_FAIL_ON_HIGH` | `fail-on-high` 输入 | `boolean` | `false` | | `INPUT_FAIL_ON_ANY` | `fail-on-any` 输入 | `boolean` | `false` | | `INPUT_SCAN_LOCKFILES` | `scan-lockfiles` 输入 | `boolean` | `true` | | `INPUT_SCAN_NODE_MODULES` | `scan-node-modules` 输入 | `boolean` | `false` | | `INPUT_OUTPUT_FORMAT` | `output-format` 输入 | `'text' \| 'json' \| 'sarif'` | `text` | | `INPUT_WORKING_DIRECTORY` | `working-directory` 输入 | `string` | `.` | | `INPUT_ALLOWLIST_PATH` | `allowlist-path` 输入 | `string` | `.shai-hulud-allowlist.json` | | `INPUT_IGNORE_ALLOWLIST` | `ignore-allowlist` 输入 | `boolean` | `false` | | `INPUT_WARN_ON_ALLOWLIST` | `warn-on-allowlist` 输入 | `boolean` | `false` | ## 支持的文件类型 | 文件 | 格式 | 直接依赖 | 传递依赖 | |------|--------|-------------|-----------------| | `package.json` | JSON | ✅ | ❌ | | `package-lock.json` | JSON (v1, v2, v3) | ✅ | ✅ | | `yarn.lock` | Yarn 自定义格式 | ❌ | ✅ | | `npm-shrinkwrap.json` | JSON | ✅ | ✅ | | `pnpm-lock.yaml` | YAML | 🚧 即将推出 | 🚧 | ## 理解结果 ### 输出格式 #### 文本输出(默认) ``` ============================================================ 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 Total dependencies: 1000 Compromised packages: 2 Security findings: 0 Scan time: 67ms Database version: 2.0.0 Last updated: 2025-12-04 ============================================================ 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 输出 ``` { "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" } ], "scannedFilesCount": 2, "scannedFiles": ["package.json", "package-lock.json"], "scanTime": 67 } ``` ### 严重级别 | 级别 | 描述 | 操作 | |-------|-------------|--------| | **CRITICAL** | 确认来自攻击的被入侵软件包 | 立即移除 | | **HIGH** | 疑似被入侵或相关软件包 | 调查并移除 | | **MEDIUM** | 来自受影响组织的软件包 | 密切监控 | | **LOW** | 潜在相关软件包 | 尽可能审查 | ### 直接依赖与传递依赖 - **直接依赖**:软件包列在您的 `package.json` 中 - **传递依赖**:软件包是您依赖项的依赖 ## 受影响软件包数据库 检测器包含一个在攻击中识别出的 **795+ 个独立软件包** 数据库,具有 **精确版本匹配** 以最大限度地减少误报。 | 组织 | 数量 | 关键软件包 | |--------------|-------|--------------| | 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` | | 其他 | 513 | 各种社区软件包 | ### 自动化每日更新 软件包数据库从 [Datadog Consolidated IOCs](https://github.com/DataDog/indicators-of-compromise/tree/main/shai-hulud-2.0) **每日自动更新**,该数据库聚合了来自 **7 家安全供应商** 的数据: | 来源 | 描述 | |--------|-------------| | **[Datadog Security Labs](https://securitylabs.datadoghq.com)** | SHA256 哈希 IOC 和恶意软件分析 | | **[Wiz](https://www.wiz.io)** | 威胁调查和攻击分析 | | **[HelixGuard](https://helixguard.ai)** | 恶意软件分析和 IOC 识别 | | **[ReversingLabs](https://www.reversinglabs.com)** | 软件供应链安全 | | **[Socket.dev](https://socket.dev)** | npm 安全监控 | | **[StepSecurity](https://www.stepsecurity.io)** | GitHub Actions 安全 | | **[Koi Security](https://koi.security)** | 供应链威胁情报 | ### 更新如何工作 ``` ┌─────────────────────────────────────────────────────────────────┐ │ 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 │ │ │ └─────────────────────────────────────────────────────────────────┘ ``` - **自动化工作流**:通过 GitHub Actions 每日 00:00 UTC 运行 - **手动触发**:可通过工作流调度手动触发 - **基于 PR 的更新**:更改会创建 Pull Request 以供审查后再合并 - **版本精度**:仅标记特定的被入侵版本(无通配符) ### 为什么版本精确性很重要 以前的版本会标记软件包的所有版本。现在仅检测特定的被入侵版本: ``` 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) ``` 这消除了以下情况的误报: - 攻击前版本(2025 年 11 月 24 日之前发布) - 修复后的干净版本 ### 手动数据库更新 手动触发数据库更新: ``` # 通过 GitHub Actions UI # 前往 Actions → "Update IOC Database" → Run workflow # 或者本地 node scripts/update-ioc-database.js ``` 查看 `compromised-packages.json` 获取包含版本信息的完整列表。 ## 入侵指标 ### 恶意文件 如果您在项目或 `node_modules` 中发现这些文件,您可能已被入侵: | 文件 | SHA-1 哈希 | SHA-256 哈希 | 用途 | |------|------------|--------------|---------| | `setup_bun.js` | `d1829b47...` | `a3894003ad1d293ba96d77881ccd2071...` | 下载 Bun 运行时 | | `bun_environment.js` | `d60ec97e...` | 多种变体(6+ 个哈希) | 执行恶意 Payload(10MB+ 混淆) | | `actionsSecrets.json` | - | - | 被盗的 GitHub Actions 密钥(双重 Base64 编码) | | `trufflehog_output.json` | - | - | TruffleHog 凭证扫描结果 | | `cloud.json` | - | - | 存储被盗的云凭证 | | `contents.json` | - | - | 包含渗透的数据 | | `environment.json` | - | - | 保存环境变量 | | `truffleSecrets.json` | - | - | TruffleHog 扫描结果 | ### Runner 安装产物 攻击会安装恶意的 GitHub Actions Runner。请检查: | 产物 | 位置 | 描述 | |----------|----------|-------------| | `.dev-env/` | `$HOME/.dev-env/` | Runner 安装目录 | | `actions-runner-linux-x64-2.330.0.tar.gz` | 各处 | 攻击使用的特定 Runner 版本 | | `.config/gcloud/application_default_credentials.json` | `$HOME/` | 目标凭证文件 | | `.npmrc` | `$HOME/` | 目标 npm 凭证 | ### 恶意工作流 检查 `.github/workflows/` 是否存在这些可疑模式: | 模式 | 描述 | |---------|-------------| | `discussion.yaml` 或 `discussion.yml` | 注入的用于远程执行的工作流 | | `formatter_*.yml` | 带有随机后缀的恶意工作流(例如 `formatter_abc123.yml`) | | `on: discussion` 触发器 | 命令注入后门触发器(🆕 v2.0.0) | 这些工作流通常使用 `SHA1HULUD` 自托管 Runner 执行恶意代码。 **v2.0.0 新增:** 检测器现在会扫描工作流文件中的 `on: discussion` 触发器,攻击使用该触发器创建命令注入后门,即使在初始感染被清除后也能持久存在。 ### GitHub 指标 搜索您的组织: - 名为 `SHA1HULUD` 的自托管 Runner - 描述包含 `Shai-Hulud: The Second Coming` 的仓库 ## 事件响应指南 ### 如果您受到影响 #### 立即行动(前 15 分钟) 1. **停止** - 不要运行 `npm install` 或任何构建命令 2. **隔离** - 尽可能将受影响的系统与网络断开 3. **记录** - 记下时间戳、受影响的系统以及运行了什么 4. **警报** - 通知您的安全团队 #### 遏制(第一个) ``` # 1. 检查恶意文件 find ./node_modules -name "setup_bun.js" -o -name "bun_environment.js" # 2. 检查恶意 workflows ls -la .github/workflows/ | grep -E "(discussion|formatter_)" # 3. 检查未授权 runners (需要 gh CLI) gh api repos/{owner}/{repo}/actions/runners --jq '.runners[].name' | grep -i sha1hulud ``` #### 凭证轮换检查清单 | 服务 | 操作 | 优先级 | |---------|--------|----------| | npm | 撤销并重新生成令牌 | 🔴 严重 | | GitHub | 轮换 PAT、OAuth 令牌、App 密钥 | 🔴 严重 | | AWS | 轮换访问密钥,使会话失效 | 🔴 严重 | | GCP | 轮换服务账号密钥 | 🔴 严重 | | Azure | 重新生成服务主体凭证 | 🔴 严重 | | Docker Hub | 重置访问令牌 | 🟡 高 | | 数据库 | 更改密码,轮换连接字符串 | 🟡 高 | | 第三方 API | 重新生成 API 密钥 | 🟡 高 | | SSH | 如果存储在仓库中,重新生成密钥 | 🟠 中 | #### 全新安装 ``` # 1. 移除现有的 node_modules rm -rf node_modules package-lock.json # 2. 清除 npm 缓存 npm cache clean --force # 3. 手动审查 package.json # 移除任何受损的 packages # 4. 带审计的全新安装 npm install --ignore-scripts # Prevent postinstall hooks npm audit # 5. 运行安全扫描 npx gensecaihq/Shai-Hulud-2.0-Detector ``` ## 常见问题 ### 一般问题 **问:这是真实的攻击吗?** 答:是的。Shai-Hulud 2.0 攻击发生在 2025 年 11 月 24 日,入侵了数百个 npm 软件包。 **问:我如何知道是否受到影响?** 答:在您的项目上运行此检测器。如果它报告受影响的软件包,您可能已被入侵。 **问:如果我已经运行了 npm install 怎么办?** 答:立即遵循 [事件响应指南](#incident-response-guide)。假设凭证已被盗。 ### 技术问题 **问:这会扫描我的实际代码吗?** 答:不会。它仅扫描 `package.json`、lockfile,以及可选的 `node_modules` 以查找已知的被入侵软件包名称。 **问:这会减慢我的 CI/CD 吗?** 答:不会。典型扫描时间在 100ms 以内。检测器针对速度进行了优化。 **问:这适用于私有 Registry 吗?** 答:是的。检测器读取本地文件,不需要 Registry 访问权限。 **问:我可以将其与 Yarn 2/3 (Berry) 一起使用吗?** 答:支持 Yarn Classic lockfile。Yarn Berry (PnP) 支持即将推出。 ### 误报 **问:如果软件包被错误标记怎么办?** 答:[提交 Issue](https://github.com/gensecaihq/Shai-Hulud-2.0-Detector/issues) 并提供详细信息。我们将进行调查并更新数据库。 **问:补丁版本呢?** 答:检测器使用 semver 匹配仅标记特定的被入侵版本。软件包的安全版本不会被标记。查看 `compromised-packages.json` 了解版本详情。 **问:为什么来自 @octokit、@microsoft、@types 的软件包没有被标记?** 答:这些是由主要组织维护的 **受信任命名空间**。检测器会自动将它们从基于内容的扫描中排除,以防止来自合法安全文档的误报。 **问:为什么我的 TruffleHog Homebrew formula 没有被标记?** 答:检测器使用 **上下文感知检测** 来区分合法的 TruffleHog 使用(安全扫描、Homebrew formula、CI 配置)和恶意滥用(npm postinstall 脚本中的凭证窃取)。只有特定于攻击的模式才会触发警报。 ## 贡献 我们欢迎您的贡献!以下是您可以帮助我们的方式: ### 快速链接 | 操作 | 链接 | |--------|------| | 报告被入侵软件包 | [软件包报告 Issue](https://github.com/gensecaihq/Shai-Hulud-2.0-Detector/issues/new?template=package-report.yml) | | 报告误报 | [误报 Issue](https://github.com/gensecaihq/Shai-Hulud-2.0-Detector/issues/new?template=false-positive.yml) | | 批量提交 | [批量提交 Issue](https://github.com/gensecaihq/Shai-Hulud-2.0-Detector/issues/new?template=batch-submission.yml) | | 贡献指南 | [CONTRIBUTING.md](CONTRIBUTING.md) | | 软件包数据库指南 | [docs/PACKAGE_DATABASE.md](docs/PACKAGE_DATABASE.md) | ### 报告问题 - **被入侵的软件包**:使用 [软件包报告](https://github.com/gensecaihq/Shai-Hulud-2.0-Detector/issues/new?template=package-report.yml) 模板 - **误报**:使用 [误报](https://github.com/gensecaihq/Shai-Hulud-2.0-Detector/issues/new?template=false-positive.yml) 模板 - **多个软件包**:使用 [批量提交](https://github.com/gensecaihq/Shai-Hulud-2.0-Detector/issues/new?template=batch-submission.yml) 模板 - **错误**:提交包含复现步骤的 Issue ### 开发设置 ``` # 1. Fork 并克隆 git clone https://github.com/YOUR_USERNAME/Shai-Hulud-2.0-Detector.git cd Shai-Hulud-2.0-Detector # 2. 安装依赖 npm ci # 3. 修改 src/ # 4. 构建 npm run build # 5. 本地测试 export INPUT_WORKING_DIRECTORY=/path/to/test/project node dist/index.js ``` ### Pull Request 流程 1. Fork 本仓库 2. 创建功能分支 (`git checkout -b feature/amazing-feature`) 3. 进行更改 4. 运行 `npm run build` 进行编译 5. 测试您的更改 6. 提交 (`git commit -m 'Add amazing feature'`) 7. 推送 (`git push origin feature/amazing-feature`) 8. 提交 Pull Request ### 代码风格 - TypeScript 严格模式 - 使用有意义的变量名 - 为复杂逻辑添加注释 - 遵循代码库中的现有模式 ### 更新软件包数据库 **添加软件包的快速步骤:** 1. **通过 GitHub Issue**(最简单): - 使用 [软件包报告](https://github.com/gensecaihq/Shai-Hulud-2.0-Detector/issues/new?template=package-report.yml) 模板 - 填写软件包详情和证据 - 维护者将进行审核并添加 2. **通过 Pull Request**(针对贡献者): # Fork 并克隆仓库 git checkout -b add-package/package-name # 编辑 compromised-packages.json - 添加到 packages 数组: { "name": "@scope/package-name", "severity": "critical", "affectedVersions": ["*"] } # 构建并提交 npm run build git commit -am "feat(db): add @scope/package-name" git push && gh pr create **所需证据:** 至少包含以下一项 - 发现恶意文件、哈希匹配、可疑脚本、安全公告或维护者被入侵确认。 ## 致谢 ### 安全研究人员 本项目建立在识别和分析 Shai-Hulud 2.0 攻击的安全研究人员的杰出工作之上: | 组织 | GitHub | 贡献 | |-------------|--------|--------------| | **[Wiz](https://www.wiz.io)** | [@wiz-sec](https://github.com/wiz-sec) | 全面的威胁调查和后续分析 | | **[Datadog Security Labs](https://securitylabs.datadoghq.com)** | [@DataDog](https://github.com/DataDog) | SHA256 哈希 IOC 和详细的恶意软件分析 | | **[Aikido Security](https://www.aikido.dev)** | [@AikidoSec](https://github.com/AikidoSec) | 初步检测和软件包数据库 | | **[Postman](https://www.postman.com)** | [@postmanlabs](https://github.com/postmanlabs) | 事后分析和软件包响应 | | **[PostHog](https://posthog.com)** | [@PostHog](https://github.com/PostHog) | 攻击时间线和事件响应 | | **[HelixGuard](https://helixguard.ai)** | [@helixguard](https://github.com/helixguard) | 恶意软件分析和 IOC 识别 | ### 研究与分析 - [Wiz.io - Shai-Hulud 2.0 调查](https://www.wiz.io/blog/shai-hulud-2-0-ongoing-supply-chain-attack) - [Wiz.io - Shai-Hulud 2.0 后续分析](https://www.wiz.io/blog/shai-hulud-2-0-aftermath-ongoing-supply-chain-attack) - [Datadog Security Labs - npm 蠕虫分析](https://securitylabs.datadoghq.com/articles/shai-hulud-2.0-npm-worm/) - [Datadog IOC 仓库](https://github.com/DataDog/indicators-of-compromise/tree/main/shai-hulud-2.0) - [Aikido Security - Shai-Hulud 再次袭击](https://www.aikido.dev/blog/shai-hulud-strikes-again-hitting-zapier-ensdomains) - [Postman Engineering - npm 供应链攻击](https://blog.postman.com/engineering/shai-hulud-2-0-npm-supply-chain-attack/) - [PostHog - 攻击事后分析](https://posthog.com/blog/nov-24-shai-hulud-attack-post-mortem) - [HelixGuard - 恶意 SHA1HULUD 分析](https://helixguard.ai/blog/malicious-sha1hulud-2025-11-24) ### 开源工具 - [GitHub Actions](https://github.com/features/actions) - CI/CD 平台 - [ncc](https://github.com/vercel/ncc) - TypeScript 编译 - [TruffleHog](https://github.com/trufflesecurity/trufflehog) - 密钥扫描(被攻击者使用,具有讽刺意味) ### 社区 感谢所有报告受影响软件包、测试检测器并帮助传播有关此攻击信息的人。 ## 感谢 衷心感谢所有通过代码、Issue 报告和讨论为本项目做出贡献的社区成员: | | 贡献者 | 贡献 | |---|-------------|---------------| |保持安全。保护您的供应链。 🛡️
⭐ Star 本仓库 • 报告 Bug • 请求功能
标签:CI/CD安全, GitHub Action, GNU通用公共许可证, Llama, MITM代理, Node.js, NPM安全, SARIF, Shai-Hulud 2.0, StruQ, TruffleHog, 依赖扫描, 前端安全, 学术论文, 安全助手, 密钥泄露检测, 文档安全, 文档结构分析, 模型提供商, 自动化攻击, 自动化攻击, 软件开发工具包, 错误基检测, 静态代码分析