依赖审计
定期盘点每个依赖:用了什么、未用什么、有风险什么、过时什么。
为什么
依赖树是你没写的责任面 — 每个包是以你的权限运行的代码,由你不认识的人维护,有你看不见的 bug。审计把这不透明团块变成受管清单:你得知有 1200 个传递依赖(非 40)、3 个无人维护、1 个有已知 CVE、12 个未用。不定期审计则 node_modules 单调增长 — 每次添加是单向棘轮永不移除,攻击面只增不减。审计是你把它缩回来的方式。
何时使用
至少每季度。任一依赖宣布高危 CVE 时立即。
如何做
1. 生成完整树:npm ls --all(或 pnpm why)— 捕获直接 + 传递数量 2. 找未用:npx depcheck(或 knip)— 列出在 package.json 但从未 import 的依赖 3. 找过时:npm outdated — 显示每包 current vs wanted vs latest 4. 找漏洞:npm audit(或 pnpm audit,或 Snyk/OSV-Scanner) 5. 找许可证问题:license-checker --production — 标记 GPL/不兼容许可证 6. 分诊:删未用、升有 CVE 的过时、为有风险但需要的开工单 7. 把审计记入 DEPS_AUDIT.md,含日期、数量、所采取行动
示例
# 一个脚本完成审计 npm ls --all > deps-tree.txt npx depcheck --json > unused.json npm outdated > outdated.txt npm audit --json > audit.json npx license-checker --production --json > licenses.json # Knip(找未用文件、导出和依赖) npx knip --include dependencies # OSV-Scanner(Google 漏洞库,覆盖 npm + pip + cargo) npx @google/osv-scanner --lockfile package-lock.json # 分诊输出: # - 12 个未用依赖 -> 从 package.json 删除 # - 3 个高危 CVE -> 立即升级 # - 2 个 GPL 许可 -> 法务审查(或换 MIT 替代)
常见问题
- ⚠只审计直接依赖而忽略 1000+ 传递依赖 — CVE 和供应链攻击就在那里。
- ⚠跑一次 npm audit 忽略 47 个低危发现 — 它们累积,未来小版本把一个变 critical。
- ⚠删了 depcheck 标记未用的依赖,但它是 peer dep 或动态 import — 生产崩溃。
最佳实践
- ✓在 CI 每 PR 自动审计,high/critical CVE 失败 — 别等季度手动跑。
- ✓用 knip 而非 depcheck — 它理解动态 import、peer dep、type-only import,误报更少。
- ✓每次审计记入 DEPS_AUDIT.md 以看趋势:node_modules 季度环比在增还是缩?