SBOM 生成工具实战:Syft 与 Trivy 的硬核用法
好,咱们直接进入正题。SBOM 不是靠嘴说出来的,得靠工具一把一把生成。这一章我带你亲手操作两个最主流的工具:Syft 和 Trivy。一个专攻容器镜像,一个擅长文件系统扫描,搭配起来基本能覆盖 90% 的场景。
我个人习惯把 Syft 放在 CI 流水线的构建阶段,Trivy 放在部署前的验收环节。为什么这么安排?往下看你就明白了。
2.1 用 Syft 生成容器镜像 SBOM
Syft 是 Anchore 家的开源工具,主打一个「快」字。你给它一个镜像,它几分钟就能吐出完整的包清单。
2.1.1 安装与基础用法
安装方式很简单,我一般用一键脚本:
curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh -s -- -b /usr/local/bin
然后直接跑:
syft nginx:1.25 -o json > nginx-sbom.json
这条命令会拉取 nginx:1.25 镜像,分析里面的所有软件包,输出成 JSON 格式。你想想看,一个 Nginx 镜像里居然有 80 多个包——连 libc、zlib 这种底层库都给你列得清清楚楚。
--select-catalogers python。我在排查一个 Flask 应用漏洞时,就用这招把无关的包过滤掉,定位速度快了一倍。
2.1.2 输出格式选择
Syft 支持多种输出格式,我列个表给你对比:
| 格式 | 适用场景 | 文件大小 | 可读性 |
|---|---|---|---|
| JSON | 程序解析、入库 | 中等 | 一般 |
| SPDX JSON | 合规审计、供应链共享 | 较大 | 较好 |
| CycloneDX JSON | 漏洞管理平台对接 | 中等 | 较好 |
| Table | 人工快速查看 | 小 | 最好 |
我个人推荐生产环境用 CycloneDX JSON。为什么?因为大部分漏洞扫描工具(包括 Trivy)都原生支持这个格式,省去转换的麻烦。
2.2 用 Trivy 生成文件系统 SBOM
Trivy 大家可能更熟悉它的漏洞扫描功能,但它也能生成 SBOM。而且它支持文件系统扫描,这对那些「不能容器化」的传统应用特别有用。
2.2.1 扫描本地目录
假设你有一个 Java 项目,目录结构是标准的 Maven 项目:
trivy filesystem --format cyclonedx --output app-sbom.json ./my-java-app
这条命令会扫描 ./my-java-app 目录下的所有文件,识别出 pom.xml 里声明的依赖,以及 lib/ 目录下的 JAR 包。我记得有一次帮客户做合规审计,他们有个 10 年历史的单体应用,就是用 Trivy 的文件系统模式扫出了 200 多个过时的库。
.git 目录和 node_modules(如果太大)。如果你需要扫描这些目录,得加 --scanners filesystem 参数。我曾经因为漏扫 node_modules,导致一个原型污染漏洞没被发现,后来补上的时候差点被运维同事骂死。
2.2.2 扫描容器镜像(对比 Syft)
Trivy 也能扫镜像,但和 Syft 的侧重点不同:
- Syft:专注 SBOM 生成,速度快,格式规范,适合 CI 构建阶段。
- Trivy:SBOM 生成 + 漏洞扫描二合一,适合验收阶段。
我通常这样搭配:Syft 在构建时生成 SBOM 并存入数据库,Trivy 在部署前拿着这个 SBOM 去查漏洞。这样既保证了 SBOM 的完整性,又避免了重复扫描。
2.3 SBOM 格式解析:JSON 与 XML
生成 SBOM 只是第一步,读懂它才是关键。咱们拿一个实际的 CycloneDX JSON 片段来拆解:
{
"bomFormat": "CycloneDX",
"specVersion": "1.4",
"version": 1,
"components": [
{
"type": "library",
"name": "openssl",
"version": "1.1.1k",
"purl": "pkg:generic/openssl@1.1.1k",
"licenses": [
{
"license": {
"id": "OpenSSL"
}
}
],
"supplier": {
"name": "OpenSSL Software Foundation"
}
}
]
}
这里有几个关键字段你得记住:
- bomFormat:格式标识,CycloneDX 或 SPDX。
- components:组件列表,每个组件包含名称、版本、类型。
- purl:包统一资源定位符,这是跨工具识别的关键。说白了,有了 purl,Trivy 才能知道这个包对应哪个 CVE。
- licenses:许可证信息,合规审计时必看。
2.3.1 JSON vs XML:怎么选?
| 维度 | JSON | XML |
|---|---|---|
| 解析速度 | 快(原生支持) | 慢(需 DOM/SAX 解析) |
| 可读性 | 好 | 一般(标签多) |
| 工具支持 | 几乎所有语言都有库 | 传统工具支持好 |
| 文件大小 | 小 | 大(冗余标签) |
| Schema 验证 | 较弱 | 强(XSD) |
我的建议是:新项目无脑选 JSON。除非你的合规部门要求必须用 XML 格式归档,否则 JSON 在性能和易用性上都完胜。
2.4 本章知识体系总览
下面这张图帮你理清 Syft 和 Trivy 在整个 SBOM 生命周期中的位置:
2.5 避坑指南与最佳实践
最后分享几个我踩过的坑,你遇到了能少走弯路:
有一次我用 Syft 扫描一个基于 Alpine 的自定义镜像,发现少了几个包。后来排查发现是 Docker 构建缓存导致的——基础镜像层没更新,Syft 只扫到了新增层。解决方案:构建时加
--no-cache 参数,或者用 syft <image> --scope all-layers 强制扫描所有层。
扫描
/usr/lib 这种系统目录时,Trivy 可能会因为权限不足而跳过某些文件。我曾经在 CI 里用普通用户跑扫描,结果漏掉了几个系统库的漏洞。后来改成 sudo trivy filesystem 才解决。但注意,生产环境别随便给 sudo,建议用专门的扫描容器。
不同工具对 CycloneDX 版本的支持不一样。Syft 默认输出 1.4,但有些老版本的漏洞管理平台只认 1.2。我建议统一用
--output cyclonedx-json=1.4 指定版本,并在平台侧做好兼容性测试。