本文大纲

ARTICLE / 技术文章

Java 项目怎么做一次真正有用的依赖漏洞扫描

软件供应链安全 · 2026/9/27

Java 项目怎么做一次真正有用的依赖漏洞扫描

一次 Maven 项目的依赖排查,让我重新认识了“漏洞扫描”这四个字。自己写的源码、引入的第三方包和已经运行的 Web 服务,适合不同的检查方式。本文只聚焦其中一类:SCA(软件成分分析),也就是识别项目依赖了什么组件,再核对这些组件版本是否命中已知漏洞。

先确认扫描对象

静态代码分析(SAST)看自研代码中的可疑实现;动态测试(DAST)对运行中的应用发起测试;SCA 主要检查开源和第三方依赖。SCA 发现“某个版本有已知漏洞”,并不自动证明本系统已经能被利用,还需要确认依赖是否进入交付物、受影响功能是否被调用、入口是否暴露。

对 Maven 多模块工程,一个实用做法是先生成 SBOM,即软件物料清单,再用漏洞数据库扫描。这样可以把直接依赖和传递依赖放在同一张清单里,方便重复检查和交付留档。CycloneDX Maven 插件的 makeAggregateBom 目标就是为多模块工程生成聚合清单。

一条可以复查的扫描路径

在项目根目录,先固定并记录实际使用的 CycloneDX 插件版本,再生成聚合 SBOM。例如我当时的项目使用:

mvn org.cyclonedx:cyclonedx-maven-plugin:2.9.1:makeAggregateBom

接着确认根目录 target/bom.json 确实产生、包含预期模块和依赖。使用当前 OSV-Scanner V2 时,可以明确指定这份文件:

osv-scanner scan source -L target/bom.json --format table

也可以递归扫描整个工程,让它发现支持的锁文件和 SBOM:

osv-scanner scan source -r .

OSV-Scanner 官方文档说明了 V2 的命令、SBOM 文件名识别规则和递归扫描行为。bom.json 是它识别的 CycloneDX 文件名之一。自动化里还应区分退出码:官方文档将 1 定义为扫描发现漏洞或其他发现,127 为一般错误,128 为未找到可扫描的软件包;退出码为 1 不是工具崩溃。输出与退出码说明

看报告时,不要只数 CVE

我先看四项:受影响组件数、漏洞条目数、最高严重程度、是否已有修复版本。同一个依赖可能命中多条通告,因此“漏洞数”不等于“有问题的包数”。随后逐条记录组件名称、当前版本、修复版本、是否为传递依赖,以及它在本系统里的实际用途。

排序也不能只按 CVSS 分数。一个处理外部上传文件的高危依赖,与一个只在构建阶段使用的同分依赖,暴露面不同。我的处理顺序是先解决有明确升级路径且处于关键调用链的项,再为暂时不能升级或无修复版本的项记录缓解措施与复查日期。扫描结果只反映扫描当时的漏洞库信息,发布前和依赖升级后都需要重跑。

把扫描变成持续工作

单次报告适合发现问题,长期价值来自固定流程:构建时生成 SBOM、在 CI 中扫描、保存结果、按影响范围处理,再在下一次发布前复查。团队可以自己设定哪些等级阻止发布;不要把“没有 Critical”误解成系统没有安全风险,也不要因为报告有 High 就不经分析地升级所有包。

SCA 回答的是“我们用了哪些已知有问题的组件”。它与代码审查、运行时防护和补丁回归各有作用。把这几个环节接起来,扫描结果才会从一封告警邮件变成可执行的维护计划。

资料:CycloneDX Maven 插件 · OSV-Scanner V2 源码扫描 · OSV-Scanner 输出与退出码