惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

S
Secure Thoughts
Recent Commits to openclaw:main
Recent Commits to openclaw:main
H
Heimdal Security Blog
SecWiki News
SecWiki News
H
Hacker News: Front Page
N
News | PayPal Newsroom
L
LINUX DO - 最新话题
N
News and Events Feed by Topic
TaoSecurity Blog
TaoSecurity Blog
AI
AI
C
Cybersecurity and Infrastructure Security Agency CISA
Scott Helme
Scott Helme
PCI Perspectives
PCI Perspectives
S
Securelist
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
Cyberwarzone
Cyberwarzone
A
Arctic Wolf
Forbes - Security
Forbes - Security
T
Tor Project blog
Spread Privacy
Spread Privacy
WordPress大学
WordPress大学
I
Intezer
Martin Fowler
Martin Fowler
Help Net Security
Help Net Security
P
Proofpoint News Feed
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
Cisco Talos Blog
Cisco Talos Blog
Latest news
Latest news
博客园 - 司徒正美
W
WeLiveSecurity
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
V
V2EX
P
Palo Alto Networks Blog
Google DeepMind News
Google DeepMind News
IT之家
IT之家
阮一峰的网络日志
阮一峰的网络日志
V
Vulnerabilities – Threatpost
Jina AI
Jina AI
S
Security Affairs
Hacker News - Newest:
Hacker News - Newest: "LLM"
Simon Willison's Weblog
Simon Willison's Weblog
Project Zero
Project Zero
T
Threatpost
P
Privacy International News Feed
人人都是产品经理
人人都是产品经理
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Application and Cybersecurity Blog
Application and Cybersecurity Blog
博客园 - Franky
Hugging Face - Blog
Hugging Face - Blog
Apple Machine Learning Research
Apple Machine Learning Research

土法炼钢兴趣小组的算法知识备份

国密算法与国密 TLS 系列索引 【系统架构设计】架构质量属性:不只是"高可用高性能" 【系统架构设计百科】告警策略:如何避免"狼来了" 【系统架构设计】CQRS:读写分离的架构哲学 【系统架构设计】空间架构:极端扩展场景的解法 【系统架构设计】微服务架构深度审视:优势、代价与适用边界 【系统架构设计】扩展性原理:水平、垂直与对角扩展 【系统架构设计】无状态设计:扩展的第一步也是最难的一步 【系统架构设计】缓存架构:从本地到分布式的多级缓存体系 【系统架构设计】管道与过滤器:Unix 哲学的架构表达 【系统架构设计】复杂性管理:架构的核心战场 【系统架构设计】消息队列架构:异步解耦的设计与陷阱 【系统架构设计】CDN 架构:全球加速的设计原理 【系统架构设计】连接池设计:被忽视的性能杀手 【系统架构设计】弹性设计模式:熔断器、舱壁与超时 【系统架构设计】高可用设计模式:冗余、故障转移与仲裁 【系统架构设计】容量规划:从拍脑袋到数据驱动 【系统架构设计】数据库扩展:分库分表的工程实践与替代方案 【系统架构设计】SLO 工程:可靠性的量化管理 【系统架构设计】性能建模:用数学思维分析系统瓶颈 【系统架构设计】混沌工程:主动验证系统的韧性 【系统架构设计】零拷贝与内存映射:数据搬运的极致优化 【系统架构设计】线程模型:从 thread-per-request 到协程 【系统架构设计】容灾架构:多活与灾备设计 【系统架构设计】数据库性能模式:索引、查询与连接管理 【系统架构设计】数据建模:从关系范式到文档模型的真实权衡 【系统架构设计】吞吐量优化:批处理、流水线与并发模型 【系统架构设计】流处理架构:从批处理到实时的范式迁移 【系统架构设计】搜索引擎架构:倒排索引之上的系统设计 【系统架构设计】时序数据架构:监控与 IoT 的存储设计 【系统架构设计】数据迁移与版本化:在线不停机的数据演进 【系统架构设计】数据湖与数据仓库:分析架构的演进路线 【系统架构设计】API 网关设计:入口层的职责边界 【系统架构设计】应用层数据一致性模式:在正确性与性能之间走钢丝 【系统架构设计】多模数据库选型:Polyglot Persistence 的工程实践 【系统架构设计】服务发现与注册:动态拓扑的基础设施 【系统架构设计】配置管理架构:从配置文件到配置中心 【系统架构设计】全链路压测:大规模系统的性能验证 【系统架构设计】幂等性设计:分布式环境下的安全重试 【系统架构设计】契约测试与 Schema 演进:服务间的信任协议 【系统架构设计】长连接与推送架构:WebSocket、SSE 与 MQTT 【系统架构设计】延迟分析:从 P50 到 P999 的全链路追踪 【系统架构设计百科】DDD 战术模式:聚合、实体与值对象 【系统架构设计百科】防腐层与开放主机服务:系统集成的 DDD 方案 【系统架构设计百科】领域事件与事件风暴:从业务到架构的桥梁 【系统架构设计百科】CQRS + Event Sourcing 完整实战:从领域建模到部署 【系统架构设计百科】DDD 与微服务:用领域模型划分服务边界 【系统架构设计】DDD 战略设计:限界上下文与上下文映射 【系统架构设计百科】认证架构:从 Session 到 JWT 到 OIDC 【系统架构设计】API 设计哲学:REST vs GraphQL vs gRPC 的真实权衡 排序算法专题:从 TimSort 到并行排序 【密码学百科】国密算法体系:SM2/SM3/SM4/SM9 全景解读 【密码学百科】承诺方案:Pedersen 承诺、向量承诺与多项式承诺 【密码学百科】不经意传输与隐私信息检索:OT、OT 扩展与 PIR 【密码学百科】门限密码学:门限签名、门限解密与分布式密钥生成 完美哈希:从理论到 gperf 实践 【密码学百科】安全多方计算:从 Yao 的混淆电路到实用 MPC 【密码学百科】同态加密:从 Paillier 到全同态加密(FHE) 【密码学百科】零知识证明系统:zk-SNARKs、zk-STARKs 与 Bulletproofs 【密码学百科】概率论与密码分析:生日攻击、差分分析与线性分析 【密码学百科】计算复杂性与归约:密码安全性证明的基石 【密码学百科】秘密共享:Shamir 方案、VSS 与安全多方计算入口 【密码学百科】椭圆曲线代数:Weierstrass 方程、点群运算与曲线选择 【密码学百科】离散对数与配对密码学:从 DLP 到 BLS 签名 【密码学百科】格密码数学基础:SVP、LWE 与格基约化 【密码学百科】抽象代数:群、环、域的密码学视角 【密码学百科】有限域算术:GF(2^n) 运算与在 AES/ECC 中的应用 【密码学百科】数论进阶:二次剩余、椭圆曲线上的 Weil 配对 【密码学百科】密码学简史:从凯撒密码到量子时代 【密码学百科】威胁模型与安全目标:CIA 三要素之外 【密码学百科】Kerckhoffs 原则与现代密码设计哲学 【密码学百科】随机性:密码学的基石 【密码学百科】信息论入门:熵、完美保密与 Shannon 定理 【密码学百科】分组密码原理:Feistel 网络与 SPN 结构 【密码学百科】AES 逐步拆解:SubBytes 到 MixColumns 的数学 【密码学百科】分组密码工作模式全览:ECB/CBC/CTR/OFB/CFB 【密码学百科】流密码:RC4 的兴衰与 ChaCha20 的崛起 【密码学百科】密码学哈希函数:MD5→SHA-2→SHA-3 的进化之路 【密码学百科】MAC 与 HMAC:消息认证的正确姿势 【密码学百科】认证加密(AEAD):GCM、ChaCha20-Poly1305 与 OCB 【密码学百科】密钥派生函数:HKDF、PBKDF2、Argon2 与密码存储 【密码学百科】公钥密码的数论基础:模运算、群、原根 【密码学百科】RSA 从原理到攻击:教科书 RSA 为什么不安全 【密码学百科】Diffie-Hellman 密钥交换与离散对数问题 【密码学百科】椭圆曲线密码学(ECC):从几何直觉到点群运算 【密码学百科】数字签名:ECDSA、EdDSA 与 Schnorr 签名 【密码学百科】现代密钥交换:X25519、ECDHE 与前向保密 【密码学百科】混合加密与 KEM/DEM 范式:ECIES 与 HPKE 【密码学百科】填充方案:PKCS#1 v1.5、OAEP 与 PSS 【密码学百科】TLS 协议全解析:从握手到 0-RTT 【密码学百科】PKI 与数字证书:信任链的构建与崩塌 【密码学百科】密码认证协议:从 SRP 到 OPAQUE 【密码学百科】零知识证明入门:如何证明你知道而不泄露 【密码学百科】安全信道构造:Noise 协议框架与 Signal 协议 【密码学百科】密钥管理工程:HSM、KMS 与密钥生命周期 【密码学百科】侧信道攻击:从时序攻击到功耗分析 【密码学百科】密码学实现陷阱:三层漏洞分类、审计工具链与系统性预防 密码敏捷性:如何设计可升级的密码系统 【密码学百科】OpenSSL/BoringSSL 架构剖析:ENGINE、Provider 与 FIPS 模块 排序基准测试:用数据说话
【开源许可与版权工程】SCA、SBOM 与软件成分分析:FOSSA、BlackDuck、Syft、OSS Review Toolkit
2026-04-22 · via 土法炼钢兴趣小组的算法知识备份

十年前,一家公司发布一个 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 的基本差异,聚焦在”怎么用工具把这些许可证和漏洞信息自动化地管起来”。

SCA 流水线架构

一、为什么成分分析变成了强制课题

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 这个词有时会被理解成”扫一下代码生成一份 Excel”。但工业级 SCA 系统通常有四个层次。

2.1 依赖发现层

这一层回答”项目里有哪些组件”。

最幼稚的做法是解析包管理器的锁文件——pom.xmlpackage-lock.jsonPipfile.lockgo.sumCargo.lockcomposer.lock 等。这种方式快、准,但只覆盖”你声明的依赖”,不覆盖:

  • 以 vendored 源码形式复制进仓库的组件(如直接把 zlib 的 C 源码放到 third_party/)。
  • 构建期动态下载的组件(某些 Makefile 会在构建时 curl 一个库)。
  • 容器基础镜像内已经安装的系统库(glibc、OpenSSL、BusyBox)。
  • 通过 UPX 壳或静态链接打包到二进制里的库。

工业级工具必须同时支持三条路径:

  1. 清单解析(manifest-based):读锁文件。
  2. 文件系统扫描(filesystem scan):遍历目录,对每个文件做指纹。
  3. 二进制分析(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.jsonlicense 字段,Maven 有 <licenses>,Go module 的 go.mod 无此字段(这是 Go 生态的痛点)。
  • 文件名启发式LICENSELICENSE.txtCOPYINGCOPYING.LESSERNOTICE
  • 文本指纹与相似度: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.MITLICENSE.ApacheLICENSE.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.0affected: 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

LicenseConcludedLicenseDeclared 的区别很关键: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-cataloger

Grype 消费 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-fixed

Grype 使用 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.json

5.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,NoticeTemplate

ORT 的”策略 + 报告模板”设计非常适合大型企业,西门子、博世、华为、宝马均有公开案例使用 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-project

ScanCode 的许可证规则库(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 聚合与持续监控平台

工作模型:

  1. CI 在每次构建后把 CycloneDX SBOM POST 到 Dependency-Track。
  2. Dependency-Track 解析 SBOM,把组件对应到内置的 PURL/CPE 数据库。
  3. 订阅 NVD、GHSA、OSV、Snyk、Sonatype OSS Index、VulnDB,周期性地刷新漏洞数据。
  4. 当新 CVE 影响某个历史 SBOM,触发 webhook/邮件/Jira 告警。
  5. 允许给组件打 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,工程师可以标记 exploitablein_triageresolvednot_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 上,本质要回答三个问题:什么时候扫扫出来怎么办产物放在哪。常见的模式有四类:

  1. PR 时扫:每次 Pull Request 触发扫描,发现新增的高危依赖时给 PR 评论、阻断合并。优点是”谁引入,谁修复”,责任归属清晰;缺点是扫描耗时会拖慢 PR 反馈,对于大型 monorepo 尤其明显。
  2. 主干/Release 时扫:合入主干或打 tag 时扫描,作为质量门禁之一。适合对 PR 流速敏感的高频项目,但”发现问题再回退”的修复成本比 PR 时发现高。
  3. 制品库入库时扫:在 Nexus/Artifactory 这类制品库代理公共源时扫描,把风险挡在外网与内网的边界。适合有统一制品库的中大型企业,本质是”供应源头治理”。
  4. 持续监控: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 sbomcosign 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。

九、工程坑点

实际落地一年后你大概率会踩到的坑:

  1. SBOM 不是一次性产物。常见误解是”发版前扫一下就行”。现实是:依赖锁文件每次 npm install 都会变,容器基础镜像每次重建都会变,CVE 每天都在新增。SBOM 必须按构建生成、按版本归档、按时间监控,任何一环缺失都失去价值。

  2. Go 二进制的模块信息缺失。Go 1.18+ 用 -buildvcs 嵌入了模块信息,但 1.17 及以下、以及 -trimpath 构建的二进制,syft 读不到依赖。解决办法是构建时强制保留 buildinfo,或扫描源码而不是二进制。

  3. Python 动态依赖看不到requirements.txt 能抓到显式依赖,但 setup.py 动态 import、conda 环境、notebook magic 安装的包都抓不到。建议以 pip freeze 的输出(运行时真实安装结果)为准。

  4. vendored 代码被漏扫。某些团队把 third_party/zlib/ 复制进仓库但没有任何元数据。此时只有 ScanCode 等基于文件指纹的工具才认得出,单靠 Syft 不够。

  5. Fat-JAR 内层依赖。Spring Boot 的可执行 JAR 里嵌套了几百个小 JAR,Syft 默认会递归解开,但某些 Shade 插件重打包后类名被重写,反解失败。治理思路:禁 shade 重写,或在 Maven 阶段先扫 dependency:list

  6. License 冲突误报。同一个包在 NPM 写 MIT、源码头写 ISC、NOTICE 写 Apache-2.0——这不一定是违规,很多项目历史上就是这么”多许可证并存”。要手工建立”已审白名单”而不是每个 PR 都报红。

  7. 容器基础镜像的 CVE 风暴。扫一个官方 Ubuntu 22.04 基础镜像能轻松扫出 200+ CVE,大部分不可利用。策略要把基础镜像 CVE 与应用层 CVE 分轨治理,基础镜像层面以”及时更新 base image”代替”逐条修复”。

  8. 漏洞数据库滞后与误报。NVD 在 2024 年经历了严重的分析积压,大量 CVE 超过 3 个月仍无 CPE 映射,导致 Grype/Trivy 误报或漏报。推荐多源交叉:OSV + GHSA + 厂商原生库。

  9. SBOM 本身成为敏感资产。一份完整 SBOM 等于告诉攻击者”我用了哪个 0-day 影响的库”。对外发布的 SBOM 与对内使用的 SBOM 应区分:对外脱敏(如不含内网路径、构建机器名),对内保真。

  10. AI 模型与数据集不在经典 SBOM 范围。用 HuggingFace 上一个 Apache-2.0 权重训练了自己的模型,这个模型在你产品里是”组件”吗?SPDX 3.0、CycloneDX 1.5 的 AI-BOM/ML-BOM 正在补这个缺口,但工具链成熟度还不高。

  11. 多仓库去重。一家公司有上千个微服务,每个服务都引入 Jackson——漏洞管理应按”组件 × 版本 × 受影响服务”维度汇总,而不是每服务各自一张表。Dependency-Track 的 “Portfolio” 视图就是解决这个的。

  12. 依赖混淆攻击(dependency confusion)。攻击者在公共 registry 上抢注你的内部包名,同版本号抢先发布,你的构建会误从外网拉取恶意包。防御手段:内部包统一使用 scope(如 @mycorp/xxx)或独立 registry 且禁止 fallback 到公共源。

  13. 恶意 typo-squattingloadsh 冒充 lodashcolros 冒充 colors,这类包往往在首次安装时植入挖矿脚本。SCA 工具需要订阅恶意包情报(如 Sonatype OSS Index、Checkmarx SCS、PyUp Safety),不是所有漏洞库都覆盖。

  14. CI 产物外泄。SBOM 里含内部 npm registry URL、内部包名、commit hash,这些本身是敏感情报。在 GitHub Actions 里用 upload-artifact 时,如果仓库是 public,Artifact 也可能被外部访问(取决于仓库配置)。

  15. 跨团队多语言一致性。前端用 Syft、后端用 ORT、运维用 Trivy——三份 SBOM 格式近似但字段值略有差异,聚合到 Dependency-Track 后产生”重复组件但不同 PURL”的脏数据。治理办法是统一工具链,或在聚合层做 PURL 归一化。

  16. 签名密钥轮换。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 诉讼、一批客户流失——投产比极高。

如果你的产品要出海到美国 / 欧盟,请顺带阅读 出海合规:许可证、出口管制与数据合规


本文为工程参考,不构成法律意见。涉及具体法律风险请咨询专业法律顾问。

十二、参考资料

标准与规范

法规

  • 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

工具官方文档

商业厂商公开资料

行业报告与实践

  • 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 建设

同主题继续阅读

把当前热点继续串成多页阅读,而不是停在单篇消费。

2026-04-22 · architecture / opensource

开源许可与版权工程

面向中国工程团队的开源许可、版权与合规系列。从 GPL、AGPL、Apache、木兰协议到中国真实案例、SCA/SBOM 工具链与出海合规,讲清楚开源在工程落地中的坑与方法。