jerzy99jerzy/cve-digest
GitHub: jerzy99jerzy/cve-digest
一个以 EPSS/KEV 驱动的 CVE 分诊流水线参考实现,用确定性优先级判断结合受防护的 LLM 摘要来帮助安全团队聚焦真正存在利用风险的漏洞。
Stars: 0 | Forks: 0
```
___ _ ___ ___ _ ___ ___ ___ _____
| _ \ /_\ | _ \ _ \/_\ | _ \/ _ \| _ \_ _|
| / / _ \| _/ _/ _ \| _/ (_) | / | |
|_|_\/_/ \_\_| |_|/_/ \_\_| \___/|_|_\ |_|
```
**智能化的 CVE 分诊机制,优先处理真正会造成威胁的漏洞,并将其自身的 LLM 边界视为攻击面。**
这是一条自动化流水线,负责摄取最新的 CVE,利用真实的漏洞利用信号(EPSS + CISA KEV)丰富其上下文,结合资产环境对其进行排序,并使用带有防护机制的 LLM 智能体生成每日分阶摘要。最初是作为 [Torq](https://torq.io) 上的工作流构建的;本代码库是一个可移植的开放式参考实现,并包含了其背后的设计与安全推敲过程。
## 问题所在
安全团队常常在海量的 CVE 中疲于奔命。原始的 CVSS 会导致过度警报(所有东西似乎都是“严重”的),而简单地使用“用 LLM 总结今天的 CVE”的工具只会让情况变得更糟:它只是通过一个完全不了解*可利用性*、*资产相关性*或*自身信任边界*的模型来洗白第三方文本。
## 设计方法
```
feed -> enrich (EPSS + KEV) -> prioritise (context-weighted: estate + VEX) -> guardrailed agent -> tiered digest
untrusted text deterministic, not the model LLM summarise-only data, not actions
```
以下三个决策主导了该设计:
1. **判断是确定性的,而非交由模型决定。** KEV 成员资格和 EPSS 概率在代码中决定优先级([`cve_digest/prioritize.py`](cve_digest/prioritize.py));KEV 项目始终优先于非 KEV 项目。LLM 绝不凭空捏造严重程度;它只负责总结我们已经排序好的内容。
2. **订阅源文本默认是恶意的。** CVE 描述(及其 id)是攻击者可以编写的文本,最终会出现在 prompt 中。它会被验证、清理、隔离,并限制在一个永远不会成为指令的 DATA 通道中([`cve_digest/guardrails.py`](cve_digest/guardrails.py))。
3. **智能体没有被滥用的权限。** 它仅获得只读的上下文丰富查询权限,并返回经过 schema 验证的数据。没有写入工具,也没有执行动作。任何与既定事实相矛盾的输出(例如模型试图降低 KEV 项目的优先级)都会被丢弃到人工审查通道,而不会被信任。
## 为什么是 Agentic,而不是定时任务 + 脚本
针对每个 CVE 的分支处理(KEV 项目会获得更深度的背景信息;P3 项目只会得到一行确定性结果,无需模型调用)、受限制的只读工具使用,以及一个自我检查过程(根据我们掌握的事实和询问的 CVE 重新验证输出)。单一的巨型 prompt 无法做出这些控制流和完整性决策;而单纯的脚本无法进行总结。编排(Orchestration)才是核心所在。详见 [`docs/architecture.md`](docs/architecture.md)。
## 优先级逻辑
| 信号 | 来源 | 作用 |
|---|---|---|
| 已知被利用 | CISA KEV | 事实覆盖 -> 始终为 P1 |
| 漏洞利用概率 (30天) | FIRST EPSS | 主要权重 |
| 影响上限 | CVSS 基础分 | 仅作排序参考 |
| 资产存在性 | 你的 SBOM,通过 OSV 匹配 | 非 KEV 项目的乘数 |
| 上下文中的可利用性 | 你的 VEX (OpenVEX / CycloneDX) | 断言优先级低于 KEV;抑制非 KEV 的噪音 |
CVSS 告诉你漏洞*可能*有多糟糕。EPSS 和 KEV 则告诉你它*现在*有多大概率会对你造成伤害。资产存在性告诉你这到底是不是你需要面对的问题。
### 为什么主要权重是 EPSS 而不是 CVSS
这是整个项目中最关键的核心决策。CVSS 在漏洞披露时对漏洞的最坏技术严重程度进行一次评分,且从此不再更新。如果仅依赖 CVSS 进行分诊,目录中的大部分内容都会显示为“高”或“严重”——这样生成的摘要只是在重播它原本旨在取代的“海量警报流”。EPSS 回答了分诊真正需要的问题:不是*这可能有多糟糕*,而是*在未来 30 天内被利用的可能性有多大*。这是 FIRST 的机器学习模型,每天根据真实的漏洞利用证据(公开的漏洞利用代码、传感器和蜜罐遥测数据、威胁情报)进行重新训练,因此它会随着威胁态势的变化而变化,而不是停留在披露时的评分上。
KEV 和 EPSS 是互补的两半。KEV 是反应性的且具有高置信度:CISA 仅在确认存在野外利用后才会列出 CVE,因此命中即是观察到的事实,流水线将其视为无条件的 P1 覆盖。EPSS 则是主动且具预测性的:它在漏洞进入 KEV 之前就标记出*可能*被武器化的内容,从而为在攻击者之前打补丁争取了时间。正是由于同时依赖这两者,CVSS 才被降级为排序参考,且永远不会单独决定层级。
这样做的回报是对紧急队列的大幅压缩。已发表的对基于 EPSS 优先级分析的研究表明,可以将“立即修复”的漏洞集合从高 CVSS 阈值标记的大约 20-30% 的漏洞缩减至 2-5% 左右,而对实际覆盖范围几乎没有影响(该数据出自 EPSS 相关文献,并非本流水线实际测量的结果)。对于一个每天都要面对 CVE 轰炸的团队来说,这种压缩决定了生成的摘要是一份大家会付诸行动的报告,还是一份大家学会忽略的噪音。
存在性匹配是通过 OSV 而不是 CPE 进行的,这是刻意为之的。NVD 基于进行匹配,SBOM 包含 package URL,但目前没有权威的 purl 到 CPE 的映射;连接这两者意味着必须对 CPE 字符串进行模糊匹配,并接受可能存在的静默误报。OSV 的索引方式与 SBOM 一致,其 `aliases` 字段包含了同一漏洞的 CVE 标识符,提供了一个精确的连接键,整个过程中无需进行任何名称转换。它是可选且开放失败的(fail-open):如果没有配置 SBOM(`CVE_DIGEST_SBOM`),或者查询失败,每个 CVE 都会以中性权重归类为 `unknown`,且排序保持不变。`unknown` 绝不会被当作不存在处理——OSV 的静默意味着该产品不在其生态系统内,而不是我们没有该产品。
### VEX:上下文中的可利用性,排序低于既定事实
资产存在性回答了*这个组件是否属于我们*。VEX 则回答了更尖锐的问题:*在我们交付的运行方式中,受漏洞影响的路径是否可达*。操作员提供的 VEX 文档(OpenVEX 或内嵌的 CycloneDX,路径由 `CVE_DIGEST_VEX` 指定)包含针对每个 CVE 的状态——`not_affected`、`affected`、`fixed`、`under_investigation`——其中 `not_affected` 是可用的最高价值的噪音削减手段,因为它能消除单靠存在性匹配无法去除的已确认误报:例如漏洞函数从未被调用、该功能在编译时已被移除、或者配置已缓解了该漏洞。
设计的要点在于 VEX 在信任顺序中的位置。VEX 声明是一种*断言*,而不是观察到的事实,因此它的排序严格低于 KEV 的事实。它仅流经非 KEV 的上下文权重,而 KEV 评分会忽略该权重,因此没有任何 `not_affected` 声明可以将一个已知被利用的 CVE 降级出最高层级——断言永远不能覆盖野外观察到的漏洞利用事实。这与“prompt 不是控制指令”的原则相同,被应用于第二个输入源:更权威的信号是通过架构设计获胜的,而不是通过配置。在其适用的范围内,VEX 确实优先于 OSV 的推断(`affected` 会覆盖资产 `absent` 的降级,因为与产品关联的生产者声明胜过基于名称的猜测),并且每个应用的的状态都会在摘要中展示并记录,因此抑制操作是可审计的,绝非静默执行。在两个方向上均开放失败(Fail-open):缺失或格式错误的文档不会改变任何结果。
## 安全态势一览
| 信任边界 | 控制 | 代码 |
|---|---|---|
| 订阅源摄取 (B1) | id 验证 + `sanitize_feed_text` + 隔离的 DATA 通道 | `guardrails.py`, `agent.build_prompt` |
| 模型输出 (B2) | schema + 边界,KEV 完整性锁定,id 自检,审查通道 | `guardrails.validate_output`, `agent.triage` |
| 交付 (B3) | 渲染时在每个通道进行转义;受信任的标记仅由我们添加 | `digest.render`, `delivery.render_email`, `delivery.render_slack` |
所有防护机制事件都会被记录,因此运行日志可供 SIEM 摄取。它们涵盖了每一层:摄取(`event=rejected`、`nvd_pages_exhausted`)、背景丰富(`epss_batch_failed`、`estate`、`osv_pages_exhausted`、`vex`)、模型边界(`injection_marker`、`kev_downgrade_dropped`、`schema_reject`、`cve_id_mismatch`)以及审查通道(`unscored`)。丢弃操作绝不是静默的——它是一个可供检测程序触发响应的结构化事件。
## 快速开始
```
pip install -e ".[dev]" # runtime + dev (pytest, ruff, mypy)
export NVD_API_KEY=... # optional, raises the NVD rate limit
export LLM_API_KEY=... # your provider; read by agent.call_model (never hardcode)
# 将 agent.call_model 接入到你的 provider / 自托管 model / Torq orchestrator,然后:
cve-digest # or: python -m cve_digest.run
```
支持 `.env` 文件(通过 python-dotenv 加载),并已在 gitignore 中忽略。
## 测试与 CI
```
ruff check . && mypy cve_digest && pytest -q
```
`tests/` 锁定了核心支撑功能:清理、渲染转义(无活跃链接/提及)、id 验证、schema 边界、KEV 完整性锁定与降级路由、P3 无模型保证、KEV 主导地位,以及在无网络情况下的端到端 `build_digest` 运行。CI([`.github/workflows/ci.yml`](.github/workflows/ci.yml))会在每次推送和 PR 时运行 lint + 类型检查 + 测试;预定的摘要生成任务是独立的,并且在 `call_model` 接入前处于禁用状态。
## 诚实的范围与局限性
- 参考实现。`call_model` 层是一个存根,你需要将其接入你的提供商或自托管模型;围绕它的防护契约才是关键部分。在未配置提供商的情况下开箱即用:模型调用按项目隔离,因此 P1/P2 项目会路由到人工审查通道(附带通知),而不是导致崩溃,同时 P3 项目依然会获得确定性的文本行。接入 `call_model` 即可让审查通道重新生成摘要。
- 资产权重的好坏取决于你的 SBOM 覆盖范围,且 OSV 仅覆盖开源生态系统:日常订阅源中的商业软件和硬件都会被归类为 `unknown`。请预期这是最常见的情况。如果没有 SBOM,非 KEV 排序将完全依赖漏洞利用信号。
- 资产索引在每次运行时都会基于 OSV 重建,并采用顺序记录填充;对于大型的容器 SBOM,这意味着成千上万个请求,而这些请求的结果仅在 SBOM 发生变化时才会改变。基于 SBOM 摘要进行缓存的索引属于计划中的状态层(去重 + 水印)功能,而不是在这里草草了结。
- 暴露面(受影响的实例是否面向互联网、是否为生产环境)*未*被建模。SBOM 回答了存在性,而不是暴露面;该维度需要结合云资源上下文,但在此尚未实现。
- EPSS/KEV 保证了广度,但不能涵盖一切。针对性的或零日漏洞(zero-day)活动在信号跟上之前不会出现。摘要生成工具是分诊的辅助手段,不能替代检测和威胁狩猎。
## 命名由来
代号是 **Rappaport**,源自斯坦尼斯瓦夫·莱姆的小说《主人的声音》
(《Glos Pana》),其主题是一个来源不明的信号以及试图
解读它的科学家们。莱姆的观点贯穿全书:团队从模糊
消息中提取出的含义更多地反映了团队自身而非消息本身,并且
无法从内部验证对其的任何解读。
这就是该流水线在代码中贯彻的原则。模型对 CVE 的解读
永远不会覆盖既定事实(KEV 完整性关卡);来源追踪将测量的
信号与推断区分开;真正的疑虑会被路由到人工审查,而
不是通过主观投射来了结。该包保留了 `cve-digest` 这个名字,这也很直白地说明了它的产出:一份经过分诊的 CVE 摘要。
## 来源
最初是作为 Torq 上的一个 Agentic 工作流构建的。本代码库是一个干净、可移植的重新实现和说明文档。不包含任何专有的工作流内部细节,也不包含特定于客户的数据。
## 作者
Jerzy Siwecki - 专注于安全工程、检测、云安全态势以及 AI 原生的安全自动化。
## 许可证
MIT。详见 [`LICENSE`](LICENSE)。
标签:C2, CVE分诊, Google Gemini, GPT, 安全规则引擎, 安全运营, 实时处理, 扫描框架, 提示词注入防护, 漏洞管理, 逆向工具