SBOM 标准与格式:SPDX、CycloneDX、SWID 详解

聊 SBOM,绕不开格式问题。市面上主流的就三种:SPDX、CycloneDX 和 SWID。很多人问我该选哪个,我的回答通常是——先搞清楚它们各自长什么样,再谈选型。

这一节,我把这三种格式掰开揉碎讲清楚。你想想看,如果连 SBOM 的“语言”都不懂,后续的审计和合规工作根本没法落地。

SPDX 格式详解

SPDX(Software Package Data Exchange)是 Linux 基金会旗下的标准。它诞生得最早,2011 年就出了第一个版本。我个人习惯把它叫做“老大哥”,因为它的生态最成熟,工具链最全。

SPDX 的核心思路是:用一套统一的字段来描述软件包的名称、版本、许可证、版权信息、文件校验和等。它的文档结构像一本“户口本”,每个软件包都有一页详细的档案。

一个典型的 SPDX 文档长这样:

SPDXVersion: SPDX-2.3
DataLicense: CC0-1.0
SPDXID: SPDXRef-DOCUMENT
DocumentName: my-app-sbom
Creator: Tool: sbom-tool-1.0
Created: 2024-01-15T10:00:00Z

## Package Information
PackageName: openssl
SPDXID: SPDXRef-Package-openssl
PackageVersion: 1.1.1t
PackageDownloadLocation: https://www.openssl.org/source/openssl-1.1.1t.tar.gz
PackageLicenseConcluded: OpenSSL
PackageLicenseDeclared: OpenSSL
PackageCopyrightText: Copyright (c) 1998-2023 The OpenSSL Project

嗯,这里要注意:SPDX 的字段名是大小写敏感的,而且每个包必须有一个唯一的 SPDXID。我在项目中遇到过有人把两个包的 ID 写重复了,结果解析工具直接报错,排查了半天。

我的习惯:SPDX 的 PackageLicenseConcluded 和 PackageLicenseDeclared 是两个不同的字段。前者是你审计后得出的结论,后者是包本身声明的许可证。千万别混用,审计时会出大问题。

CycloneDX 格式详解

CycloneDX 是 OWASP 社区推出的标准。它比 SPDX 年轻,但发展很快。为什么?因为它专为“安全”而生。说白了,SPDX 更像一个“通用档案”,而 CycloneDX 从一开始就瞄准了漏洞管理和依赖分析。

CycloneDX 使用 JSON 或 XML 格式,结构更紧凑,更适合程序处理。它的核心概念是 Bom(Bill of Materials),每个组件都可以携带丰富的安全元数据,比如漏洞引用、哈希值、组件类型等。

一个典型的 CycloneDX JSON 片段:

{
  "bomFormat": "CycloneDX",
  "specVersion": "1.5",
  "version": 1,
  "components": [
    {
      "type": "library",
      "name": "openssl",
      "version": "1.1.1t",
      "purl": "pkg:generic/openssl@1.1.1t",
      "hashes": [
        {
          "alg": "SHA-256",
          "value": "a0b1c2d3e4f5..."
        }
      ],
      "licenses": [
        {
          "license": {
            "id": "OpenSSL"
          }
        }
      ]
    }
  ]
}

你看,CycloneDX 里有个 purl 字段,这是 Package URL 的缩写。它能把一个组件在全球范围内唯一标识出来。我曾经用这个字段做跨项目的依赖合并,效果非常好。

避坑指南:CycloneDX 的 specVersion 一定要写对。我见过有人用 1.4 的解析器去读 1.5 的文档,结果 services 和 formulation 这些新字段全被忽略了。版本对齐很重要。

SWID 标签介绍

SWID(Software Identification Tag)是 ISO/IEC 19770-2 标准。它跟前面两个不太一样——SWID 是 由软件安装包自带的,而不是事后生成的。你可以把它理解成软件的“身份证”,安装时就贴在软件上了。

SWID 使用 XML 格式,结构相对固定。它的核心元素是 SoftwareIdentity,里面包含名称、版本、制造商、注册表项等。SWID 最大的优势是:它跟操作系统和包管理器的集成度很高。比如 Windows 10/11 的很多系统组件都自带 SWID 标签。

一个简化的 SWID 示例:

<SoftwareIdentity
  xmlns="http://standards.iso.org/iso/19770/-2/2015/schema.xsd"
  name="OpenSSL"
  version="1.1.1t"
  versionScheme="multipartnumeric">
  <Entity
    name="OpenSSL Foundation"
    regid="regid.2023-01.openssl.org" />
  <Evidence>
    <Directory path="C:\Program Files\OpenSSL" />
  </Evidence>
</SoftwareIdentity>

SWID 的缺点也很明显:它只覆盖安装了 SWID 标签的软件。对于开源组件、自编译软件、脚本语言包,SWID 基本无能为力。所以它通常作为辅助手段,跟 SPDX 或 CycloneDX 配合使用。

三种格式对比与选型

讲完了各自的特点,我们来做个横向对比。我整理了一张表,方便你快速决策:

维度 SPDX CycloneDX SWID
标准化组织 Linux Foundation OWASP ISO/IEC
主要格式 Tag-Value / RDF / JSON JSON / XML XML
核心用途 许可证合规、版权审计 漏洞管理、依赖分析 软件资产识别、安装管理
生成方式 事后扫描生成 事后扫描生成 安装时自带
工具生态 非常成熟(FOSSology、ORT) 快速增长(Dependency-Track、Grype) 有限(OSIS、SWID Tool)
漏洞关联 需额外映射 原生支持 需额外映射
适用场景 法律合规、开源审计 DevSecOps、CI/CD 集成 企业资产管理、Windows 环境

怎么选?我个人的经验是:

  • 如果你的主要目标是许可证合规(比如要过开源审计),选 SPDX。它的许可证字段最丰富,法律团队也最认可。
  • 如果你的主要目标是漏洞管理(比如在 CI/CD 里做依赖扫描),选 CycloneDX。它跟 OWASP Dependency-Track、Grype 等工具配合得天衣无缝。
  • 如果你需要做企业级的软件资产盘点(比如 Windows 环境下的软件清单),用 SWID 作为补充。

当然,现实情况往往是混合使用。我在一个大型项目中,就同时用了 SPDX 做许可证审计,CycloneDX 做漏洞扫描,SWID 做资产登记。三种格式各司其职,互不冲突。

核心建议:不要纠结于“哪个最好”。先确定你的合规目标,再选格式。如果实在拿不准,从 CycloneDX 起步,它的学习曲线最平缓,工具链最现代。

三种格式的关系图

为了让你更直观地理解它们之间的关系,我画了一张图:

SBOM 三种标准格式关系图 SBOM 标准格式 SPDX 许可证合规 CycloneDX 漏洞管理 SWID 资产识别 说明: SPDX 侧重许可证与版权信息,CycloneDX 侧重漏洞与依赖安全,SWID 侧重安装资产识别。 三者可以共存,互不替代。实际项目中常组合使用。 选型建议 法律合规 → SPDX | 安全扫描 → CycloneDX | 资产盘点 → SWID

这张图把三种格式的核心定位和关系说清楚了。它们不是竞争关系,而是互补关系。你完全可以根据自己的场景,选择一种或多种组合使用。