Skip to content
返回质量保障

依赖扫描

每次变更自动发现第三方依赖中的已知漏洞。

为什么

现代应用 80-90% 是第三方代码——你的 package.json 拉 1000 个传递依赖,各有自己的 CVE。漏洞代码不是你写的但你发布它且你负责。log4j 漏洞(CVE-2021-44228)让任何未补丁服务器通过精心日志串执行任意代码,存在于数千开发者从未听过 log4j 的应用——它传递性引入。依赖扫描自动化不可能手动做的事: 每次变更把每个依赖对 CVE 数据库查,使传递包中新披露漏洞数小时内抓非入侵后。

何时使用

每个 PR(新高/危 CVE 即阻止)、主分支每晚(抓上次合并后披露的 CVE)、每次发布前。别跳——一次漏扫是一次漏漏洞。

如何做

1. 选扫描器接入 CI
   - Snyk(广语言支持、好修复建议)
   - Dependabot(GitHub 原生、免费、创建 PR 升版本)
   - npm audit / pnpm audit(内置、快、但上下文少)

2. 每个 PR 和主分支每晚扫
   - PR: 变更引入的新高/危 CVE 即构建失败
   - 每晚: 扫当前 lockfile,任何新 CVE 开 issue
   - 不对已存在 CVE 失败(PR 前就在)——分开追踪

3. 按可利用性而非仅严重性分类每个发现
   - 仅开发依赖(如测试运行器)中的危 CVE 生产不可利用
   - 处理用户输入的生产依赖中的中 CVE 在你上下文可能危
   - 用扫描器的可达性分析若可用(Snyk Code、OSV-Scanner)

4. 通过升级修非抑制
   - 升到修复版本;若需大升级则排期
   - 若无修复用补丁 fork、虚拟补丁(Snyk)或隔离依赖
   - 仅在有文档理由和过期日时抑制发现

5. 保持依赖列表小且新
   - 删未用依赖(depcheck、knip)——少依赖少 CVE
   - 启用 Renovate/Dependabot 保持版本新——陈旧依赖累积 CVE
   - lockfile 中固定传递依赖使子依赖升级不静默引入漏洞

示例

# .github/workflows/dependency-scan.yml
name: 依赖扫描
on: [pull_request, schedule: [{cron: "0 2 * * *"}]]  # 每晚 2 点

jobs:
  scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: snyk/actions/node@master
        env:
          SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
        with:
          args: --severity-threshold=high --fail-on=all
      # 引入新高/危 CVE 即 PR 失败。

# Dependabot 配置: .github/dependabot.yml
version: 2
updates:
  - package-ecosystem: "npm"
    directory: "/"
    schedule:
      interval: "weekly"
    open-pull-requests-limit: 10
    # Dependabot 开 PR 升版本。及时审查合并——
    # 若 CVE 危急,搁置 2 周的 PR 是 2 周暴露。

# 分类示例:
# CVE-2024-1234(危)在 [email protected]——生产用、处理用户输入
#   → 立即修: npm i [email protected]
# CVE-2024-5678(高)在 jest@29——仅开发、不在生产 bundle
#   → 排下个迭代,今天非生产风险

常见问题

  • ⚠对所有 CVE 包括已存在的失败构建使团队瘫痪——构建因传递依赖中不可修 CVE 红了数月,新 CVE 被无视,信号丢失。
  • ⚠仅扫直接依赖漏传递依赖中漏洞——log4j 漏洞在大多受影响应用中是传递的,浅扫会完全漏它。
  • ⚠把严重性当唯一分类因素——仅开发测试框架中的危 CVE 非生产风险,而生产 JSON 解析器中的中原型污染 CVE 在你应用中可能可利用。
  • ⚠无理由无过期抑制发现使扫描器变绿——抑制累积,真漏洞被藏,无人审抑制列表直到入侵。

最佳实践

  • ✓仅对变更引入的新高/危 CVE 失败 PR,已存在 CVE 追踪在单独 backlog——保持信号可行动而非淹没团队于红构建。
  • ✓用带可达性分析的扫描器(Snyk Code、OSV-Scanner)确定漏洞函数是否真在你代码中被调——不可达代码路径中的 CVE 非即时风险。
  • ✓启用 Renovate 或 Dependabot 用自动 PR 保持依赖新——减 CVE 暴露最便宜的方式是不在每个包上落后 20 个小版本。
  • ✓周期性审查和清理依赖列表(depcheck、knip)——删未用依赖永久移除其 CVE 并减扫描面。