SBOM 标准与格式:SPDX、CycloneDX、SWID 深度解析
聊 SBOM,绕不开格式问题。就像写病历要用统一模板,不同医院才能看懂。SBOM 也一样——格式不统一,上下游根本没法协作。
目前主流的三种格式:SPDX、CycloneDX、SWID。我这些年做供应链安全,三种都踩过坑。今天把它们的核心逻辑、适用场景、以及我个人的选型经验,一次性说清楚。
SPDX 标准详解
SPDX(Software Package Data Exchange)是 Linux 基金会维护的标准。它最早关注的是许可证合规——说白了,就是帮你搞清楚项目里用了哪些开源组件,它们的许可证能不能兼容。
我记得刚入行那会儿,公司有个产品因为用了 GPL 的库,差点被法务叫停。那时候要是早用 SPDX,根本不会出这种问题。
SPDX 的核心结构
一个 SPDX 文档包含几个关键部分:
- 文档元信息:创建者、创建时间、文档命名空间
- 包信息:包名、版本、下载位置、校验和
- 文件信息:每个文件的许可证、版权、贡献者
- 许可证信息:引用的许可证列表,包括自定义许可证
- 关系:包与包、文件与包之间的依赖关系
SPDX 2.3 版本新增了安全参考字段,可以直接关联 CVE 编号。这意味着 SPDX 不再只是许可证工具,也开始涉足安全领域了。
来看一个简化的 SPDX JSON 示例:
{
"spdxVersion": "SPDX-2.3",
"dataLicense": "CC0-1.0",
"SPDXID": "SPDXRef-DOCUMENT",
"name": "my-app-1.0.0",
"packages": [
{
"SPDXID": "SPDXRef-Package-log4j",
"name": "log4j",
"versionInfo": "2.17.1",
"licenseDeclared": "Apache-2.0",
"checksums": [
{
"algorithm": "SHA256",
"checksumValue": "a1b2c3d4e5..."
}
]
}
],
"relationships": [
{
"spdxElementId": "SPDXRef-DOCUMENT",
"relatedSpdxElement": "SPDXRef-Package-log4j",
"relationshipType": "DESCRIBES"
}
]
}
我的习惯:生成 SPDX 时,一定把 licenseDeclared 和 licenseConcluded 都填上。前者是组件声明的许可证,后者是你审计后确认的。两者不一致的情况,我见过太多次了。
CycloneDX 标准详解
CycloneDX 是 OWASP 社区推出的标准。它的定位很明确——为安全而生。如果你主要关心漏洞管理、依赖风险,CycloneDX 会更顺手。
我曾经帮一个金融客户做软件供应链审计,他们要求每个组件必须关联 CVE。SPDX 当时还不支持这个,CycloneDX 直接原生支持,省了我不少事。
CycloneDX 的核心特性
- 组件依赖图:支持
dependsOn关系,能画出完整的依赖树 - 漏洞引用:直接嵌入
vulnerabilities数组,关联 CVE、CVSS 评分 - 服务组件:不光能描述软件包,还能描述 API、微服务
- 轻量级:默认 JSON 格式,解析快,适合 CI/CD 流水线
CycloneDX 的依赖关系描述非常直观:
{
"bomFormat": "CycloneDX",
"specVersion": "1.4",
"components": [
{
"type": "library",
"name": "jackson-databind",
"version": "2.13.2",
"purl": "pkg:maven/com.fasterxml.jackson.core/jackson-databind@2.13.2"
}
],
"dependencies": [
{
"ref": "pkg:maven/my-app/my-app@1.0.0",
"dependsOn": [
"pkg:maven/com.fasterxml.jackson.core/jackson-databind@2.13.2"
]
}
],
"vulnerabilities": [
{
"id": "CVE-2022-25647",
"source": {
"name": "NVD",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2022-25647"
},
"ratings": [
{
"score": 7.5,
"severity": "high"
}
]
}
]
}
我曾经踩过的坑:CycloneDX 的 purl(Package URL)格式必须严格规范。少写一个斜杠,或者类型写错,解析器直接报错。建议用工具自动生成,别手写。
SWID 标签介绍
SWID(Software Identification)标签是 ISO 19770-2 标准。它跟 SPDX、CycloneDX 不太一样——SWID 更关注软件的身份和安装状态。
你想想看,IT 资产管理团队要统计公司装了多少软件、哪些需要升级。SWID 就是干这个的。它由软件发布商生成,嵌入安装包中。
SWID 的核心结构
- 实体信息:软件发布商、版本、唯一 ID
- 元数据:安装路径、大小、校验和
- 链接关系:补丁、更新包、依赖组件
- 签名:数字签名保证标签未被篡改
SWID 标签通常以 XML 格式存在:
<SoftwareIdentity
xmlns="urn:iso:std:iso:19770:-2:2015"
name="MyApp"
version="1.0.0"
tagId="com.example.myapp-1.0.0">
<Entity name="Example Corp" role="softwareCreator"/>
<Meta persistentId="com.example.myapp"/>
<Link rel="patch" href="https://updates.example.com/patch-1.0.1.swid"/>
</SoftwareIdentity>
实际场景:SWID 在 Windows 生态里用得比较多。微软的 MSI 安装包默认就带 SWID 标签。Linux 下反而少见,更多用 SPDX 或 CycloneDX。
三种格式的对比与选型
三种格式各有侧重,没有绝对的「最好」。我一般根据场景来选:
| 维度 | SPDX | CycloneDX | SWID |
|---|---|---|---|
| 维护组织 | Linux Foundation | OWASP | ISO/IEC |
| 核心关注点 | 许可证合规 | 安全漏洞 | 软件身份 |
| 格式支持 | JSON / XML / RDF / Tag | JSON / XML | XML |
| 依赖关系 | 支持(关系类型丰富) | 支持(依赖树清晰) | 有限(主要补丁关系) |
| 漏洞关联 | 2.3 版本开始支持 | 原生支持 | 不支持 |
| 许可证描述 | 非常详细 | 基础支持 | 不支持 |
| 工具生态 | 成熟(FOSSology、ORT) | 活跃(OWASP 工具链) | 企业级(微软、IBM) |
选型建议
我个人习惯这样选:
- 做开源合规审计 → 选 SPDX。它的许可证描述能力最强,法务团队也认。
- 做安全漏洞管理 → 选 CycloneDX。原生漏洞关联,CI/CD 集成最方便。
- 做企业 IT 资产盘点 → 选 SWID。Windows 环境天然支持,省去生成成本。
- 通用场景 → SPDX + CycloneDX 组合。我现在的项目就是两套都生成,各取所长。
一句话总结:SPDX 管「能不能用」,CycloneDX 管「安不安全」,SWID 管「装没装」。搞清楚这个,选型就不会错。