dependency-audit · v2.2.13 · 2026-09-09 · sha256 8485426d95a66b1e

dependency-audit v2.2.13A

Immutable. This exact content is served forever at /api/v1/blob/8485426d95a66b1e.

---
name: dependency-audit
description: '依赖供应链审计:pnpm/npm audit 输出与退出码解读、license 与投毒风险检查清单、锁文件漂移检测命令。任务要求审计项目依赖的已知漏洞、许可证风险、可疑包或 lockfile 一致性并出结论时用;单独安装/升级某个依赖或纯功能开发不展开本流程。'
whenToUse: '用户要求审计或盘点项目依赖安全(漏洞、license、投毒、锁文件漂移)、解读 audit 报告、判断某个依赖能否引入,或写依赖审计结论时使用;单个依赖的普通升级与纯功能开发不触发本技能。'
metadata:
  pack: dsh-skill-pack-security
  version: '2.2.13'
---

# 依赖审计(dependency-audit)

目标:对仓库依赖面给出**每条结论都附命令证据**的审计结果。输出分七块:已知漏洞、license、投毒风险、锁文件漂移、多生态漏洞、SBOM 清单、provenance/签名。

## 自动化预检:plugin_vet 工具

`plugin_vet` 已自动执行本技能第 3/4/7 节的静态部分(license 判定、投毒清单、SBOM 依赖树),其结果逐条引用本技能小节编号。自动化命中后,按各节命令复核证据并排除误报。

## 1. 定位包管理器与锁文件

```sh
git ls-files -- 'package.json' 'pnpm-lock.yaml' 'package-lock.json' 'yarn.lock' 'bun.lockb' 'npm-shrinkwrap.json'
node --version; pnpm --version
osv-scanner --version
```

样例输出(pnpm 仓库):`package.json` 与 `pnpm-lock.yaml` 各一行。
判据:锁文件决定后续命令族(pnpm→第 2 节,npm→同节 npm 变体);**多个锁文件并存 = 仓库异常**,写进发现;版本号写进报告(audit 数据随 registry 与工具版本变化);`osv-scanner` 不可用只影响第 6 节,注明即可。

## 2. 已知漏洞:pnpm audit

```sh
pnpm audit --prod --json > audit.json; echo $LASTEXITCODE
```

(bash 用 `$?`;PowerShell 用 `$LASTEXITCODE`。)

- 退出码:0 = 无已知漏洞;非 0 = 有漏洞 **或 registry 不可达**(stderr 含 `fetch`/`ECONNREFUSED`/`ETIMEDOUT` 时为网络失败,不是发现漏洞——重试后再说)。
- `--prod` 只审生产依赖;需要全量视图时补跑 `pnpm audit --json`,devDependencies 部分按下文的降档规则处理。
- 输出样例(`advisories` 是按 advisory id 键控的**对象**,下例为其一个值;字段以实际输出为准):

```json
{ "id": "GHSA-xxxx-yyyy-zzzz", "severity": "high",
  "module_name": "example-lib", "vulnerable_versions": "<2.3.0",
  "patched_versions": ">=2.3.1", "recommendation": "Upgrade to 2.3.1",
  "found": { "paths": ["prod-dep@1.0.0 > example-lib@2.2.9"] } }
```

- 解读规则:
  - `severity` 只信 registry 值(low/moderate/high/critical),不自行推断。
  - 每个 advisory 查 `patched_versions` 是否存在;不存在 = 暂无修复版本,记录"无修复版本",不要声称"升级即可修复"。
  - 影响路径只在 devDependencies 中 → 默认降一档报告,除非该 devDep 参与构建产物(用代码证据证明,不能口头认定)。
- 误报/误判判据(全表见 `references/pnpm-audit-reading.md`):advisory 状态 disputed/withdrawn、版本范围不含当前版本、路径不可达(不可达必须有调用点证据:`pnpm why <包>` + 源码 grep 无引用)。
- npm 项目变体:`npm audit --json`(退出码同为 0/非 0;结构是 `vulnerabilities` 对象而非 `advisories` 对象,样例见 references)。

## 3. license 检查

```sh
pnpm licenses list --json
```

样例行:`{ "name": "example-lib", "license": "MIT" }`(输出结构以实际为准)。
找三类问题:

1. **无声明**:license 字段为空/null → 记录"无许可证声明"(用法本身即合规风险)。
2. **强 copyleft**:直接依赖中出现 GPL/AGPL/SSPL/CPAL 等(完整清单见 `references/license-and-lockfile.md`)→ 定位用途:`pnpm why <包名>` 给出依赖链。
3. **非 SPDX**:值含 `SEE LICENSE IN <file>` → `git ls-files -- '<包目录>/**/LICENSE*'` 或解包读该文件再定论。

判据:license 风险结论 = 包名 + 依赖链 + 许可证 + 用途;找不到用途(源码无 import)的按"未使用依赖"另记一条。

## 4. 投毒风险检查清单(对每个"新/可疑"依赖逐项打勾)

完整命令与阈值表见 `references/license-and-lockfile.md`,五项速记:

1. **名称相似性**:`npm view <包> time.created`(样例:`2026-08-10T02:00:00.000Z`)。判据:创建 < 30 天且下载量极低 → 高风险标记,转 `supply-chain-review` 做 typosquat 判定。
2. **install 脚本**:`npm view <包> scripts --json`(样例:`{ "postinstall": "node scripts/download.js" }`)。非空 → 转 `supply-chain-review` 第 1 节逐条查危险特征。
3. **发布者与仓库**:`npm view <包> repository.url maintainers --json`。判据:repository 缺失/指向可疑 fork + 维护者历史为零 → 记录。
4. **网络行为**:`npm pack <包> --pack-destination .tmp` 后 `grep -rnE 'https?://' .tmp/<包>/` 看请求域。判据:出现与包用途无关的域名 → 记录并人工复核。
5. **provenance**:`npm view <包> provenance --json`。判据:无 provenance 不等于恶意,但写进风险记录。

判据:单条命中只是"记录",**两条及以上同时命中才升级为"发现"**——防止单项误判。

## 5. 锁文件漂移检测

步骤与命令:

```sh
git diff HEAD -- pnpm-lock.yaml | head -n 40
pnpm install --frozen-lockfile
grep -c 'integrity' pnpm-lock.yaml
```

- 步骤 1 判据:diff 非空 = 锁文件有改动,逐块看是否意外(合并冲突残留 `<<<<<<<` 也算)。
- 步骤 2 判据:CI 语义下任何漂移立即失败。
  样例失败输出:`ERR_PNPM_OUTDATED_LOCKFILE  Cannot install with "frozen-lockfile" because pnpm-lock.yaml is not up to date with package.json`
  本地通过 + CI 失败 = 平台差异(optionalDependencies)→ 逐包核对,**不要关掉 frozen-lockfile**。
- 步骤 3 判据:integrity 条目数 ≈ 依赖条目数;明显偏少 = 锁文件被手改/损坏。
- 漂移原因分类与复核命令、lockfileVersion 对照表见 `references/license-and-lockfile.md`。

## 6. 多生态与离线:osv-scanner

```sh
osv-scanner scan -r .
```

样例输出行(以实际输出为准):

```
Scanning dir .
Scanned <project>/package-lock.json file and found 2 packages
```

- 判据:退出码 0 = 未发现;非 0 = 有漏洞或参数错误(stderr 区分)。`-r .` 自动识别目录中的全部锁文件(pnpm/npm/yarn/bun/pip/Cargo/Go/Maven 等);单文件用 `osv-scanner scan lockfile <文件>`。
- 与 pnpm audit 差异:osv-scanner 查 OSV 数据库(聚合 GitHub Advisories 等来源),覆盖 pnpm audit 看不到的其他生态;两边不一致时按 advisory id 逐条核对,不互相当作误报依据。
- 离线路径:`osv-scanner scan -r . --offline`(配合本地 OSV 数据)用于 registry 不可达环境;报告注明数据版本。

## 7. SBOM 资产清单(机器可复核的盘点)

```sh
trivy sbom . --format cyclonedx -o sbom.cdx.json
# 或 syft dir:. -o spdx-json=sbom.spdx.json
```

样例输出:退出码 0,并打印产物路径(`sbom.cdx.json`)。
判据:SBOM 作为依赖盘点附录随报告提交;条目数与 `pnpm licenses list` 条目数量级一致,不一致 = 记录并说明原因。SBOM 不含密钥但含依赖拓扑,按报告同等级别保管。

## 8. provenance 与签名

```sh
npm view <包> provenance --json
npm view <包> dist.integrity --json
npm audit signatures
```

- 判据:`provenance` 非空 = 包由 CI 构建并带构建来源声明;`dist.integrity` 与锁文件中同版本包的 `integrity` 值必须一致,不一致 = 锁文件被手改或包被替换,立即升级为发现。
- `npm audit signatures` 校验 registry 签名:退出码 0 = 通过;非 0 输出列出签名缺失/无效的包,记录并人工复核来源。
- 无 provenance 不等于恶意,但写进风险记录(第 4 节第 5 项同规则)。

## 结论格式

每条结论 = 断言 + 命令 + 输出摘要 + 误报排除说明("我排除了 X,因为 <证据>")。无证据的担忧写进"观察",不进"发现"。