零依赖的 npm 和 PyPI 供应链受损检测 CLI 扫描器。
2026年5月11日,一种自传播的供应链蠕虫被命名为 Mini Shai-Hulud(CVE-2026-45321,GHSA-g7cv-rxg3-hmpx)入侵了 npm 生态系统。该恶意软件归因于 TeamPCP(又名 DeadCatx3、PCPcat、ShellForce、CipherForce),它劫持了 GitHub Actions OIDC 令牌,发布带有有效 SLSA Build Level 3 来源证明的恶意包。它窃取了 CI/CD 流水线、云提供商和加密货币钱包中的凭证,并在 Claude Code 和 VS Code 中安装了持久化钩子。内置的“死亡开关”会威胁,如果 npm 令牌被撤销,则擦除用户的家目录。
受影响的包包括 TanStack router 和 start 包、Mistral AI SDK、OpenSearch 客户端、UiPath 工具等。由于供应链攻击传播迅速,组织需要一种轻量、可信赖的扫描器,可以在任何地方运行,而无需在其自身攻击面上增加新的依赖项。
package-lock.json、pnpm-lock.yaml、yarn.lock、bun.lock、bun.lockb、poetry.lock、Pipfile.lock 和 requirements.txt 中的受损 npm 和 PyPI 包。fs、path、child_process、os)。该扫描器不会增加您的供应链风险。0 = 干净,1 = 发现问题,2 = 错误)。src/db.ts 中;更新文件并重新运行。无需安装。直接使用您选择的包运行器:
# npx
npx @digi4care/shai-scan
# bunx
bunx @digi4care/shai-scan
# pnpm dlx
pnpm dlx @digi4care/shai-scan
全局安装(可选):
npm install -g @digi4care/shai-scan
# 或
pnpm add -g @digi4care/shai-scan
从源码安装:
git clone https://github.com/digi4care/shai-scan.git
cd shai-scan
pnpm install
bun run src/cli.ts --help # Bun(推荐用于开发)
# 或使用 Node.js 构建并运行:
pnpm run build && node dist/cli.js --help
npx @digi4care/shai-scan
npx @digi4care/shai-scan ~/projects/my-app
npx @digi4care/shai-scan --json .
npx @digi4care/shai-scan --sarif --sarif-file results.sarif .
#!/bin/bash
npx @digi4care/shai-scan --severity high . || {
code=$?
if [ "$code" -eq 1 ]; then
echo "检测到供应链问题"
exit 1
elif [ "$code" -eq 2 ]; then
echo "扫描器错误"
exit 2
fi
}
name: Supply Chain Scan
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: 22
- run: pnpm install --frozen-lockfile
- run: npx @digi4care/shai-scan --severity high .
name: Supply Chain Scan SARIF
on:
push:
branches: [main]
pull_request:
branches: [main]
schedule:
- cron: '0 6 * * 1'
jobs:
scan:
runs-on: ubuntu-latest
permissions:
security-events: write
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: 22
- run: pnpm install --frozen-lockfile
- run: npx @digi4care/shai-scan --sarif --sarif-file results.sarif .
- uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: results.sarif
| 格式 | 标志 | 描述 |
|---|---|---|
| 文本 | (默认) | 人类可读的发现结果表格,包含严重性、包名、版本和攻击波详情 |
| JSON | --json | 结构化的 JSON 发现结果数组,适用于导入 SIEM 或自定义仪表板 |
JSON 示例片段:
[
{
"package": "@tanstack/react-router",
"version": "1.169.5",
"ecosystem": "npm",
"severity": "critical",
"campaign": "mini-shai-hulud-wave4",
"cve": "CVE-2026-45321",
"reference": "https://github.com/TanStack/router/security/advisories/GHSA-g7cv-rxg3-hmpx"
}
]
| 代码 | 含义 |
|---|---|
| 0 | 未检测到受损包或 IOC |
| 1 | 检测到一个或多个问题 |
| 2 | 运行时错误(无效路径、无法读取锁定文件等) |
当发现新的供应链攻击时,更新 src/db.ts:
CompromisedVersion[] 数组,包含受影响的包和版本。CAMPAIGNS 数组中追加一个新的 Campaign 对象,包括 CVE/GHSA 标识符、严重性、描述、参考 URL 和 IOC 指标。buildLookup() 函数会在下次运行时自动重建查找映射。使用 Bun 时不需要构建步骤。对 src/db.ts 的更改会立即生效(通过 bun run src/cli.ts)。对于 npm 包,编辑后运行 pnpm run build。
零运行时依赖:该扫描器仅使用 Node.js/Bun 内置模块。它不会在运行时下载或执行第三方代码,消除了扫描器本身成为入侵媒介的风险。
使用 pnpm 作为包管理器:pnpm 使用严格锁定文件,默认不执行生命周期脚本,并支持内容寻址存储。这些特性相比其他包管理器减少了攻击面。
推荐的 .npmrc 设置:为了在安装包时获得最大保护,请将以下内容添加到您的项目或全局 .npmrc 中:
ignore-scripts=true
engine-strict=true
无网络调用:shai-scan 不会回拨电话、下载签名或需要 API 密钥。所有攻击波数据都随包一起提供。
以下包和版本已知在 CVE-2026-45321(Mini Shai-Hulud 第 4 波)中受损。这是一个代表性子集;完整列表维护在 src/db.ts 中。
MIT。详情请参见 LICENSE。
shai-scan 是一种检测辅助工具,不能替代全面的安全审计、依赖审查或威胁情报平台。它仅基于内置数据库识别已知的受损版本;在攻击波被添加之前,新的或零日供应链攻击可能无法被检测到。始终遵循深度防御原则:审计依赖、固定版本、验证来源证明并监控 CI/CD 流水线。
| SARIF | --sarif | OASIS SARIF 2.1.0 格式,用于上传到 GitHub Code Scanning、GitLab Secure 或其他 SARIF 消费端 |
| 包 | 生态系统 | 受损版本 |
|---|
@tanstack/react-router | npm | 1.169.5, 1.169.8 |
@tanstack/vue-router | npm | 1.169.5, 1.169.8 |
@tanstack/solid-router | npm | 1.169.5, 1.169.8 |
@tanstack/router-core | npm | 1.169.5, 1.169.8 |
@tanstack/react-start | npm | 1.167.68, 1.167.71 |
@mistralai/mistralai | npm | 2.2.2, 2.2.3, 2.2.4 |
@mistralai/mistralai-azure | npm | 1.7.2, 1.7.3 |
mistralai | pypi | 2.4.6 |
@opensearch-project/opensearch | npm | 3.5.3, 3.6.2, 3.7.0, 3.8.0 |
@uipath/robot | npm | 1.3.4 |
@squawk/airways | npm | 0.4.2, 0.4.3, 0.4.5 |
@draftauth/core | npm | 0.13.1, 0.13.2 |
@tallyui/core | npm | 0.2.1, 0.2.2, 0.2.3 |
safe-action | npm | 0.8.3, 0.8.4 |
cmux-agent-mcp | npm | 0.1.3 - 0.1.8 |
nextmove-mcp | npm | 0.1.3, 0.1.4, 0.1.5, 0.1.7 |
ts-dna | npm | 3.0.1, 3.0.2, 3.0.4 |
cross-stitch | npm | 1.1.3, 1.1.4, 1.1.6 |
git-git-git | npm | 1.0.8 - 1.0.12 |
git-branch-selector | npm | 1.3.3 - 1.3.7 |
agentwork-cli | npm | 0.1.4, 0.1.5 |
wot-api | npm | 0.8.1, 0.8.2, 0.8.4 |
ml-toolkit-ts | npm | 1.0.4, 1.0.5 |
@beproduct/nestjs-auth | npm | 0.1.2 - 0.1.19 |
@dirigible-ai/sdk | npm | 0.6.2, 0.6.3 |
@taskflow-corp/cli | npm | 0.1.24 - 0.1.29 |
@tolka/cli | npm | 1.0.2, 1.0.3, 1.0.4, 1.0.6 |
@supersurkhet/cli | npm | 0.0.2 - 0.0.7 |
guardrails-ai | pypi | 0.10.1 |