漏洞扫描器匹配误差

漏洞扫描器的命中不是“这个资产已被证明可利用”,而是一个有时间截面的关联判断:扫描器把当时观察到的制品,经过组件识别、坐标与版本归一化,再与某一版漏洞情报和适用性规则连接起来。任何一层发生遗漏、误识别或过度近似,都可能把不适用的漏洞报成命中,也可能漏掉真实受影响的组件。

因此,误报与漏报不能脱离“真值单位”讨论。最低限度应固定:制品 digest 或精确 build、组件坐标与来源生态、二进制/源码包版本、漏洞或公告 ID、情报数据库快照、扫描器版本与配置,以及要判断的状态。工具之间有分歧只说明实现和数据链不同,不能把多数票当真值;一次“零发现”也不等于软件没有漏洞。

分层误差模型

层 扫描器实际在回答什么 典型误报来源 典型漏报来源
采集与范围 哪些文件、镜像层、锁文件或已安装包进入了扫描? 旧层、重复制品或开发依赖被当成当前运行资产 未解压层、私有依赖、无权限目录或不支持的包类型未进入 inventory
组件识别 文件和元数据属于哪个组件? 名称碰撞、同一组件重复计数、系统包与语言包混淆 重打包、重命名、去元数据、vendoring 或静态链接使组件不可见
身份归一化 这个名称对应哪个生态、vendor、product 与 package? 用宽泛 CPE 把同名包连到另一产品,例如语言包名称与系统产品撞名 缺少可匹配的 CPE、PURL 或发行版坐标,或 source/binary package 映射缺失
版本语义 当前版本是否落入受影响区间? 忽略 epoch、发行版 revision、预发布语义或 vendor backport,只按上游版本阈值判断 错误比较器、区间端点、别名或“版本未知时跳过”使受影响版本未命中
情报与时间 此漏洞记录在该数据快照中如何描述? 撤回、别名重复、过时受影响范围或多个 feed 重复并入 上游/供应商公告延迟、数据源覆盖不足、修改尚未同步或数据库陈旧
产品适用性 该供应商构建、平台、架构和配置是否真的受影响? 已 backport 修复却版本号未升到上游修复版;可选模块未编译仍被计入 供应商 feed 缺失、受影响配置未被建模、补丁被下游重新引入
可达性与处置上下文 漏洞代码能否在此产品中执行或被攻击者控制? 只按“依赖存在”报告,未考虑调用图、构建开关、部署路径和缓解措施 不健全的可达性分析或错误、陈旧、未验证的 VEX 把真实命中压掉
聚合与政策 多源命中如何去重、抑制和展示? CVE alias 未归并、同一组件多个位置重复报告 ignore rule、严重性阈值、首次匹配优先或输出截断隐藏了发现

这八层不是互斥分类。例如,一个系统包可先因 PURL 缺失落入 CPE fallback,再因上游阈值忽略发行版 backport,最终表现为误报。要修复的是证据链中最早失真的环节,而不是只在报告末端加白名单。

Package URL 与 CPE 的角色也不同:PURL 用 ecosystem-aware 的 type、namespace、name、version、qualifiers、subpath 标识软件包;CPE 2.3 则把命名、名称匹配、字典与 applicability language 分层。仅有一个 CPE 名称并不等于已经证明某台资产上的配置适用,详见 CPE 与 CVE 资产适用性。

三种工具代表不同工作点

工具 官方匹配链的重点 可观察的取舍 不能据此推出
Grype 从 SBOM/inventory 生成或补全包坐标,先用生态和发行版 matcher,再聚合去重;无法精确识别的其他包可回退到 NVD CPE,VEX/ignore 在后处理阶段生效 官方明确承认 CPE fallback 既可能因同名产品误报,也可能因缺少 CPE 漏报 Grype 命中就是 NVD、供应商与制品三方共同确认;或未命中就是安全
Trivy 系统包优先使用发行版公告,语言包使用生态数据源;precise 与 comprehensive 是不同 detection priority 默认 precise 为降低误报可能漏掉信息不足的包;comprehensive 用更多近似提高覆盖也会增加误报。第三方或自编译包不能自动继承发行版包语义 两种模式中较“宽”的结果更接近真值;或供应商严重性标签等于匹配准确率
OSV-Scanner 以 OSV 的 package/ecosystem/version range 为主,并可对部分语言做 call analysis ecosystem-aware range 可避免一部分通用版本比较错误;调用分析能缩小“存在但未调用”的噪声,但受语言、构建和分析覆盖限制 代码不可达已经得到完备证明;或 OSV 未收录就不存在漏洞

工具版本、数据库 build 和默认策略会变化,这张表描述的是 2026-08-11 所核验的公开实现边界,不是永久排名。

独立研究说明了什么

独立 benchmark 的首要问题不是样本多大,而是 漏洞扫描器基准真值集 如何建立:是已知依赖清单、人工验证的制品—漏洞对、可复现触发,还是仅把另一个数据库或工具当答案。若真值仍来自同一情报源,评测只能测实现一致性,不能测端到端正确性。

单条发现的验证流程

  1. 冻结证据。 保存制品 digest、SBOM 生成器、scanner 版本、完整配置、数据库 build/更新时间、命令和未过滤原始输出;不要只留 UI 截图或最后一张汇总表。
  2. 验证 inventory。 用包管理器、锁文件、build manifest、文件哈希或镜像层反查组件确实存在,并区分运行、开发、测试和残留层。
  3. 验证身份。 核对生态、namespace、source/binary package、vendor/product、PURL/CPE 和 alias;同名不是同一产品,坐标缺失也不是“无漏洞”。
  4. 重算版本。 使用对应生态或发行版的比较器,检查 epoch、revision、prerelease、受影响区间端点;对系统包查供应商公告、OVAL 和精确 package release,不能只看上游版本号。
  5. 核对情报。 回到 CNA/供应商/项目公告,检查 affected/unaffected 范围、别名、修改或撤回状态和数据时间;数据库聚合记录不是独立复核。
  6. 核对制品适用性。 查架构、编译选项、启用模块、受影响文件/函数、部署暴露面和已有缓解。此步骤可把“组件受影响”细化成“产品是否受影响”,但不自动证明可利用或不可利用。
  7. 审查 VEX。 只有当产品 ID 精确、声明者及来源可追溯、时间和版本足够新、状态理由可审计、冲突优先级明确时,才消费 OpenVEX 等 VEX 声明。保留被抑制结果,避免错误或高优先级旧 VEX 造成不可见漏报。
  8. 复扫并验证修复。 工具中 ticket 消失只是链条的再次计算;仍需确认新制品确实安装、旧层或旧节点已移除,并保存前后快照。

证据边界

相关页面

证据

基准真值的两种补充设计

实现级校正