贝利信息

SBOM (软件物料清单) 是什么 如何上传和解析CycloneDX/SPDX格式的XML

日期:2026-01-26 00:00 / 作者:畫卷琴夢
SBOM是软件供应链必需的成分表,CycloneDX/SPDX XML解析失败主因是非标准扩展、缺失命名空间或版本混用;应使用cyclonedx-python-lib安全解析并严格遵循v1.4/v1.5规范。

SBOM 不是附加功能,而是现代软件供应链里必须有的“成分表”——它明确列出项目所用的开源组件、版本、许可证、已知漏洞等信息。CycloneDX 和 SPDX 是当前主流的两种 SBOM 格式,XML 是它们都支持的序列化方式,但解析和上传时容易因命名空间、schema 版本或元素嵌套层级出错。

为什么 CycloneDX/SPDX 的 XML 解析常失败

根本原因不是格式本身复杂,而是实际生成的 XML 常含非标准扩展、缺失必要命名空间声明,或混用不同 spec 版本(如 CycloneDX v1.4 与 v1.5 的 bom 根元素属性不兼容)。常见报错包括:

用 Python 安全解析 CycloneDX XML

别直接用原生 xml.etree,优先用官方库 cyclonedx-python-lib,它内置 schema 校验和版本适配逻辑:

from cyclonedx.parser import XmlParser
from cyclonedx.model.bom import Bom

确保文件无 BOM,且是 UTF-8 编码

with open('sbom.xml', 'rb') as f: bom = XmlParser().parse(f)

获取所有组件名称和版本

for component in bom.components: print(f"{component.name} @{component.version}")

关键点:

上传 CycloneDX/SPDX XML 到依赖扫描平台

GitHub Dependabot、GitLab Dependency Scanning、Syft + Grype 都接受 XML,但上传路径和参数差异大:

SPDX XML 上传更受限:目前 GitHub/GitLab 原生不支持 SPDX XML 扫描,需先用 spdx-tools 转成 JSON-LD 或 tag-value 格式再传。

手动生成合规 CycloneDX XML 的最小要点

不要手动拼 XML 字符串。用 cyclonedx-python-lib 构建对象再序列化:

from cyclonedx.model import LicenseChoice, Component, Property
from cyclonedx.output import XmlOutput

c = Component( name='requests', version='2.31.0', purl='pkg:pypi/requests@2.31.0' ) c.licenses = LicenseChoice(license_expression='Apache-2.0')

bom = Bom() bom.metadata.component = c bom.components.add(c)

输出严格符合 v1.4 规范的 XML

output = Xml

Output(bom, schema_version=14) with open('sbom.xml', 'wb') as f: f.write(output.output_as_string().encode('utf-8'))

重点:

真正难的不是生成或上传,而是让每个构建环节(CI、打包、发布)自动产出带完整许可证和哈希值的 SBOM,并确保不同工具链之间 component.bom_refpurl 保持一致。一旦某处用了缩写 pkg:npm/express,另一处用了全量 pkg:npm/express@4.18.2,关联分析就断了。