拿到匹配结果只是"发现漏洞"的终点,"修复漏洞"的起点在哪里?想象这样一个场景:一次扫描产生了 200 条漏洞匹配,其中既有 Critical 级别的远程代码执行漏洞,也有 Low 级别的本地拒绝服务漏洞。安全工程师面临一个现实问题——应该先修哪一个?
Grype 源码分析 09:软件版本比较为什么如此复杂
前面的文章中,我们分析了 Grype 如何加载漏洞数据库、匹配框架如何运转、以及不同生态系统如何实施各自的匹配策略。但在整个漏洞匹配链路中,有一个环节被我们反复提及却一直未被展开讨论——版本比较。Grype 需要为 14 种以上的软件包格式分别提供正确的版本比较逻辑,而每一套逻辑背后都对应着一个生态的历史积累、社区约定和技术规范。
Grype 源码分析 08:不同软件生态的漏洞匹配策略
在上一篇文章中,我们分析了 Grype Matcher 匹配框架的整体架构:三条搜索路径(语言生态、发行版、CPE)、Criteria 查询条件体系、result.Set 中间结果容器,以及跨 Matcher 的 IgnoreFilter 去重机制。但上一篇文章重点在"框架如何运转",并没有深入回答一个更具体的问题:为什么 apk、deb、rpm、npm、Go 这些不同生态不能共用一种匹配规则?
Grype 源码分析 07:Matcher 匹配框架
在上一篇文章中,我们详细分析了 Grype 漏洞数据库 v6 的实现原理——它如何下载、存储和查询漏洞数据。数据库提供了 vulnerability.Provider 接口,Matcher 通过这个接口查询候选漏洞记录。但是,一个关键问题还没有回答:拿到一批软件包后,Grype 如何为每个包选择正确的 Matcher?每个 Matcher 又如何构造查询条件、执行搜索、过滤结果,并最终生成 Match 对象?
Grype 源码分析 06:漏洞数据库实现原理
在上一篇文章中,我们分析了 Package、Vulnerability 和 Match 三个核心类型,其中 Vulnerability 对象是在漏洞数据库中查询得到的,查询接口由 vulnerability.Provider 定义。但是,这个 Provider 背后是什么?漏洞数据库从哪里来、如何存储、又是如何被高效查询的?这正是本文要回答的问题。
Grype 源码分析 05:Grype 的核心数据模型
之前文章分别分析了 Grype 的整体执行流程、命令行配置系统和软件包发现过程。在 pkg.Provide() 返回 []pkg.Package 之后,runGrype() 会将这批软件包交给 VulnerabilityMatcher 执行漏洞匹配,最终生成一份扫描报告。在这一整条链路中,有三个数据结构贯穿始终:
Grype 源码分析 04:从目录和镜像到软件包清单
前两篇文章从 main() 和配置系统开始,建立了 Grype 的顶层调用框架。runGrype() 完成配置加载后,第一个关键步骤就是调用 pkg.Provide(),将用户输入转换成漏洞匹配引擎可以直接使用的 []pkg.Package。这篇文章将分析 Grype 如何把 dir:、docker:、registry:、sbom: 甚至一个 PURL 字符串统一为一个软件包集合。
Grype 源码分析 03:如何解析命令行和配置
上一篇文章从 main() 开始,跟踪了一次扫描如何进入 runGrype()。在真正加载漏洞数据库(Database,源码和日志中常简写为 DB)和收集软件包之前,还有一个重要步骤:把默认值、配置文件、profile(配置档)、环境变量和命令行参数合并成最终的 options.Grype。这篇文章我们将分析 Grype 是如何解析命令行和配置的。
Grype 源码分析 02:整体流程
上一篇文章介绍了 Grype 的基本用法。这篇文章开始分析 Grype 的源码实现,我们先不深入某一种漏洞如何匹配,而是从程序入口开始,跟踪执行一条扫描命令最后是如何获取漏洞结果的。通过分析扫描命令的执行流程,我们将建立 Grype 的整体调用链,为后续分析配置系统、软件包 Provider、漏洞数据库和 Matcher 打下基础。