SBOM 标准与格式:三大主流规范深度解析
做 SBOM 这几年,我接触过不少团队。大家最常问的一个问题是:「SBOM 到底该用什么格式?」
说实话,这个问题没有标准答案。但有三套格式,你绕不开——SPDX、CycloneDX 和 SWID。它们就像嵌入式世界的三种「方言」,各有各的生态位。今天我就把这三套东西掰开揉碎了讲清楚。
核心观点: 选格式不是选「最好的」,而是选「最适合你设备安全场景的」。SPDX 强在许可证合规,CycloneDX 强在安全上下文,SWID 强在软件身份标识。
SPDX:许可证合规的老大哥
SPDX(Software Package Data Exchange)是 Linux 基金会旗下的项目。我最早接触它是在 2015 年,那时候它主要解决一个痛点:开源软件的许可证到底怎么追踪?
SPDX 的核心思路很直接——给每个软件包打上标签,记录它的许可证、版权信息、文件清单。你想想看,一个嵌入式设备里可能集成了几十个开源组件,GPL、MIT、Apache 混在一起,没有 SPDX 你根本理不清。
我的经验: 在 IoT 设备合规审计中,SPDX 几乎是标配。我曾经帮一家客户梳理他们的路由器固件,用 SPDX 格式导出了 47 个组件的许可证信息,审计方直接认可,省掉了大量人工核对时间。
SPDX 目前最新版本是 2.3,支持 JSON、YAML、RDF/XML 等多种序列化格式。它的核心元素包括:
- SPDX Document:整个 SBOM 的容器,包含元数据
- Package Information:每个软件包的名称、版本、下载位置
- File Information:文件级别的校验和、许可证
- Snippet Information:代码片段的许可证信息(这个很实用)
- Relationship:包与包之间的依赖关系
// SPDX 2.3 JSON 示例片段
{
"spdxVersion": "SPDX-2.3",
"dataLicense": "CC0-1.0",
"SPDXID": "SPDXRef-DOCUMENT",
"name": "iot-firmware-v1.2",
"packages": [
{
"SPDXID": "SPDXRef-Package-libcurl",
"name": "libcurl",
"versionInfo": "7.79.1",
"licenseConcluded": "MIT",
"licenseDeclared": "MIT",
"copyrightText": "Copyright (c) 1996 - 2021, Daniel Stenberg, <daniel@haxx.se>"
}
]
}
注意: SPDX 的许可证字段有 licenseConcluded 和 licenseDeclared 两个。前者是你经过分析后得出的结论,后者是组件自己声明的。我见过有人把这两个搞混,审计时出了大问题。
CycloneDX:安全上下文的一把好手
CycloneDX 是 OWASP 社区推出的标准。说实话,我一开始对它不太感冒——觉得 SPDX 已经够用了。但后来做设备安全漏洞管理时,我发现 CycloneDX 在安全上下文这块确实有两把刷子。
CycloneDX 的设计哲学是「轻量 + 安全」。它原生支持:
- 漏洞引用:直接关联 CVE、NVD、OSS Index 等漏洞库
- 组件类型:区分应用、库、操作系统、固件、硬件等
- 服务组件:描述微服务、API 等运行时依赖
- 加密资产:记录算法、密钥长度等加密信息
你想想看,在嵌入式设备里,一个组件可能有多个版本,每个版本对应不同的 CVE。CycloneDX 的 vulnerabilities 字段可以直接把 CVE 列表嵌进去,省掉了二次关联的麻烦。
// CycloneDX 1.4 JSON 示例片段
{
"bomFormat": "CycloneDX",
"specVersion": "1.4",
"serialNumber": "urn:uuid:3e671687-395b-41f5-a30f-a58921a69b79",
"components": [
{
"type": "library",
"name": "openssl",
"version": "1.1.1l",
"purl": "pkg:generic/openssl@1.1.1l",
"properties": [
{
"name": "device:target",
"value": "arm-cortex-m4"
}
]
}
],
"vulnerabilities": [
{
"id": "CVE-2022-0778",
"source": {
"name": "NVD",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2022-0778"
},
"ratings": [
{
"severity": "high",
"score": 7.5
}
]
}
]
}
关键差异: CycloneDX 使用 purl(Package URL)作为组件标识,而 SPDX 使用自定义的 SPDXID。purl 的好处是标准化程度更高,方便跨工具链对接。
SWID:软件身份的设备级身份证
SWID(Software Identification Tag)是 ISO/IEC 19770-2 标准。它跟 SPDX 和 CycloneDX 不太一样——SWID 更关注「安装后的软件身份」。
我记得第一次在嵌入式设备上部署 SWID 标签时,感觉它就像给每个软件组件发了一张「身份证」。这张身份证记录了:
- 软件的唯一标识(regid + 名称 + 版本)
- 安装路径和文件清单
- 父级软件和子级组件的关系
- 数字签名(用于验证标签真实性)
SWID 在 Windows 生态里用得比较多,但在嵌入式 Linux 和 RTOS 里也有应用场景。比如,你可以在设备出厂时生成 SWID 标签,写入设备的安全存储区。后续做远程设备资产盘点时,直接读取 SWID 标签就能知道设备上装了哪些软件。
<!-- SWID XML 示例片段 -->
<SoftwareIdentity
xmlns="http://standards.iso.org/iso/19770/-2/2015/schema.xsd"
tagId="com.example.iot-gateway-v2.1"
name="IoT Gateway Firmware"
version="2.1.0"
versionScheme="multipartnumeric">
<Entity name="Example Corp" regid="regid.2024-05.com.example" role="tagCreator"/>
<Evidence>
<Directory path="/usr/local/bin"/>
<File name="gatewayd" size="2456789">
<Hash type="SHA256">a1b2c3d4e5f6...</Hash>
</File>
</Evidence>
<Payload>
<Directory root="/usr/local/bin"/>
<File name="gatewayd"/>
<File name="config-parser"/>
</Payload>
</SoftwareIdentity>
避坑指南: 我曾经在一个项目里直接用 SWID 标签做漏洞匹配,结果发现 SWID 的版本号格式五花八门——有的用 2.1.0,有的用 v2.1.0,还有的用 2.1.0.1234。后来我强制团队统一使用 multipartnumeric 版本方案,才解决了这个问题。
三种格式的硬核对比
好了,三种格式都介绍完了。下面这张表是我在实际项目中总结的对比,你可以直接拿去用:
| 对比维度 | SPDX | CycloneDX | SWID |
|---|---|---|---|
| 标准化组织 | Linux Foundation | OWASP | ISO/IEC |
| 核心用途 | 许可证合规 | 安全漏洞管理 | 软件身份标识 |
| 序列化格式 | JSON, YAML, RDF/XML, Tag/Value | JSON, XML, Protobuf | XML(强制) |
| 组件标识 | SPDXID(自定义) | purl(标准化) | regid + 名称 + 版本 |
| 漏洞关联 | 外部引用(ExternalRef) | 原生内嵌(vulnerabilities) | 不支持 |
| 许可证支持 | ★★★★★ 最全面 | ★★★☆☆ 基础支持 | ★★☆☆☆ 有限 |
| 设备端适配 | ★★★☆☆ 文件较大 | ★★★★☆ 轻量灵活 | ★★★★★ 原生安装标记 |
| 数字签名 | 支持(外部签名) | 支持(外部签名) | 原生内嵌签名 |
| 典型场景 | 开源合规审计 | CI/CD 安全扫描 | 设备资产盘点 |
怎么选?我的建议
说实话,没有银弹。但我可以给你一个决策框架:
- 如果你的主要痛点是许可证合规(比如产品要过开源审计),选 SPDX。它的许可证字段最丰富,审计方也最认可。
- 如果你的主要痛点是安全漏洞管理(比如要对接 VEX、CSAF),选 CycloneDX。它的漏洞上下文最完整,而且支持
bom-ref交叉引用。 - 如果你的主要痛点是设备资产盘点(比如要远程识别设备上的软件),选 SWID。它原生支持安装路径、文件哈希和数字签名。
- 如果你要做全链路(合规 + 安全 + 资产),我建议 SPDX + CycloneDX 双格式输出。我在一个智能家居项目里就是这么干的——SPDX 给法务,CycloneDX 给安全团队,各取所需。
一个小技巧: 在嵌入式设备上,SWID 标签可以做得非常小——一个 XML 文件几百字节。我曾在只有 64KB Flash 的 MCU 上成功部署过 SWID 标签,配合安全存储区,实现了设备级的软件身份认证。