极狐GitLab 软件供应链安全:SBOM 与持续依赖扫描落地
极狐GitLab 软件供应链安全:SBOM 与持续依赖扫描落地
软件供应链攻击正在从"边缘风险"变成"日常威胁"。SolarWinds、Log4j 等事件之后,企业安全团队越来越关注一个问题:我们到底用了哪些第三方组件?它们有没有已知漏洞?当新的 CVE 披露时,能不能第一时间知道自家中招了没有?
这篇文章从"软件物料清单(SBOM)"切入,介绍极狐GitLab 基于 CycloneDX 的依赖项扫描如何在流水线中生成 SBOM、与安全咨询数据库比对识别已知漏洞;同时说明"持续依赖扫描"(Continuous Dependency Scanning)如何在数据库更新时自动重扫、捕获新披露的 CVE 而无需重跑流水线,以及这一能力对 SBOM 优先的供应链治理支撑。
一、为什么 SBOM 成了供应链安全的"基础设施"
SBOM(Software Bill of Materials,软件物料清单)本质上就是软件成分的"配料表"。它用结构化格式记录了一个项目依赖了哪些开源组件、版本号、许可证信息,以及组件之间的传递依赖关系。
在监管层面,美国行政命令 EO 14028、欧盟 Cyber Resilience Act 都在推动 SBOM 成为软件交付的标配。对企业来说,SBOM 的价值不止于合规:
漏洞响应:拿到 SBOM 就能在 CVE 披露后秒级定位受影响系统
许可证审计:避免 GPL 等强 copyleft 许可证的合规风险
依赖可视化:搞清楚"我的依赖的依赖"到底引入了什么东西
极狐GitLab 的依赖项扫描从 17.x 版本开始全面转向 CycloneDX 标准格式,这是目前业界最广泛采用的 SBOM 规范之一。
二、基于 SBOM 的依赖项扫描:解耦架构的优势
传统的依赖扫描(如 Gemnasium 分析器)是"一体化"设计:分析器在 CI/CD 作业里既检测依赖、又比对漏洞数据库、再生成报告。这种方式在极狐GitLab 17.9 之后已标记为弃用,长期发展方向是基于 SBOM 的解耦扫描。
2.1 解耦扫描的工作流程
基于 SBOM 的扫描把流程拆成了几个独立阶段:
依赖项检测:分析器解析项目中的锁定文件(如
package-lock.json、pom.xml、go.mod等),构建完整的依赖关系图SBOM 生成:输出符合 CycloneDX 1.4/1.5/1.6 标准的 SBOM 文件,命名格式为
gl-sbom--.cdx.json漏洞扫描:SBOM 通过依赖扫描 SBOM API 上传至极狐GitLab 实例,由内置的漏洞扫描引擎将组件与极狐GitLab 安全咨询数据库进行匹配
报告生成:分析器整合漏洞结果,输出
gl-dependency-scanning-report.json,并在合并请求中展示安全小部件
这种解耦架构的好处很明显:
支持所有分支扫描(自 17.9 起),不再局限于默认分支
扫描与漏洞匹配分离:SBOM 生成后可以被多种下游能力复用,包括持续依赖扫描、许可证扫描
行业标准格式:CycloneDX 是 OWASP 推动的开放标准,便于与其他安全工具链集成
2.2 开启方式
在 .gitlab-ci.yml 中引入官方模板即可启用:
include:
- template: Jobs/Dependency-Scanning.v2.gitlab-ci.yml这个模板会自动:
检测项目中的锁定文件和依赖关系图
生成 CycloneDX SBOM
调用 SBOM API 进行漏洞匹配
上传依赖扫描报告
2.3 关键配置项
变量 | 默认值 | 说明 |
|---|---|---|
|
| 最大扫描目录深度, |
|
| 排除路径(glob 模式) |
|
| 是否包含开发/测试依赖 |
|
| 启用静态可达性分析,聚焦实际被代码调用的依赖 |
|
| 无锁定文件时从清单文件提取直接依赖(准确性较低) |
其中 静态可达性分析 是一个值得关注的特性:它会解析源代码,标记 SBOM 组件中哪些被实际调用。这意味着你可以优先处理"真的在用且有漏洞"的依赖,而不是被大量未使用的传递依赖淹没。
2.4 依赖解析与清单回退
有些项目(尤其是 Maven 和 Python)可能没有提交锁定文件。极狐GitLab 提供了两种补救机制:
依赖项解析:在
.pre阶段运行最小化镜像,使用原生构建工具(Maven Java 21 / Python 3.12)自动生成锁定文件。注意:解析环境可能与项目实际构建环境不完全一致,高度自定义的项目建议手动提供锁定文件清单回退:直接从
pom.xml、requirements.txt、build.gradle等清单文件提取直接依赖。这种方式只能拿到直接依赖,无法确定精确版本,准确性最低
三、持续依赖扫描:不跑流水线也能抓新漏洞
基于 SBOM 的扫描解决了一个问题:"我现在有哪些漏洞?"但供应链安全还有一个更棘手的问题:"昨天还没有漏洞,今天 CVE 数据库更新了,我的项目中招了吗?"
传统做法是在每次数据库更新后手动重跑流水线,这显然不现实。极狐GitLab 的持续依赖扫描(Continuous Dependency Scanning,也称持续漏洞扫描 CVS)就是为解决这个场景设计的。
3.1 工作原理
持续依赖扫描的核心逻辑很简单:
注册组件:在默认分支上至少成功运行一次基于 SBOM 的依赖扫描,将项目的组件信息(名称、版本、PURL)注册到极狐GitLab 实例
监听公告更新:极狐GitLab 安全咨询数据库定期更新(聚合了多个来源的安全公告)
后台自动比对:当新公告发布时,后台作业(Sidekiq)自动将已注册组件与新公告进行比对
创建漏洞:如果发现匹配,直接在项目的漏洞报告中创建新的漏洞记录
关键点:整个过程不需要重新运行 CI/CD 流水线,也不会生成新的安全报告产物。
3.2 与流水线扫描的关系
持续依赖扫描和流水线中的依赖扫描是互补关系,不是替代关系:
能力 | 流水线依赖扫描 | 持续依赖扫描 |
|---|---|---|
触发时机 | 代码变更、MR、定时流水线 | 安全咨询数据库更新 |
扫描范围 | 当前代码状态的依赖 | 默认分支已注册的组件 |
产物生成 | 有(SBOM + 扫描报告) | 无(仅创建漏洞记录) |
适用场景 | 开发阶段实时发现 | 生产环境持续监控 |
需要注意的是:持续依赖扫描能自动"创建"漏洞,但不能自动"消除"漏洞。当漏洞被修复(如升级依赖版本)后,仍需通过默认分支的流水线扫描来更新组件注册信息,并将已不存在的漏洞标记为 resolved。
3.3 支持的包类型
持续依赖扫描支持以下 PURL 类型的组件:
cargo、conan、go、maven、npm、nuget、packagist、pub、pypi、rubygem、swift
注意:Go 伪版本不被支持,因为伪版本无法准确映射到具体代码状态,可能导致漏报。
3.4 私有化部署的额外配置
在私有化部署环境中,需要在管理员区域选择要同步的软件包仓库元数据。极狐GitLab 会定期发布软件包元数据更新,私有化实例需要同步这些数据才能进行准确的漏洞比对。
在 JihuLab.com(SaaS)上,同步由极狐GitLab 统一管理,无需额外配置。
四、一个完整的落地示例
假设你有一个 Node.js 项目,想在流水线中启用基于 SBOM 的依赖扫描 + 持续依赖扫描。.gitlab-ci.yml 可以这样写:
stages:
- build
- test
- security
include:
- template: Jobs/Dependency-Scanning.v2.gitlab-ci.yml
# 自定义依赖扫描作业(可选,用于覆盖默认配置)
dependency_scanning:
stage: security
variables:
DS_MAX_DEPTH: -1
DS_STATIC_REACHABILITY_ENABLED: "true"
DS_EXCLUDED_PATHS: "**/test/**,**/docs/**"运行一次默认分支的流水线后,项目的组件信息就被注册到实例中了。之后无论你是否提交代码,只要安全咨询数据库有新公告,持续依赖扫描就会在后台自动检查你的项目是否受影响,并在漏洞报告中展示结果。
五、SBOM 优先的供应链治理思路
把上述能力串起来,可以形成一个"SBOM 优先"的软件供应链安全治理闭环:
生成:每次流水线自动生成 CycloneDX SBOM,作为可审计的交付物
扫描:SBOM 上传 API 进行漏洞匹配,在 MR 阶段拦截有漏洞的依赖变更
监控:持续依赖扫描在后台跟踪新披露 CVE,无需重跑流水线
响应:漏洞报告统一管理发现的问题,结合极狐GitLab 的漏洞管理流程分配修复责任人
合规:SBOM 文件可直接用于许可证审计和供应链合规申报
这个闭环的核心优势在于把安全左移到了依赖引入的那一刻,同时通过持续监控覆盖了"代码不变、威胁变"的长期风险。
六、写在最后
软件供应链安全不是一次性扫描就能解决的问题。极狐GitLab 基于 SBOM 的依赖项扫描 + 持续依赖扫描组合,把"生成物料清单—识别已知漏洞—持续监控新威胁"三个环节串成了自动化流水线。
对于已经在使用极狐GitLab 旗舰版的团队,建议尽快从 Gemnasium 分析器迁移到基于 SBOM 的扫描(v2 模板),并确保默认分支至少成功运行过一次扫描以激活持续依赖扫描。对于还在评估供应链安全方案的团队,CycloneDX 标准格式 + 后台自动监控的组合,是一个值得优先考虑的落地路径。
参考文档

