4. 软件供应链安全:SBOM 生成与验证、依赖项扫描

好,咱们进入第四章节。软件供应链安全,说白了就是搞清楚你用的每一行代码从哪来、是谁写的、有没有藏着雷。我见过太多团队,上线前只测功能,不查依赖,结果被一个埋了三年的老漏洞一锅端。

这一章,咱们重点聊两个核心工具:SBOM(软件物料清单)和依赖项扫描。一个是“家底清单”,一个是“安检门”,缺一不可。

4.1 为什么需要 SBOM?

你想想看,一个现代应用,自己写的代码可能只占 10%,剩下 90% 都是开源组件、第三方库、框架、中间件。一旦某个底层库爆出漏洞,你连自己用了哪个版本都不知道,怎么应急?

SBOM 就是解决这个问题的。它像一张详细的购物小票,记录了软件里每个组件的名称、版本、供应商、依赖关系。有了它,漏洞通报一来,你 10 分钟就能定位到受影响的服务。

核心价值:SBOM 让“未知的依赖”变成“已知的资产”,是供应链安全的第一道防线。

我个人习惯,在项目初始化阶段就把 SBOM 生成纳入 CI/CD 流水线。不是等上线前补一张,而是每次构建都生成,版本对齐。

4.2 SBOM 的生成方式

生成 SBOM 的工具不少,我常用的是 CycloneDX 和 SPDX 两种格式。CycloneDX 更轻量,适合容器和微服务;SPDX 更全面,适合合规审计。

下面是一个用 cyclonedx-bom 工具生成 Node.js 项目 SBOM 的例子:

# 安装工具
npm install -g @cyclonedx/bom

# 在项目根目录生成 SBOM
cyclonedx-bom -o bom.json

# 查看生成的 JSON 文件
cat bom.json | jq '.components[] | {name, version, purl}'

生成的 bom.json 里会列出所有直接和传递依赖。注意看 purl 字段,它是包的唯一标识,方便后续匹配漏洞库。

格式 特点 适用场景
CycloneDX 轻量、支持容器/组件级 DevOps 流水线、微服务
SPDX 全面、含许可证信息 合规审计、法律审查
SWID ISO 标准、偏企业级 大型企业资产管理

我的经验:如果团队刚开始做,先用 CycloneDX 跑起来,别追求完美。等流程成熟了,再考虑多格式输出。

4.3 SBOM 的验证与签名

生成 SBOM 只是第一步。你怎么保证这张清单没被篡改?怎么确认它确实对应你正在运行的版本?

嗯,这里就要引入签名和验证机制。我建议用 cosign 对 SBOM 文件进行签名,然后把签名和 SBOM 一起存到 OCI 镜像仓库里。

# 使用 cosign 对 SBOM 签名
cosign sign-blob --key cosign.key bom.json > bom.json.sig

# 验证签名
cosign verify-blob --key cosign.pub --signature bom.json.sig bom.json

验证通过,说明 SBOM 是原始发布者签发的,没被中间人改过。这一步在供应链攻击频发的今天,特别重要。

注意:签名密钥要妥善保管,建议用硬件安全模块(HSM)或云 KMS 管理。我曾经见过密钥硬编码在 CI 脚本里的案例,那等于没锁门。

4.4 依赖项扫描:把 SBOM 变成行动

有了 SBOM,下一步就是扫描。扫描工具会把 SBOM 里的组件和已知漏洞数据库(如 NVD、GitHub Advisory、OSS Index)做比对,告诉你哪些组件有风险。

我常用的扫描工具有:

  • Trivy:轻量、支持容器和文件系统扫描
  • Grype:和 Syft 配合,生成 SBOM 后直接扫
  • OWASP Dependency-Check:老牌工具,Java 生态友好

下面是用 Trivy 扫描一个 SBOM 文件的命令:

# 直接扫描项目目录
trivy fs --format json --output scan-result.json ./my-project

# 或者先有 SBOM,再扫 SBOM
trivy sbom bom.json --format table

扫描结果会列出每个漏洞的 CVE 编号、严重等级、修复版本。我建议把严重和高危漏洞设为流水线阻断门禁,中危和低危走人工评审。

4.5 依赖项扫描的避坑指南

做依赖扫描几年,我踩过不少坑。挑几个典型的说说:

  • 误报太多:有些扫描工具会把“调用路径不可达”的漏洞也报出来。我建议结合 可达性分析,只关注实际被调用的代码路径。
  • 扫描频率太低:漏洞库每天更新,你一个月扫一次,等于裸奔。我习惯在每次 PR 合并前触发扫描。
  • 忽略传递依赖:很多团队只扫直接依赖,但 Log4j 那种漏洞往往藏在传递依赖里。记得开启深度扫描。

避坑指南:我曾经遇到一个项目,扫描报告显示 200 多个漏洞,团队直接躺平了。后来我们做了可达性分析,发现真正可被利用的只有 12 个。所以,别被数字吓到,要聚焦真实风险。

4.6 从 SBOM 到自动化响应

光扫描还不够,你得能自动响应。我设计过一套流水线:

  1. 代码提交 → 自动构建 → 生成 SBOM
  2. SBOM 签名 → 存入制品仓库
  3. 触发依赖扫描 → 比对漏洞库
  4. 高危漏洞 → 阻断发布 → 通知安全团队
  5. 低危漏洞 → 记录到缺陷跟踪系统

这套流程跑起来后,团队再也没出现过“上线后才发现用了有漏洞的库”这种尴尬事。

SBOM 生成与验证流程 代码提交 / PR 合并 自动构建 & 依赖解析 生成 SBOM(CycloneDX) cosign 签名 SBOM 存入 OCI 镜像仓库 Trivy 依赖扫描 关键动作 1. 每次构建生成 SBOM 2. 签名防篡改 3. 扫描阻断高危 输出产物 bom.json bom.json.sig scan-result.json

4.7 工具链整合建议

最后,我整理了一个工具链对照表,方便你根据技术栈选型:

环节 推荐工具 备注
SBOM 生成 Syft、CycloneDX CLI 支持容器、文件系统
SBOM 签名 cosign、sigstore 免费、支持 OIDC
依赖扫描 Trivy、Grype 速度快、误报率低
漏洞数据库 NVD、OSV、GitHub Advisory 建议本地缓存
策略引擎 Open Policy Agent (OPA) 自定义阻断规则

小建议:别一口气上全套。先从 SBOM 生成 + Trivy 扫描开始,跑通后再加签名和策略引擎。循序渐进,团队才跟得上。

好了,这一章的内容就是这些。SBOM 和依赖扫描是软件供应链安全的基础设施,做好了,后面的事就顺了。