十年前,一家公司发布一个 Java
应用,合规团队会问:“你们用了什么第三方库?”开发会打开
pom.xml,数一数 direct
dependencies,大概是二十几个,回一份 Excel 就算交差。
今天你再问同样的问题,答案是:我们也不知道。
一个普通的 Spring Boot 微服务,直接依赖十几个,间接依赖(transitive dependency)往往超过 400 个,这些间接依赖跨越至少七八种开源许可证,每周有若干个新的 CVE 披露,每天都有版本更新。没有人能靠人力维护这张清单。
软件成分分析(Software Composition Analysis,SCA) 和 软件物料清单(Software Bill of Materials,SBOM) 就是为了回答”你到底用了什么”这个问题而生的工程体系。它已经从 2015 年前后小众合规厂商的产品,演进成 2021 年美国总统行政令(Executive Order 14028)明文要求、2024 年欧盟《网络弹性法案》(Cyber Resilience Act,CRA)立法背书的基础设施。
如果你还没读过本系列前面的许可证知识,建议先看:
本文假设你已经理解 MIT、Apache-2.0、GPL、AGPL、SSPL 的基本差异,聚焦在”怎么用工具把这些许可证和漏洞信息自动化地管起来”。
一、为什么成分分析变成了强制课题
2014 年的 Heartbleed、2015 年的 Shellshock、2017 年的 Equifax 数据泄露(起因是未升级的 Apache Struts CVE-2017-5638)、2020 年 SolarWinds 供应链攻击、2021 年 Log4Shell(CVE-2021-44228)——这一连串事件的共同规律是:受害企业并不知道自己用了什么版本的什么组件。
Log4Shell 爆发的那一周,安全团队第一件事不是打补丁,而是”先找一下我们哪里用了 Log4j”。很多公司花了两到三周才把自己家里的 Log4j 实例全部枚举清楚。原因是 Log4j 经常被另一个库间接引入,而那个库又被另一个库间接引入,在 fat-JAR、容器镜像、嵌入式 agent 中层层嵌套。
这件事直接催生了 2021 年 5 月拜登政府的行政令 EO 14028(Improving the Nation’s Cybersecurity),其中第 4(e) 条款明确要求联邦政府采购的软件必须提供 SBOM。美国商务部国家电信和信息管理局(NTIA)随后发布了《SBOM 最小元素》(The Minimum Elements For a Software Bill of Materials,2021 年 7 月),定义了 SBOM 必须包含的七项数据字段。
欧盟紧随其后。2024 年 10 月通过、2027 年底全面生效的《网络弹性法案》(CRA)对”带数字元素的产品”施加了强制安全义务,其中附件一明确要求制造商”识别并记录产品中包含的组件与漏洞”,行业普遍理解为必须提供 SBOM。
中国方面,等保 2.0(GB/T 22239-2019)在应用安全通用要求里含蓄地要求”对应用系统中使用的开发框架、第三方软件进行管理”;工信部 2022 年发布的《网络产品安全漏洞管理规定》要求厂商对自身及第三方组件漏洞承担披露义务;2023 年后陆续出现的关键信息基础设施(关基)采购指南明确提出”供方应随产品交付软件成分清单”。
换言之,SBOM 在国内外都已经从”加分项”变成”准入门槛”。
除了合规压力,工程侧本身也有刚需。过去十年开源依赖图谱的爆炸式增长有几个数据可以参考:
- npm 注册的包数量从 2014 年约 10 万个增长到 2024 年底超过
350 万个。一个普通 React 应用
node_modules目录下解压后的文件数通常在 20 万到 100 万级别。 - Maven Central 累计制品数在 2024 年越过 1000 万大关,累计下载超过 8000 亿次。
- Python PyPI 包数量 2024 年底约 55 万,年新增约 6 万个。
- Go 生态因其扁平模块系统相对节制,但一个中等规模的
Kubernetes 周边项目
go.sum达到 300–500 行已属常态。
在这种规模下,人工维护依赖清单早已失效。即使你愿意给每个直接依赖标注许可证,传递依赖的数量也会以指数级扩展。比较出名的统计是 Tidelift 2021 年报告:一个中等规模应用的开源组件中,超过 80% 是传递依赖,开发者主动选择的直接依赖往往只是冰山一角。
对版权律师而言,SBOM 是开源合规取证的唯一可行路径;对 CISO 而言,SBOM 是 0-day 响应速度的决定性资产;对 DevOps 团队而言,SBOM 是”升不升版本”的决策依据;对采购与审计而言,SBOM 是合同附件。一份 SBOM 同时服务这四类角色,这也是它能迅速制度化的根本原因。
二、SCA 的工作原理
SCA 这个词有时会被理解成”扫一下代码生成一份 Excel”。但工业级 SCA 系统通常有四个层次。
2.1 依赖发现层
这一层回答”项目里有哪些组件”。
最幼稚的做法是解析包管理器的锁文件——pom.xml、package-lock.json、Pipfile.lock、go.sum、Cargo.lock、composer.lock
等。这种方式快、准,但只覆盖”你声明的依赖”,不覆盖:
- 以 vendored 源码形式复制进仓库的组件(如直接把 zlib 的 C
源码放到
third_party/)。 - 构建期动态下载的组件(某些 Makefile 会在构建时
curl一个库)。 - 容器基础镜像内已经安装的系统库(glibc、OpenSSL、BusyBox)。
- 通过 UPX 壳或静态链接打包到二进制里的库。
工业级工具必须同时支持三条路径:
- 清单解析(manifest-based):读锁文件。
- 文件系统扫描(filesystem scan):遍历目录,对每个文件做指纹。
- 二进制分析(binary analysis):对已编译的 ELF、PE、Mach-O、WASM 做符号匹配、字符串匹配、机器学习特征匹配。
Black Duck 的 Knowledge Base、FOSSA 的 Revere 引擎、Syft 的 cataloger 插件都属于第 2、3 层。
2.2 许可证识别层
这一层回答”这个组件是什么许可证”。
SPDX license list(截至 2025 年收录约 660 个许可证 ID)是产业共识的词汇表。识别手段:
- 元数据读取:npm 包的
package.json有license字段,Maven 有<licenses>,Go module 的go.mod无此字段(这是 Go 生态的痛点)。 - 文件名启发式:
LICENSE、LICENSE.txt、COPYING、COPYING.LESSER、NOTICE。 - 文本指纹与相似度:ScanCode Toolkit 把每个 SPDX 许可证的正文做 n-gram 指纹,对源码中的注释、头文件块做模糊匹配,输出置信度分数。
- 声明与文件冲突检测:有些项目
package.json写 MIT,但代码里带 GPL-2.0 的头文件——这通常意味着有人违规复制代码,必须人工复核。
ScanCode 是这一层事实上的开源标杆,Black Duck、FOSSA、Mend 也都有自研的识别引擎。
一个经常被忽视的问题是许可证声明与源码不一致。举几类常见情形:
- 一个 npm 包
package.json声明MIT,但其中一个源文件顶部的注释写着”This file is licensed under GPL-2.0”。这个文件很可能是早年从 Linux 内核复制粘贴过来的,当前仓库里就是一颗法律地雷。 - 一个开源库的
LICENSE目录下同时放了LICENSE.MIT、LICENSE.Apache、LICENSE.GPL,但没有LICENSE总声明。这种 “multi-licensed” 情况要求使用方主动选择一个许可证——默认使用等于同时接受三份合约,在实务中通常选择最宽松的那个,但需保留选择证据。 - NOTICE 文件里列出”本软件使用了 xxx 库”,却没在
dependency 里声明——这是典型的 vendored
代码,扫描工具必须能覆盖到
third_party/、vendor/、external/这些目录。
因此许可证识别层在企业环境里通常需要双轨:一条快速路径(读元数据)用于 CI 阻断,一条慢速路径(全文扫描)用于合规审阅。
2.3 漏洞关联层
这一层回答”这些组件有没有已知漏洞”。
主要数据源:
- NVD(National Vulnerability Database,美国 NIST 维护,CVE 的权威元数据)。
- GHSA(GitHub Security Advisory,覆盖面远超 NVD 且响应更快)。
- OSV.dev(Google 发起,聚合 PyPI、npm、Go、RubyGems、Maven Central、Packagist、crates.io、OSS-Fuzz 的统一格式漏洞数据库)。
- CNVD / CNNVD(中国国家漏洞库,部分覆盖国内软件)。
- 商业厂商自研数据源(Snyk DB、Black Duck BDSA、Sonatype Data Research)。
关联的关键是 PURL(Package URL,RFC
草案),形如
pkg:maven/org.apache.logging.log4j/log4j-core@2.14.1。一个稳定的
PURL 能唯一标识”哪个生态的哪个包的哪个版本”,SBOM
工具与漏洞库都围绕 PURL 对齐。
与 PURL 并列的还有 CPE(Common Platform
Enumeration),形如
cpe:2.3:a:apache:log4j:2.14.1:*:*:*:*:*:*:*。CPE
是 NVD 早期使用的标识符,痛点是:NVD 分析员需要人工给每个
CVE 分配 CPE;同一个包经常有几个相近但不同的 CPE
字符串,匹配规则容易遗漏;CPE 与 PURL 之间没有官方 1:1
映射。2024 年 NVD 分析延迟恶化后,纯 CPE
匹配路线的误报和漏报问题更加突出,PURL-first
已经成为新系统的默认选择。
除数据源本身的覆盖差异外,关联还要处理版本范围语义。同一个
CVE 可能写成
< 2.17.0、>= 2.0, < 2.15.0、affected: 2.14.x,不同生态(Maven
的区间语法、npm semver、Debian 的
dpkg --compare-versions)语义不一致。工业级 SCA
往往要为每种生态写独立的版本比较器。这也是为什么 Trivy/Grype
这类扫描器会维护一张各生态的 canonical 版本比较实现。
2.4 策略执行层
这一层回答”发现了风险怎么办”。常见策略规则:
- 禁止引入 AGPL-3.0、SSPL-1.0(除非走白名单审批)。
- 禁止引入 CVSS ≥ 7.0 且已有补丁的组件。
- 禁止引入 EOL 超过 12 个月的组件(如 Python 3.6、Node 14)。
- 仅允许来自可信 registry(公司内部镜像源)的包。
实现手段包括在 CI 中阻断流水线、在 PR 上留评论、在 Dependency-Track 中发告警、在制品库(Artifactory、Nexus)中设拦截规则。OPA(Open Policy Agent)的 Rego 语言和 CycloneDX 的 “License Expression” 字段可以把策略写成声明式代码。
策略层最常犯的错误是一刀切。同一个许可证(如 LGPL-2.1)在不同产品形态下的触发条件完全不同:作为 SaaS 后端使用基本无传染义务,静态链接进嵌入式固件分发就必须开源修改或提供可替换机制。一个成熟的策略引擎需要把”产品形态(分发/SaaS/内部工具)“作为输入维度,否则只能退化为”禁所有 Copyleft”这种一刀切,既杀错又挡不住真风险。关于这个话题展开见 Copyleft 工程边界。
三、SBOM:软件物料清单
SBOM 是 SCA 的输出契约。SCA 是过程,SBOM 是结果文档。目前主流有两套格式。
3.1 SPDX(Linux 基金会)
SPDX(Software Package Data Exchange)由 Linux 基金会于 2010 年发起,2021 年以 ISO/IEC 5962:2021 成为国际标准。它的定位是”许可证合规交换”,许可证表达能力最强。
SPDX 2.3(2022 年发布)支持 Tag-Value、RDF、JSON、YAML、Spreadsheet 多种序列化。核心概念:
- Package:一个交付物单元。
- File:包内的单个文件,可分别记录许可证。
- Snippet:文件内的代码片段(用于记录”这一段来自 OpenSSL”)。
- Relationship:包之间的关系(DEPENDS_ON、CONTAINS、STATIC_LINK、DYNAMIC_LINK、BUILD_TOOL_OF 等)。
- License Expression:SPDX 表达式语言,如
Apache-2.0 OR MIT、(GPL-2.0-only WITH Classpath-exception-2.0)。
SPDX 3.0(2024 年发布)做了较大结构重构,拆成 Core、Software、Security、Licensing、Build、AI、Dataset 等 profile,未来可以同时承载 SBOM、AI-BOM(AI 模型物料清单)、Dataset-BOM(数据集清单)。
一个极简的 SPDX 2.3 Tag-Value 片段示例:
SPDXVersion: SPDX-2.3
DataLicense: CC0-1.0
SPDXID: SPDXRef-DOCUMENT
DocumentName: my-service-1.4.2
DocumentNamespace: https://example.com/spdx/my-service-1.4.2-abc123
Creator: Tool: syft-1.12.0
Created: 2026-04-01T09:00:00Z
PackageName: log4j-core
SPDXID: SPDXRef-Package-log4j-core-2.17.1
PackageVersion: 2.17.1
PackageDownloadLocation: https://repo.maven.apache.org/maven2/org/apache/logging/log4j/log4j-core/2.17.1/log4j-core-2.17.1.jar
PackageLicenseConcluded: Apache-2.0
PackageLicenseDeclared: Apache-2.0
PackageCopyrightText: Copyright (c) Apache Software Foundation
ExternalRef: PACKAGE-MANAGER purl pkg:maven/org.apache.logging.log4j/log4j-core@2.17.1
Relationship: SPDXRef-Package-my-service DEPENDS_ON SPDXRef-Package-log4j-core-2.17.1
LicenseConcluded 与
LicenseDeclared
的区别很关键:Declared 是工具从 metadata
读到的声明,Concluded
是人工或扫描器综合各种证据得出的结论。两者不一致时,审阅员应以
Concluded 为准并留下理由。
3.2 CycloneDX(OWASP)
CycloneDX 由 OWASP 于 2017 年发起,定位更偏”应用安全”。它的 schema 更简洁,对漏洞、VEX、服务、依赖图谱支持较早。
截至 2024 年 CycloneDX 1.6 支持:
- components:库、容器、操作系统、设备、文件、机器学习模型、数据。
- dependencies:显式依赖图。
- vulnerabilities:内嵌 CVE 信息与 CVSS。
- VEX(Vulnerability Exploitability eXchange):声明”这个 CVE 在我的产品里不可利用”的机制。
- formulation:记录构建过程(Build-BOM)。
- ML-BOM:描述模型、训练数据、考量。
CycloneDX 原生 JSON、XML、Protobuf,社区工具链(cdxgen、Dependency-Track)围绕它搭建。
对应的 CycloneDX 1.5 片段:
{
"bomFormat": "CycloneDX",
"specVersion": "1.5",
"serialNumber": "urn:uuid:3e671687-395b-41f5-a30f-a58921a69b79",
"version": 1,
"metadata": {
"timestamp": "2026-04-01T09:00:00Z",
"tools": [{"vendor": "anchore", "name": "syft", "version": "1.12.0"}],
"component": {
"type": "application",
"bom-ref": "pkg:maven/com.example/my-service@1.4.2",
"name": "my-service",
"version": "1.4.2"
}
},
"components": [
{
"type": "library",
"bom-ref": "pkg:maven/org.apache.logging.log4j/log4j-core@2.17.1",
"group": "org.apache.logging.log4j",
"name": "log4j-core",
"version": "2.17.1",
"purl": "pkg:maven/org.apache.logging.log4j/log4j-core@2.17.1",
"licenses": [{"license": {"id": "Apache-2.0"}}]
}
],
"dependencies": [
{
"ref": "pkg:maven/com.example/my-service@1.4.2",
"dependsOn": ["pkg:maven/org.apache.logging.log4j/log4j-core@2.17.1"]
}
]
}CycloneDX 的 bom-ref 是 BOM
内部的引用锚点,通常直接复用
PURL,这让图谱构建变得极简。
3.3 两格式对比
| 维度 | SPDX | CycloneDX |
|---|---|---|
| 发起方 | Linux 基金会 | OWASP |
| 国际标准 | ISO/IEC 5962:2021 | ECMA-424(2024) |
| 主要定位 | 许可证合规交换 | 应用安全与漏洞 |
| 许可证表达 | 最完整(SPDX Expression 是业界事实标准) | 引用 SPDX ID |
| 漏洞/VEX | 3.0 新增 Security profile | 原生一等公民 |
| 序列化 | Tag-Value、JSON、YAML、RDF、XLSX | JSON、XML、Protobuf |
| 文件粒度 | 支持 File、Snippet | 默认 Component 级 |
| 工具生态 | FOSSology、ORT、tern、spdx-tools | cdxgen、Dependency-Track、CycloneDX CLI |
| 与 PURL | 2.3 起支持 | 1.0 起原生 |
| AI/数据 | 3.0 Profile | 1.5+ ML-BOM |
实践建议:
- 对外交付合规用 SPDX(政府采购、律师审阅、开源基金会更认)。
- 对内安全运营用 CycloneDX(与 Dependency-Track、VEX、漏洞库联动最顺)。
- 两者可互转,Syft、cdxgen、CycloneDX CLI 都支持双向输出。
值得单独说明的是 VEX(Vulnerability Exploitability eXchange)。VEX 不是 SBOM 的替代品,而是补丁——当 SBOM 告诉你”我用了 Log4j 2.14.0”,VEX 回答”这个 Log4j 在我的产品里的 JNDI 查找功能被禁用,CVE-2021-44228 不可利用”。CycloneDX 1.4 起把 VEX 纳入一等公民,CISA 也发布了独立的 VEX 规范(Common Security Advisory Framework / CSAF VEX)。在给下游客户交付 SBOM 时,SBOM + VEX 成对交付才能避免客户被一堆”其实不受影响的 CVE”淹没。
四、商业工具详解
商业 SCA 市场格局在 2020 年后发生了明显分化:一部分以开发者体验为卖点(Snyk、FOSSA),一部分仍固守”法律合规 + 审计报告”的老护城河(Black Duck、Sonatype),一部分挤在中间(Mend、Veracode SCA、Checkmarx SCA)。Gartner 的 AST(Application Security Testing)魔力象限里 SCA 近年基本稳定在这几家。下面逐一拆解。
4.1 Snyk
以色列起家,2015 年成立,2022 年估值一度达 76 亿美元(后有回调)。产品线覆盖 SCA(Snyk Open Source)、SAST(Snyk Code)、容器(Snyk Container)、IaC(Snyk IaC)。
特点:
- 开发者体验做得最好,IDE 插件(VS Code、JetBrains)是差异化卖点。
- 漏洞数据库 Snyk Intel 自研,响应速度通常快于 NVD 几天到几周。
- 对 JavaScript、Python、Java 生态覆盖最全,Go、Rust 覆盖一般。
- 许可证合规是”够用”级别,不是强项(它的主卖点是漏洞)。
- 定价按开发者席位,中型团队年费常见 5–20 万美元区间。
4.2 FOSSA
2015 年旧金山成立。相对 Snyk 更偏合规。
特点:
- 许可证识别精度在商业产品里第一梯队。
- 支持”策略包”概念,客户可以订阅 Linux Foundation、Apache Foundation 推荐策略。
- SaaS 为主,也提供 on-premise(国内大客户常选)。
- 与 GitHub、GitLab 深度集成,可直接在 PR 里显示”此 PR 引入了 GPL-3.0 的 xxx”。
- 定价按贡献者席位,中型团队年费常见 3–15 万美元。
4.3 Black Duck(Synopsys)
Black Duck Software 成立于 2002 年,是整个 SCA 行业的奠基者,2017 年被 Synopsys 以 5.65 亿美元收购。2024 年 Synopsys 将软件完整性业务(含 Black Duck、Coverity、Seeker)分拆成独立公司,仍沿用 Black Duck 品牌。
特点:
- Knowledge Base(KB) 是行业规模最大的开源组件指纹库,据官方披露覆盖超 600 万开源项目。
- 强项是二进制分析——可以在没有源码、没有锁文件的情况下扫一个
.jar或容器镜像,反推出里面的组件。 - 合规流程最完整:审批工作流、义务矩阵(obligation matrix)、法律报告(Audit Report)都有成熟模块。
- 价格最贵,大型企业合同常见 6 位数美元/年。
- 国内有总代理,华为、中兴、工商银行等都在用。
- 审计报告(Notices、Attribution Package)是它在法律场景里不可替代的优势——Black Duck 报告是少数在美国诉讼中被采信的取证材料。
4.4 Mend(原 WhiteSource)
以色列 WhiteSource 于 2011 年成立,2022 年改名 Mend.io。
特点:
- “Renovate”(全自动依赖升级机器人)是它收购的重要资产,开源版本被 GitHub 等广泛使用。
- Mend Bolt 免费版提供基本扫描,适合小团队。
- 漏洞修复建议(remediation)和自动 PR 升级是最大卖点。
- 定价中等,年费通常在 Snyk 和 Black Duck 之间。
4.5 Sonatype Nexus IQ
Sonatype 是 Maven Central 的运营方,2008 年成立,做 Nexus Repository(制品库)起家,Nexus IQ 是其 SCA 产品。
特点:
- 与 Nexus Repository 深度耦合——可以在制品库层面直接阻断下载高危组件。
- “Firewall” 模式可拦截新引入的恶意包(typo-squat、依赖混淆攻击)。
- Sonatype 对 Maven 生态数据掌握最完整。
- 对 Java / .NET 企业客户最友好,对前端生态一般。
- 价格接近 Black Duck 级别。
一个用于快速横向对比的表格:
| 工具 | 定位 | 漏洞数据源 | 许可证识别 | 二进制分析 | 典型年费(中型团队) |
|---|---|---|---|---|---|
| Snyk | 开发者优先 | 自研 Intel + NVD + GHSA | 中 | 否 | 5–20 万美元 |
| FOSSA | 合规优先 | 自研 + NVD | 强 | 有限 | 3–15 万美元 |
| Black Duck | 合规 + 审计 | BDSA(自研) | 强 | 强 | 10–50 万美元 |
| Mend | 修复自动化 | 自研 + NVD | 中 | 有限 | 5–20 万美元 |
| Sonatype IQ | 制品库阻断 | Sonatype Data Research | 中 | 有限 | 10–40 万美元 |
上述数字基于公开招投标与行业报告估算,不同规模、模块、席位差异极大,以实际报价为准。
五、开源工具详解
5.1 Syft + Grype(Anchore)
Anchore 公司 2020 年开源 Syft(SBOM 生成)与 Grype(漏洞扫描),是目前最活跃的开源 SBOM 工具链。
Syft 的能力:
- 支持容器镜像(Docker、OCI、Singularity)、目录、单个文件、tarball。
- Cataloger 覆盖 Alpine apk、Debian dpkg、RHEL rpm、Arch、Gentoo、Python(pip、poetry、pipenv、conda)、JavaScript(npm、yarn、pnpm)、Ruby gem、Java(jar、war、ear、par)、Go(binary、mod)、Rust(cargo)、PHP(composer)、Dart pub、Erlang rebar、Elixir mix、Swift、.NET、Nix、Homebrew 等。
- 输出格式:syft-json、syft-table、syft-text、cyclonedx-json、cyclonedx-xml、spdx-tag-value、spdx-json、github-json。
一个典型工作流:
# 安装(Linux / macOS)
curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh -s -- -b /usr/local/bin
# 对容器镜像生成 SBOM(CycloneDX JSON)
syft docker.io/library/nginx:1.25.3 -o cyclonedx-json > nginx-1.25.3.cdx.json
# 对本地目录生成 SPDX
syft dir:. -o spdx-json > my-app.spdx.json
# 对二进制文件做成分分析
syft /usr/local/bin/kubectl -o table
# 指定 cataloger(例如只看 Java 与 OS 包)
syft my-app.jar --catalogers java-cataloger,rpm-db-catalogerGrype 消费 Syft 输出:
# 直接扫描
grype docker.io/library/nginx:1.25.3
# 从 Syft SBOM 读入,离线扫描(SBOM-first 工作流)
syft -o json docker.io/library/nginx:1.25.3 | grype
# 仅报告 high/critical 且阻断 CI
grype sbom:nginx-1.25.3.cdx.json --fail-on high --only-fixedGrype 使用 Anchore 维护的漏洞数据库(聚合 NVD、GHSA、Alpine secdb、Debian OVAL、Red Hat OVAL、Amazon ALAS、Ubuntu USN、Wolfi、Chainguard 等)。
Syft 默认不下载源码,它只读包管理器元数据和文件指纹,因此速度极快——扫一个几百 MB 的容器镜像通常 10 秒内完成。这也是它与 ORT/ScanCode 的根本定位差异:Syft 回答”里面有什么”,ORT/ScanCode 回答”每一行代码是什么许可证”。二者配合而不是互相替代。
另一个实践要点是 Syft 的 --source-name 和
--source-version
参数:默认情况下它会用扫描目标的目录名或镜像名,若想让输出的
SBOM 在 Dependency-Track
里稳定对应同一个项目,最好显式传递。例如:
syft dir:. \
--source-name my-service \
--source-version $(git describe --tags --always) \
-o cyclonedx-json > sbom.cdx.json5.2 OSS Review Toolkit(ORT)
ORT 由 HERE Technologies 发起,2017 年开源,现已捐给 OpenChain。它的定位是企业级合规工作流,而不是单点扫描工具。ORT 由若干 subcommand 组成:
- Analyzer:解析项目元数据,构建依赖图。支持 Gradle、Maven、NPM、Yarn、Pnpm、Composer、Cargo、Go Modules、pip、Poetry、Bower、Conan、CocoaPods、NuGet、Stack、PUB 等 20+ 构建系统。
- Downloader:把所有依赖的源码下载下来(用于下一步扫描)。
- Scanner:对源码跑许可证扫描,默认集成 ScanCode Toolkit、FossID、Askalono。
- Advisor:查漏洞(集成 OSV、VulnerableCode、Nexus IQ、Black Duck、Snyk)。
- Evaluator:执行策略规则(用 Kotlin DSL 写)。
- Reporter:输出报告——SPDX、CycloneDX、PDF、HTML、Excel、NOTICE 文本。
典型命令:
# 1. 分析依赖(产出 analyzer-result.yml)
ort analyze -i ./my-project -o ./ort-output
# 2. 下载源码
ort download -i ./ort-output/analyzer-result.yml -o ./ort-output/downloads
# 3. 扫描许可证
ort scan -i ./ort-output/analyzer-result.yml -o ./ort-output
# 4. 查漏洞
ort advise -i ./ort-output/scan-result.yml -o ./ort-output \
--advisors OSV,VulnerableCode
# 5. 执行策略
ort evaluate -i ./ort-output/scan-result.yml -o ./ort-output \
--rules-resource /rules/osadl-matrix.rules.kts
# 6. 生成报告
ort report -i ./ort-output/evaluation-result.yml -o ./ort-output/reports \
--report-formats SpdxDocument,CycloneDx,WebApp,NoticeTemplateORT 的”策略 + 报告模板”设计非常适合大型企业,西门子、博世、华为、宝马均有公开案例使用 ORT。
ORT 的另一特色是
curations(人工修订)。开源生态里许可证元数据错漏很多——某个包声明是
MIT,实际源码里带了 GPL 代码;某个包根本没写 LICENSE
字段。面对这种情况,ORT 允许在 curations.yml
里写”对这个 PURL,concluded license 为 xxx,理由为
yyy”,把人工判断沉淀下来,下次扫描自动复用。这是企业级合规流程中”一次审阅,永久生效”的关键机制。ORT
官方还维护了一个公共的 ort-config
仓库,沉淀了社区共识的 curations,可以直接引用。
5.3 ScanCode Toolkit
nexB 公司发起,2015 年开源,是许可证识别事实上的开源标杆。ORT、FOSSology 都会在内部调用 ScanCode。
pip install scancode-toolkit
scancode --license --copyright --package --info --json-pp result.json ./my-projectScanCode 的许可证规则库(scancode-licensedb)手工维护了几千条正则与文本模板,准确率在开源工具里第一。ScanCode.io(配套的 SaaS/自托管 Web 界面)让审阅者可以在 UI 里对扫描结果做 triage。
5.4 FOSSology
Linux 基金会项目,2008 年由惠普开源,定位是人工审阅平台。
- 多用户协作:许可证审阅需要人工判断时的工作流(分配、复核、通过)。
- 内置 Nomos、Monk、Ninka 三个许可证识别扫描器,可交叉校验。
- 数据库驱动(PostgreSQL),支持版本化的历史审阅记录。
FOSSology 在中国电信、中兴、华为内部有多年使用记录。它更像 Bugzilla 的 OSS 合规版,不是 CI 工具。
5.5 Dependency-Track
OWASP 旗舰项目,2013 年起由 Steve Springett 维护。定位是SBOM 聚合与持续监控平台。
工作模型:
- CI 在每次构建后把 CycloneDX SBOM POST 到 Dependency-Track。
- Dependency-Track 解析 SBOM,把组件对应到内置的 PURL/CPE 数据库。
- 订阅 NVD、GHSA、OSV、Snyk、Sonatype OSS Index、VulnDB,周期性地刷新漏洞数据。
- 当新 CVE 影响某个历史 SBOM,触发 webhook/邮件/Jira 告警。
- 允许给组件打 VEX 注解:“Log4j 在我产品里不可利用,因为 JNDI lookup 已禁用”。
它解决的核心痛点是时间维度的成分分析:扫一次只能告诉你此刻风险,Dependency-Track 告诉你”一周前上线那个版本是否受今天新披露的 CVE 影响”。
部署一般是 Docker Compose 起三个容器(apiserver、frontend、postgres),数分钟即可。
Dependency-Track 的几个高频用法:
- Portfolio 视图:把一家公司所有产品/服务的 SBOM 集中聚合,按组件维度反查”哪些产品用了 log4j 2.14.x”。
- Policy Engine:基于组件 metadata 的规则(许可证、CVSS、EPSS、是否 EOL、是否来自可信源),触发 warn 或 fail。
- Notifications:可对接邮件、Slack、飞书、企业微信、webhook,让新 CVE 告警直达值班工程师。
- VEX 工作流:对每个 CVE,工程师可以标记
exploitable、in_triage、resolved、not_affected(附豁免理由),生成对外交付用的 VEX 文档。 - API / CLI:全部能力有 REST API,可以写脚本批量操作——例如每季度把所有项目的 high CVE 导出生成一份治理报表。
5.6 cdxgen
CycloneDX 官方的 SBOM 生成器,印度工程师 Prabhu Subramanian 主力维护,由 OWASP Foundation 托管。
相比 Syft,cdxgen 的差异:
- 语言覆盖更广:在 JVM、Python、JavaScript 之外,对 Rust、Swift、Dart、Elixir、Clojure、.NET、Android APK、iOS IPA、Unity 资产、Terraform state、Helm chart 都能生成 BOM。
- 深度字段:能同时输出 SaaSBOM、OBOM(运维清单)、MBOM(机器学习清单)。
- PURL 精度更高:对 vendored
依赖会尝试解析内部
package.json。
npm install -g @cyclonedx/cdxgen
# 自动探测项目类型
cdxgen -o bom.json .
# 指定类型(多项目共存时)
cdxgen -t java -o java-bom.json ./backend
cdxgen -t js -o js-bom.json ./frontend
# 容器镜像
cdxgen -t docker -o image.bom.json myorg/myapp:1.0
# 深度模式(解析 vendored / 二进制)
cdxgen --deep -t go -o go-deep.bom.json .六、CI 集成
SCA 落到 CI 上,本质要回答三个问题:什么时候扫、扫出来怎么办、产物放在哪。常见的模式有四类:
- PR 时扫:每次 Pull Request 触发扫描,发现新增的高危依赖时给 PR 评论、阻断合并。优点是”谁引入,谁修复”,责任归属清晰;缺点是扫描耗时会拖慢 PR 反馈,对于大型 monorepo 尤其明显。
- 主干/Release 时扫:合入主干或打 tag 时扫描,作为质量门禁之一。适合对 PR 流速敏感的高频项目,但”发现问题再回退”的修复成本比 PR 时发现高。
- 制品库入库时扫:在 Nexus/Artifactory 这类制品库代理公共源时扫描,把风险挡在外网与内网的边界。适合有统一制品库的中大型企业,本质是”供应源头治理”。
- 持续监控:SBOM 入库后,依赖监控平台(Dependency-Track)在新 CVE 发布时回溯所有历史 SBOM,发现受影响产品就触发响应。这是时间维度的保护,与前三类是互补而非替代关系。
成熟的 SCA 体系通常是前扫后监控的组合:PR 时做增量扫描(快)、主干 release 时做全量扫描(慢但完整)、Dependency-Track 做持续监控(时间覆盖)。
6.1 GitHub Dependency Graph 与 Dependabot
GitHub 内置两件事:
- Dependency
Graph:对公开仓库(和开启”Dependency
graph”的私有仓库)自动解析支持的清单文件(package-lock.json、yarn.lock、Pipfile.lock、requirements.txt、poetry.lock、Gemfile.lock、composer.lock、go.sum、Cargo.lock、pom.xml、build.gradle、*.csproj、pubspec.lock
等)。可直接从 API 下载 SPDX 格式
SBOM:
GET /repos/{owner}/{repo}/dependency-graph/sbom。 - Dependabot:基于 GHSA
数据库,发现高危依赖后自动开 PR 升级。Dependabot 配置放在
.github/dependabot.yml。
对于企业 / 军工敏感代码不能上 GitHub SaaS 的场景,GitHub Enterprise Server 的 “Advanced Security” 许可里也提供 Dependabot、Secret Scanning、Code Scanning 三件套。
Dependabot 典型配置示例:
# .github/dependabot.yml
version: 2
updates:
- package-ecosystem: "gomod"
directory: "/"
schedule:
interval: "weekly"
open-pull-requests-limit: 5
groups:
minor-and-patch:
update-types: ["minor", "patch"]
ignore:
- dependency-name: "github.com/internal/legacy-sdk"
- package-ecosystem: "npm"
directory: "/web"
schedule:
interval: "daily"
versioning-strategy: increase-if-necessary
- package-ecosystem: "docker"
directory: "/"
schedule:
interval: "weekly"
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "monthly"groups 是 2023 年新增的能力,能把一堆 patch
升级打包成一个 PR,显著减少 review
疲劳。对于更激进的全自动化,可以考虑 Renovate(Mend
开源维护),它支持 monorepo 按 package 级别分组、交叉关联
CVE、在 PR 里嵌入 release note 摘要。
6.2 Gitee 依赖扫描
Gitee(开源中国旗下)企业版在 2023 年后上线了”依赖扫描”,数据源包括 CNVD、NVD,对 Maven、npm、pip、Go 模块做依赖分析;“许可证识别”模块使用 ScanCode 规则库的本地化版本。Gitee 也接入了 OpenAtom 开源基金会的合规检查模板。
此外 GitCode、CodeArts(华为云)也都在 2024 年陆续推出了自研 SCA 能力,基本都是 ScanCode + 国产漏洞库的组合。
腾讯工蜂(git.code.tencent.com)、阿里云云效(codeup)也提供类似的内置 SCA 能力。对于主要在国内 DevOps 平台上开发的团队,优先用平台内置功能,省去自搭一套 Syft + Dependency-Track 的运维开销。代价是:这些平台的 SBOM 导出能力通常不完整,很难满足对外交付的 NTIA 最小元素要求,仍需在发版环节额外生成一份独立 SBOM。
6.3 在 GitHub Actions 里集成 Syft
以下是一个典型的”每次 push 生成 SBOM、附件到 Release、并上传到 Dependency-Track”的工作流:
# .github/workflows/sbom.yml
name: Generate SBOM
on:
push:
branches: [main]
tags: ['v*']
pull_request:
workflow_dispatch:
permissions:
contents: write # 用于上传到 Release
jobs:
sbom:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Syft
uses: anchore/sbom-action/download-syft@v0
- name: Generate CycloneDX SBOM
run: |
syft dir:. \
-o cyclonedx-json=sbom.cdx.json \
-o spdx-json=sbom.spdx.json
- name: Grype scan (fail on high)
uses: anchore/scan-action@v3
with:
sbom: sbom.cdx.json
fail-build: true
severity-cutoff: high
- name: Upload SBOM artifacts
uses: actions/upload-artifact@v4
with:
name: sbom
path: |
sbom.cdx.json
sbom.spdx.json
- name: Upload to Dependency-Track
if: github.ref == 'refs/heads/main'
env:
DT_URL: ${{ secrets.DEPENDENCY_TRACK_URL }}
DT_API_KEY: ${{ secrets.DEPENDENCY_TRACK_API_KEY }}
PROJECT_UUID: ${{ secrets.DT_PROJECT_UUID }}
run: |
curl -sS -X POST "$DT_URL/api/v1/bom" \
-H "X-Api-Key: $DT_API_KEY" \
-H "Content-Type: multipart/form-data" \
-F "project=$PROJECT_UUID" \
-F "bom=@sbom.cdx.json"
- name: Attach SBOM to Release
if: startsWith(github.ref, 'refs/tags/')
uses: softprops/action-gh-release@v2
with:
files: |
sbom.cdx.json
sbom.spdx.json几个要点:
- 两种格式都生成——对内用 CycloneDX 送 Dependency-Track,对外用 SPDX 附到 Release 满足合规。
- 阻断基于漏洞严重度——Grype 的
--fail-on是最直接的策略网关。 - Tag 推送时才附件到 Release——避免每个 PR 构建都污染 Release 资产。
- 主分支才推送到 Dependency-Track——防止 PR 产生噪声项目版本。
对容器镜像,把 syft dir:. 替换为
syft <image>:<tag> 即可。配合
cosign attach sbom 或
cosign attest --predicate sbom.cdx.json 可以把
SBOM 签名后附到 OCI
Registry,形成可验证的软件供应链证明(in-toto
attestation)。
把 SBOM 附到镜像的完整命令组合:
# 1. 构建镜像
docker buildx build -t registry.example.com/app:1.4.2 --push .
# 2. 生成 SBOM
syft registry.example.com/app:1.4.2 -o cyclonedx-json > sbom.cdx.json
# 3. 签名镜像
cosign sign registry.example.com/app:1.4.2 --key cosign.key
# 4. 把 SBOM 作为 attestation 附到镜像
cosign attest \
--predicate sbom.cdx.json \
--type cyclonedx \
--key cosign.key \
registry.example.com/app:1.4.2
# 5. 下游验证
cosign verify-attestation \
--key cosign.pub \
--type cyclonedx \
registry.example.com/app:1.4.2 \
| jq -r '.payload' | base64 -d | jq '.predicate'这种做法让 SBOM 永远跟随镜像走,而不是散落在 Release 资产或某个邮件附件里。符合 SLSA(Supply-chain Levels for Software Artifacts)level 3 的供应链成熟度模型。
七、合规要求:EO 14028、CRA、等保 2.0
7.1 美国 EO 14028
2021 年 5 月 12 日签署,行政令序号 14028。第 4 节专门讲”增强软件供应链安全”。相关落地文件:
- NIST SP 800-218:《安全软件开发框架》(SSDF),2022 年 2 月发布,V1.1。
- NIST SP 800-161r1:《系统与组织的网络安全供应链风险管理实践》。
- NTIA Minimum Elements for a SBOM(2021 年 7 月):规定 SBOM 至少包含七项字段——供应商名、组件名、组件版本、其他唯一标识、依赖关系、SBOM 作者、时间戳;并要求支持自动化生成、机器可读格式、可分发。
- OMB M-22-18 / M-23-16:要求联邦机构在采购软件时获取开发方的自证明(self-attestation),必要时提供 SBOM。
- CISA Secure Software Development Attestation Form(2024 年起强制)。
对中国企业出海美国的影响:向美国联邦、州政府、军方供货必须提供 SBOM;商业 SaaS 的大型美国客户(金融、医疗)也逐步把 SBOM 写进供应商合同。
与 EO 14028 配套的还有几个具体法规节点:
- 2022 年 12 月《FY2023 NDAA》通过后,国防部(DoD)进一步细化 CMMC 2.0(Cybersecurity Maturity Model Certification),SBOM 被纳入 Level 2/3 的常见证据清单。
- 2023 年 CISA 发布《SBOM Sharing Lifecycle Report》,建议使用 Publish → Authorize → Access 三阶段模型管理 SBOM 分发,支持 HTTPS、OCI、S3 多种渠道。
- 2024 年 FDA 开始要求上市医疗器械软件随附 SBOM(Premarket Submission),CSA(Cybersecurity Act 524B 条款)。
7.2 欧盟《网络弹性法案》(CRA)
2022 年 9 月草案、2024 年 10 月正式通过(Regulation (EU) 2024/2847),自公布后 36 个月全面适用(2027 年底),报告义务于 21 个月后生效(2026 年 9 月)。
核心义务:
- 生产者需识别并记录产品中的组件,承担漏洞处理义务至少 5 年或产品生命周期(取其长者)。
- 对重要产品(Important Products,Class I/II)和关键产品(Critical Products)有额外符合性评估要求。
- 漏洞披露:知晓被主动利用的漏洞须在 24 小时内通知 ENISA 与成员国 CSIRT。
业内普遍解读:CRA 附件一第 2(1) 条的”识别 & 记录”等同于要求 SBOM。ENISA 也公开表态支持 SPDX/CycloneDX。
CRA 对开源项目作者的处理是一个专门博弈点:商业性质的开源(open-source software stewards)承担有限义务,纯个人业余开源不在范围内。对中国开源维护者的实际影响较小,但对”把开源 fork 后商业化销往欧盟”的公司,必须把 SBOM、漏洞响应、CE 合格声明全部走完。
CRA 另一条容易被忽视的高压线是主动利用披露 24 小时义务——在企业内部这意味着安全响应团队必须有能够 24 小时在岗的流程与人员,并且能够快速从 SBOM 反向定位到受影响产品版本、客户清单,才能在 24 小时内完成通知。SBOM 没有做持久化、没有版本化的公司,这条义务几乎不可能满足。
EU CRA 的落地时间线值得记忆:
| 时间 | 里程碑 |
|---|---|
| 2024-10-23 | 法案正式通过 |
| 2024-12-11 | 在 Official Journal 发布 |
| 2025-06-11 | 第 14 条报告义务指南出台窗口(委员会实施法案) |
| 2026-09-11 | 漏洞报告义务生效 |
| 2027-12-11 | 全面适用(所有主要义务) |
国内厂商对欧盟出口前应预留至少 12–18 个月准备期来搭 SBOM 能力与漏洞响应流程。
7.3 中国等保 2.0 与 SBOM
GB/T 22239-2019(信息安全技术 网络安全等级保护基本要求,俗称等保 2.0)本身没有”SBOM”字样,但相关条款已经等价要求:
- 8.1.4.7 应用安全—应用程序完整性:应对应用系统的完整性进行保护,可扩展解释为”组件清单可追溯”。
- 8.1.10 安全运维管理—外包运维管理 / 软件开发管理:要求记录第三方组件、开源组件的版本、来源、漏洞管理。
- 三级及以上系统的漏洞管理要求覆盖”自研代码与第三方组件”。
此外:
- 《网络产品安全漏洞管理规定》(工信部、网信办、公安部,2021 年 9 月)第 7 条:网络产品提供者发现或获知其产品存在安全漏洞后应当在 2 日内向工信部 CSTIS 平台报送。这条对”你用了哪个 Log4j 版本”的追溯能力提出了硬要求。
- GB/T 36637-2018 信息技术 ICT 供应链安全风险管理指南。
- 2024 年起国资委、金融监管部门在关键信息基础设施(关基)采购中陆续引入”随产品交付 SBOM”的技术条款,部分央企把 SBOM 作为投标必交材料。
实务操作上,国内企业的 SBOM 字段通常沿用 SPDX/CycloneDX,但增加一列”国产替代建议”或”国密合规状态”以满足本地化要求。
另外值得留意的三份国内标准/草案:
- GB/T 43698-2024 《网络安全技术 软件供应链安全要求》:2024 年 8 月发布,2025 年 3 月实施,首次在国标层面引入 SBOM 概念,要求软件供方”建立并维护软件物料清单”并”在交付时提供”。字段定义与 NTIA 最小元素基本对齐。
- 信标委 TC260 先后发布《软件物料清单实践指南》若干版本草稿,给出了 SPDX/CycloneDX 本地化落地建议,特别是对国产组件命名空间(如 gitee://、gitcode://)的 PURL 扩展建议。
- 金融行业:人民银行 JR/T 0197、银保监会网信标准中陆续出现对开源组件清单化、漏洞可追溯的要求,工商银行、建设银行已在 2024 年招标文件中明确要求交付物附 SBOM。
从合规触发点上说,一家公司若同时满足以下条件中的两条及以上,就值得把 SBOM 列为刚性工程目标:
- 产品对外销售或 SaaS 对外服务;
- 客户里有政府、金融、军工、关基运营者;
- 产品出口至美国或欧盟;
- 主要软件形态包含容器镜像或嵌入式固件;
- 公司有 A 轮以后融资或上市计划(尽调侧会严查)。
八、工程落地路径
8.1 第一步:把 Syft 跑起来
落地的第一天不要去谈”全公司统一 SCA 平台”,先让 Syft 在 一个项目 的 CI 里跑起来,输出 CycloneDX JSON,上传为 Artifact。这一步成本极低(半天工作量),价值极高:从此团队至少能回答”我用了什么”。
注意事项:
- 不要试图一次性扫所有仓库,先选一个代表性项目(例如最大的 Java 服务)。
- 不要设阻断规则——先观察,不执法。三周后再谈策略。
- SBOM 产物做版本化存档(对象存储按
repo/branch/commit归档),这决定了后面”追溯历史漏洞”能不能做成。
8.2 第二步:接入漏洞数据库
部署 Dependency-Track(或者直接用 SaaS,如 OWASP 自托管版本),把 SBOM 推上去,让它订阅 NVD/GHSA/OSV。
这一步会暴露第一个现实:历史技术债远大于新增风险。几乎所有项目第一次扫描都会发现几十个 high/critical。此时不要 panic——按”可利用性 × 修复成本”做优先级,先处理”有公开 exploit 且一条命令能升的”,把中长期不能升的组件挂 VEX 标注并上报给安全团队备案。
Dependency-Track 的最小部署(Docker Compose):
# docker-compose.yml
version: "3.8"
services:
dtrack-apiserver:
image: dependencytrack/apiserver:4.11.0
environment:
- ALPINE_DATABASE_MODE=external
- ALPINE_DATABASE_URL=jdbc:postgresql://db:5432/dtrack
- ALPINE_DATABASE_USERNAME=dtrack
- ALPINE_DATABASE_PASSWORD=changeme
deploy:
resources:
limits:
memory: 8G
volumes:
- dtrack-data:/data
depends_on: [db]
ports: ["8081:8080"]
dtrack-frontend:
image: dependencytrack/frontend:4.11.0
environment:
- API_BASE_URL=http://localhost:8081
ports: ["8080:8080"]
db:
image: postgres:15
environment:
- POSTGRES_DB=dtrack
- POSTGRES_USER=dtrack
- POSTGRES_PASSWORD=changeme
volumes:
- pgdata:/var/lib/postgresql/data
volumes:
dtrack-data:
pgdata:首次启动后到管理界面开启 NVD、GitHub Advisories、OSV 三个 analyzer 数据源,等待首轮镜像同步(NVD 完整镜像约 200 MB,OSV 约 500 MB),之后 API Key 即可用于从 CI 上传 SBOM。
8.3 第三步:许可证策略网关
等漏洞治理走上正轨后,再上许可证。典型策略:
| 许可证类别 | 合并到 main | 发布到公网 | SaaS 自用 |
|---|---|---|---|
| 公共领域 / CC0 | ✔ | ✔ | ✔ |
| MIT / BSD / Apache-2.0 | ✔ | ✔ | ✔ |
| MPL-2.0 / LGPL(动态链接) | ✔ | ✔(附义务) | ✔ |
| LGPL 静态链接 | 需审批 | 需审批 | ✔ |
| GPL-2.0 / GPL-3.0 | 需审批 | 仅随 GPL 产品 | ✔ |
| AGPL-3.0 | ❌ 原则禁 | ❌ | 需审批 |
| SSPL / BSL / Commons Clause | ❌ | ❌ | ❌ |
| 未知 / 无声明 | ❌ | ❌ | ❌ |
策略用 ORT Evaluator 的 Kotlin DSL 或 Dependency-Track 的 Policy Engine 落地,结合 OPA Rego 还能把”我们的产品是 SaaS 还是分发品”当成参数传入。
一个最小的 OPA Rego 策略示例:
package sbom.license
# 默认黑名单
forbidden_licenses := {
"AGPL-3.0-only", "AGPL-3.0-or-later",
"SSPL-1.0",
"Commons-Clause",
"BUSL-1.1",
}
# 产品类型参数(通过 input.product_type 传入)
# "distributed"(分发)| "saas"(自用)| "internal"(内部工具)
deny[msg] {
some component
component := input.components[_]
license := component.licenses[_].license.id
forbidden_licenses[license]
input.product_type == "distributed"
msg := sprintf("分发产品禁止使用 %s 许可证(组件:%s@%s)",
[license, component.name, component.version])
}
deny[msg] {
some component
component := input.components[_]
license := component.licenses[_].license.id
license == "GPL-3.0-only"
input.product_type == "distributed"
not component.properties[_].name == "license_approval"
msg := sprintf("GPL-3.0 组件 %s 需走白名单审批",
[component.name])
}
在 CI 中调用:
opa eval \
--data policy.rego \
--input sbom.cdx.json \
--format pretty \
'data.sbom.license.deny'有 deny 输出就阻断构建。Rego 的优点是策略即代码——策略本身可以进版本库、走 PR review、写单测。
8.4 第四步:SBOM 发布与存档
- 内部存档:每次发版的 SBOM
在对象存储里保留 ≥ 5 年(CRA 要求),按
product/version/{spdx,cdx}.json命名。 - 外部发布:对公共版本,把 SBOM 附到
GitHub Release 或 OCI
Registry(
cosign attach sbom)。一些开源项目(如 Kubernetes、Istio)已经这么做。 - 签名:用 Sigstore / cosign 对 SBOM 做 in-toto v1 attestation,下游可以验证 SBOM 确实来自你的 CI,而不是被中间人篡改。
- VDR / VEX:当 CVE 不适用时发 VEX 声明,避免给下游制造”假警报”。
配套还需要建立几条最低限度的运营 SLA:
| 事件 | 响应 SLA |
|---|---|
| Critical CVE(CVSS ≥ 9.0)且已有公开 exploit | 8 小时内确认影响范围 + 48 小时内热修 |
| High CVE(7.0 ≤ CVSS < 9.0) | 72 小时内确认 + 7 天内修复或 VEX 豁免 |
| Medium / Low | 30 天内随例行版本合并修复 |
| 许可证高风险引入(AGPL/SSPL) | PR 阻断 + 24 小时内人工复核 |
| 新 CVE 影响过往 Release(回溯) | 7 天内发布客户通告 |
SLA 写下来之后,SCA 工具才真正开始发挥作用;没有 SLA 的 SBOM 只是一份没人看的 JSON。
九、工程坑点
实际落地一年后你大概率会踩到的坑:
SBOM 不是一次性产物。常见误解是”发版前扫一下就行”。现实是:依赖锁文件每次
npm install都会变,容器基础镜像每次重建都会变,CVE 每天都在新增。SBOM 必须按构建生成、按版本归档、按时间监控,任何一环缺失都失去价值。Go 二进制的模块信息缺失。Go 1.18+ 用
-buildvcs嵌入了模块信息,但 1.17 及以下、以及-trimpath构建的二进制,syft读不到依赖。解决办法是构建时强制保留 buildinfo,或扫描源码而不是二进制。Python 动态依赖看不到。
requirements.txt能抓到显式依赖,但 setup.py 动态 import、conda 环境、notebook magic 安装的包都抓不到。建议以pip freeze的输出(运行时真实安装结果)为准。vendored 代码被漏扫。某些团队把
third_party/zlib/复制进仓库但没有任何元数据。此时只有 ScanCode 等基于文件指纹的工具才认得出,单靠 Syft 不够。Fat-JAR 内层依赖。Spring Boot 的可执行 JAR 里嵌套了几百个小 JAR,Syft 默认会递归解开,但某些 Shade 插件重打包后类名被重写,反解失败。治理思路:禁 shade 重写,或在 Maven 阶段先扫
dependency:list。License 冲突误报。同一个包在 NPM 写 MIT、源码头写 ISC、NOTICE 写 Apache-2.0——这不一定是违规,很多项目历史上就是这么”多许可证并存”。要手工建立”已审白名单”而不是每个 PR 都报红。
容器基础镜像的 CVE 风暴。扫一个官方 Ubuntu 22.04 基础镜像能轻松扫出 200+ CVE,大部分不可利用。策略要把基础镜像 CVE 与应用层 CVE 分轨治理,基础镜像层面以”及时更新 base image”代替”逐条修复”。
漏洞数据库滞后与误报。NVD 在 2024 年经历了严重的分析积压,大量 CVE 超过 3 个月仍无 CPE 映射,导致 Grype/Trivy 误报或漏报。推荐多源交叉:OSV + GHSA + 厂商原生库。
SBOM 本身成为敏感资产。一份完整 SBOM 等于告诉攻击者”我用了哪个 0-day 影响的库”。对外发布的 SBOM 与对内使用的 SBOM 应区分:对外脱敏(如不含内网路径、构建机器名),对内保真。
AI 模型与数据集不在经典 SBOM 范围。用 HuggingFace 上一个 Apache-2.0 权重训练了自己的模型,这个模型在你产品里是”组件”吗?SPDX 3.0、CycloneDX 1.5 的 AI-BOM/ML-BOM 正在补这个缺口,但工具链成熟度还不高。
多仓库去重。一家公司有上千个微服务,每个服务都引入 Jackson——漏洞管理应按”组件 × 版本 × 受影响服务”维度汇总,而不是每服务各自一张表。Dependency-Track 的 “Portfolio” 视图就是解决这个的。
依赖混淆攻击(dependency confusion)。攻击者在公共 registry 上抢注你的内部包名,同版本号抢先发布,你的构建会误从外网拉取恶意包。防御手段:内部包统一使用 scope(如
@mycorp/xxx)或独立 registry 且禁止 fallback 到公共源。恶意 typo-squatting。
loadsh冒充lodash、colros冒充colors,这类包往往在首次安装时植入挖矿脚本。SCA 工具需要订阅恶意包情报(如 Sonatype OSS Index、Checkmarx SCS、PyUp Safety),不是所有漏洞库都覆盖。CI 产物外泄。SBOM 里含内部 npm registry URL、内部包名、commit hash,这些本身是敏感情报。在 GitHub Actions 里用
upload-artifact时,如果仓库是 public,Artifact 也可能被外部访问(取决于仓库配置)。跨团队多语言一致性。前端用 Syft、后端用 ORT、运维用 Trivy——三份 SBOM 格式近似但字段值略有差异,聚合到 Dependency-Track 后产生”重复组件但不同 PURL”的脏数据。治理办法是统一工具链,或在聚合层做 PURL 归一化。
签名密钥轮换。cosign 签名的 SBOM 在密钥轮换后验证失败,需要保留历史公钥或使用 Fulcio 的短期证书配合 Rekor 透明日志。SLSA L3+ 的标准做法是结合 OIDC 与 Fulcio 实现 “keyless” 签名。
十、选型建议
| 场景 | 推荐组合 |
|---|---|
| 个人项目 / 小团队 | Syft + Grype(本地跑) + GitHub Dependabot |
| 创业公司 A 轮前 | Syft + Grype + Dependency-Track(自托管) |
| 中型企业(百人研发) | 上面基础上 + ORT(合规报告)+ Renovate(升级机器人) |
| 大型企业(千人以上) | 商业 SCA(FOSSA/Black Duck/Snyk 三选一)+ 内部 Dependency-Track + 自研策略 |
| 金融、电信、国央企 | Black Duck 或 Nexus IQ 作底座(审计报告齐全) + 国产化 SCA(补 CNVD 数据源) |
| 军工、关基 | 完全离线:本地 ScanCode + 本地 VulnerableCode + 本地漏洞库同步 |
一个经验法则:工具只是 30%,流程与人占 70%。再贵的 Black Duck 也挡不住开发绕过 CI 直推制品;再好用的 Syft 也救不了一家没人读 SBOM 的公司。能跑得下去的标志是:有一个 OSPO 或安全团队每周 review 一次 Dependency-Track 告警、每季度 review 一次许可证策略、每年复审一次 SBOM 发布政策。
再给一个选型决策树,帮助快速定位:
- 问题 1:你的软件要对外分发还是 SaaS
自用?
- 分发(含嵌入式、桌面、移动、镜像公开发布)→ 许可证合规权重高,优先 FOSSA / Black Duck / ORT。
- 纯 SaaS → 漏洞权重高,优先 Snyk / Dependency-Track。
- 问题
2:是否有国密、关基、军工、金融核心的合规要求?
- 是 → 需要国产化方案:悬镜、默安、奇安信、长亭等厂商的 SCA 产品,或自建 ScanCode + CNVD 同步。
- 否 → 商业开源任选。
- 问题 3:研发规模?
- <50 人 → Syft + Grype + Dependabot + Dependency-Track(全开源栈)。
- 50–500 人 → 前述再叠加 ORT(合规报告)+ Renovate(自动升级)。
- >500 人 → 至少一款商业 SCA 作底座 + 内部聚合平台(多数企业自研)。
- 问题 4:是否存在大量 C/C++ 二进制分发?
- 是 → Black Duck 的二进制分析几乎是唯一成熟选项,也可考虑 JFrog Xray、CodeSentry。
- 否 → 开源栈即可覆盖。
- 问题 5:出口目标市场?
- 仅国内 → 对齐等保 2.0 与 GB/T 43698。
- 美欧 → 必须能产出符合 NTIA Minimum Elements 与 CRA 附件 I 的 SBOM。
- 全球 → SPDX(对外)+ CycloneDX(对内)双格式并行。
关于 OSPO 如何搭建,见 企业开源办公室(OSPO)与开源 PMO 建设。
十一、中国企业实践概览
以下信息仅基于公开演讲、博客、白皮书,不代表内部实际架构。
华为:2020 年前后在内部上线基于 ORT 和 FOSSology 的开源合规平台”EulerMakerSec”(名称未公开)。华为是 ORT 的主要企业贡献者之一,公开提交了若干 Gradle/Maven 解析器改进。鸿蒙/欧拉项目的每个版本都随产品发布 SPDX SBOM。
字节跳动:字节的开源办公室 2022 年前后在 OpenAtom 会议上介绍过内部 SCA 体系,核心组件包括:基于 ScanCode 的许可证扫描、自研漏洞库(聚合 NVD/GHSA/OSV/CNVD)、与内部制品库 Bits 深度集成。对外的火山引擎云产品在 2024 年起陆续支持为客户生成 CycloneDX SBOM。
蚂蚁集团:在 2023 年 KubeCon China 演讲中介绍了基于 CycloneDX + Dependency-Track 的内部方案,结合自研的 “AntSec SBOM” 把 SBOM 签名(cosign)+ in-toto provenance 写入了 OceanBase/SOFAStack 等对外发布产品。蚂蚁也是 CycloneDX 标准的企业贡献者之一。
腾讯:腾讯代码安全团队公开过基于 Syft + Grype 的容器镜像扫描流水线,覆盖所有上 TKE(Tencent Kubernetes Engine)的业务镜像;在 OSPO 层面主要用商业工具做合规兜底(具体厂商未官宣)。
阿里巴巴:Dragonwell JDK、OceanBase、PolarDB 等对外产品在 2024 年后发布 SBOM(SPDX/CycloneDX 并存);云效 DevOps 平台内建了依赖扫描与许可证检查模块。
小米 / vivo / OPPO:Android/鸿蒙 衍生系统出海面临 Google GMS 和欧盟 CRA 双重合规压力,均已在 ROM 发布流程里加入 SBOM 生成步骤,供渠道商与监管核查。
这几家的共同规律:内部早用开源自研 + 外部合规交付用 SPDX/CycloneDX 标准。
另一个值得关注的趋势是国产 SCA 厂商的崛起。2023 年后几家安全厂商陆续推出本地化 SCA 产品:
- 悬镜安全(Xmirror):源鉴 OSS 产品主打 SCA,在金融、运营商场景有较广部署,数据源结合了国内 CNVD/CNNVD 与国外 NVD/GHSA。
- 默安科技:雳鉴 SCA,与其 SAST/IAST 产品同源,面向金融科技客户。
- 奇安信:代码卫士供应链安全模块,依托其全集团的威胁情报数据。
- 长亭科技:牧云 · 开源安全防护平台,主打容器与制品库侧阻断。
- 开源网安(SecZone):自研 SourceCheck 产品,早在 2018 年就做 SCA,积累了较多国产软件指纹。
国产厂商普遍的优势是 CNVD/CNNVD 数据同步及时、支持国产化操作系统(麒麟、统信、欧拉)的包格式解析、对国产 CPU 架构(鲲鹏、飞腾、龙芯、兆芯)二进制的识别。劣势在国际开源生态(Rust、Swift、现代前端工具链)覆盖尚在追赶。对于”信创 + 国际化并存”的企业,常见策略是商业双栈——一家国产 + 一家国际,在内部聚合层合并去重。
最后是一个成本观察:人力成本通常高于工具成本。一家 500 人研发规模的企业,搭建并维护 SCA/SBOM 体系的人力投入普遍在 3–5 FTE(full-time equivalent),包括安全工程师、OSPO 合规、DevOps 集成、法务审阅各占其中一部分。而工具年费按座位通常在 20 万到 200 万人民币区间,二者加起来只是整体研发成本的千分之几,却能避免一起 Equifax、一次 GPL 诉讼、一批客户流失——投产比极高。
如果你的产品要出海到美国 / 欧盟,请顺带阅读 出海合规:许可证、出口管制与数据合规。
本文为工程参考,不构成法律意见。涉及具体法律风险请咨询专业法律顾问。
十二、参考资料
标准与规范
- ISO/IEC 5962:2021 — Information technology — SPDX Specification V2.2.1
- ECMA-424 — CycloneDX Bill of Materials Standard(2024)
- NTIA, The Minimum Elements For a Software Bill of Materials (SBOM), July 2021
- NIST SP 800-218, Secure Software Development Framework (SSDF) Version 1.1, February 2022
- NIST SP 800-161r1, Cybersecurity Supply Chain Risk Management Practices for Systems and Organizations, May 2022
- CISA, Secure Software Development Attestation Common Form, March 2024
- SPDX Specification 3.0,https://spdx.github.io/spdx-spec/
- CycloneDX Specification 1.6,https://cyclonedx.org/specification/overview/
- Package URL (PURL) Specification,https://github.com/package-url/purl-spec
- OSV Schema,https://ossf.github.io/osv-schema/
法规
- Executive Order 14028 — Improving the Nation’s Cybersecurity(2021-05-12)
- Regulation (EU) 2024/2847 — Cyber Resilience Act(2024-10-23)
- GB/T 22239-2019 《信息安全技术 网络安全等级保护基本要求》
- GB/T 36637-2018 《信息技术 ICT 供应链安全风险管理指南》
- 《网络产品安全漏洞管理规定》工信部、网信办、公安部,2021-09-01
工具官方文档
- Syft,https://github.com/anchore/syft
- Grype,https://github.com/anchore/grype
- OSS Review Toolkit,https://oss-review-toolkit.org/
- ScanCode Toolkit,https://scancode-toolkit.readthedocs.io/
- FOSSology,https://fossology.github.io/
- OWASP Dependency-Track,https://dependencytrack.org/
- cdxgen,https://github.com/CycloneDX/cdxgen
- Sigstore cosign,https://docs.sigstore.dev/cosign/overview/
商业厂商公开资料
- Black Duck (Synopsys),https://www.blackduck.com/
- FOSSA,https://fossa.com/
- Snyk,https://snyk.io/
- Mend.io,https://www.mend.io/
- Sonatype Nexus IQ,https://www.sonatype.com/products/open-source-security-dependency-management
行业报告与实践
- Linux Foundation, The State of Software Bill of Materials (SBOM) and Cybersecurity Readiness, 2022
- Sonatype, State of the Software Supply Chain(年度报告)
- OpenChain Project(ISO/IEC 5230 合规规范)
上一篇:数字天堂、不乱买、罗盒:中国 GPL 诉讼第一案系列 | 下一篇:企业开源办公室(OSPO)与开源 PMO 建设
同主题继续阅读
把当前热点继续串成多页阅读,而不是停在单篇消费。
【开源许可与版权工程】开源许可证实操手册:从选型到发布
面向工程团队的开源许可证完整操作手册:许可证选型决策树、LICENSE/NOTICE/SPDX 文件写法、第三方依赖声明、CI 自动化检查、发布物合规标注,以及六套真实可复制的项目结构模板。
【开源许可与版权工程】闭源项目如何选择开源依赖:公司内部合规实操
面向做闭源/商业产品的团队:逐一拆解 MIT、LGPL、GPL、AGPL、SSPL、BSL 在 SaaS、私有化部署、移动 App、嵌入式固件等形态下的许可边界,给出三级名单模板、CI 扫描配置、SBOM 存证方案与出海补充要求。
开源许可与版权工程
面向中国工程团队的开源许可、版权与合规系列。从 GPL、AGPL、Apache、木兰协议到中国真实案例、SCA/SBOM 工具链与出海合规,讲清楚开源在工程落地中的坑与方法。
【开源许可与版权工程】红芯浏览器与「国产内核」往事:披皮事件的工程复盘
2018 年 8 月,红芯浏览器在完成 2.5 亿元融资后被发现基于 Chromium 换皮。本文从工程角度复盘这一事件:Chromium BSD-3 协议本身允许什么、不允许什么,如何通过文件指纹识别 Chromium 魔改,以及深度 Deepin、统信 UOS、麒麟 Kylin、中科曙光等国产系统的开源合规现状。