The Cloudflare Blog

Build your own vulnerability harness

8.5内容质量
Build your own vulnerability harness

TL;DR · AI 摘要

构建一个模型无关的漏洞扫描系统,能提升企业级安全分析的覆盖范围和准确性。

核心要点

  • 使用多个模型进行交叉验证,能有效提升漏洞检测的准确性。
  • 模型应作为可互换组件,以增强防御覆盖范围。
  • 构建系统时应从一开始就设计为模型无关,以适应未来模型的变化。

结构提纲

按章节快速跳转。

  1. 介绍构建模型无关漏洞扫描系统的重要性及背景。

  2. 模型应被当作可互换组件,以增强防御覆盖范围和适应模型变化。

  3. 使用不同模型进行交叉验证,能提升漏洞检测的准确性和全面性。

  4. 系统设计应从一开始就支持模型无关,以适应未来模型的变化。

  5. 介绍如何管理状态控制、消除误报并协调大规模的漏洞处理流程。

思维导图

用一张图看清主题之间的关系。

查看大纲文本(无障碍 / 无 JS 友好)
  • 构建模型无关的漏洞扫描系统
    • 模型作为可互换组件
      • 提升防御覆盖范围
    • 跨模型交叉验证
      • 提升漏洞检测准确性
    • 系统设计原则
      • 模型无关设计

金句 / Highlights

值得收藏与分享的关键句。

#AI#安全#模型#漏洞扫描
打开原文

构建你自己的漏洞检测框架

2026-06-18

  • Dan Jones
  • Alexandra Godoi
  • Grant Bourzikas

17 分钟阅读

几周前,我们发布了 Project Glasswing 项目的初步发现,研究了当前沿安全模型被应用于企业代码库时会发生什么。我们还探讨了我们的防御架构如何适应,以保护我们的基础设施和客户免受前沿 AI 带来的威胁。自那以后,AI 生态系统继续迅速变化 —— 那些紧密围绕单一模型构建的开发人员已经经历了当该模型不再可用或被更强大的模型取代时会发生什么。这些市场变化进一步强化了我们的核心观点:无论哪一天哪种基础模型领先,代理工作流程的未来都不会在单一模型、提示或单代理会话中找到。

从本地化的安全“技能”转向持续、全舰队的扫描流水线,需要一种将模型视为可互换组件的架构。依赖单一模型会限制防御覆盖范围,因为同一系统倾向于以完全相同的视角查看代码路径。为了解决这个问题,模型应频繁互换并交叉测试。通过在流水线中使用不同的模型(例如,使用一个模型进行初步发现,使用完全不同的模型进行验证),我们可以确保漏洞通过不同的逻辑集进行交叉检查。此外,真正的企业级框架必须超越孤立的仓库,追踪跨仓库依赖项中的漏洞,最终将数千个原始候选者过滤到一个可信的、经过筛选的可操作修复队列中。

本文旨在实际探讨如何构建这种与模型无关的层,重点介绍我们如何管理状态控制、消除误报,并在大规模上协调端到端的筛选。

提前回答两个异议

第一篇文章阐述了为什么通用编码代理无法完成这项工作。主要问题是代理一次只能持有一个假设,覆盖真实仓库的一小部分后,就会填满其上下文窗口,然后在上下文压缩过程中丢失信息。如需更多详情,请阅读那篇文章。

在继续之前,我们想回答两个可能的问题。

“为什么不使用子代理,而使用框架?”子代理是有用的,而且是一个不错的起点。但安全分析需要数百个独立的调查,这些调查可以跨运行持续存在,不共享上下文窗口,并且可以在之后重新定义范围并交叉参考。它需要持久性、去重、可恢复性,最终还需要全舰队的依赖追踪。这是一个编排问题,而一个提示无法带你到达那里。

“这篇博客文章只是前沿模型的广告吗?”不。我们的方法以框架为中心,而不是模型。在漏洞发现方面,我们使用当前最适合我们需求的前沿模型。当我们将不同的模型指向同一个目标时,每个模型都会发现不同比例的漏洞。框架才是持久的部分。如果你构建自己的系统,请从第一天起就设计为与模型无关。这将允许你自由选择任何模型,而不会受到限制。

一切从一项技能开始

我们从一个约450行的安全审计技能开始,最初只在一个仓库上运行,并不断调整提示信息,直到发现真正的漏洞。后来,我们添加了协调机制,这成为了整个系统的基础。真正的价值在于提示信息本身,而我们的提示信息几乎未变,仍然保留了初始技能中的攻击者场景、漏洞类别和反模式检测。

该技能被设计为在一个会话中执行一个七阶段的审计:

  • 三个并行的研究代理进行侦察并编写 architecture.md 文件。
  • 每个攻击类别都有一个 Hunter 代理运行,试图破坏代码,而不是审查代码。
  • 对抗性验证器尝试推翻每个发现。
  • 生存下来的发现被写成一份可读性高的人类可读的漏洞报告。
  • 它们也会以 findings.json 的形式发出,并遵循一个模式,机械检查会验证该文件。
  • 最后,一个全新的代理独立地重新验证每个发现与源代码的匹配情况。
  • 经过重新验证并存活下来的发现被提交到 ingest API。

第一个技能几乎直接映射到后来的框架:

技能阶段 | 框架阶段 ---|--- 侦察代理编写 architecture.md | 侦察 猎人按攻击类别运行 | 猎取 验证器推翻发现 | 验证 存活的发现成为报告 | 报告 findings.json 机械检查模式一致性,而不是正确性 | findings 中行号和函数的机械验证 新代理重新验证发现 | 独立验证

该技能有效,但它很快揭示了自身的局限性。查看覆盖率指标,单次运行只能发现你通过多次运行发现的漏洞的一半左右。根据我们的经验,它发现的漏洞往往偏向于更简单和不那么微妙的漏洞。一旦你的流程基本上是“运行十次然后手动比较”,你可能需要开始考虑一个真正的框架。

在运行和微调该技能时,我们遇到了三个障碍:

  • 上下文耗尽:一小时后,上下文窗口被填满,模型会吞噬自己的记忆,立刻忘记它整个上午追踪到的漏洞。我们通过完全外部化状态,将大语言模型视为一个无状态的计算引擎,打破了这个瓶颈。
  • 持久性:运行过程中发生崩溃意味着需要从头开始。由于一个AI速率限制错误或连接问题就丢失数小时的工作,这是一种非常昂贵的方式来意识到你需要更好的架构。
  • 跨仓库推理:一个仓库会话完全看不到使用它的应用程序之间的关系,当你检查组件之间的接口时,出现的漏洞数量可能比预期的要多。

建议:一个真实但最小的框架仅包括保存在数据库中的 Recon、Hunt 和 Validate 阶段,以及一个不能提交自己发现的独立 Validator。在你有多个重要的仓库之前,应完全跳过跨仓库追踪。在你被噪音淹没之前,可以跳过专门的去重代理。从你的开发环境中开始一个技能,让提示信息正常运行,只有在缺少下个架构阶段是具体阻碍你时,才构建下一个架构阶段。

将技能编码为一个流水线

大多数该领域的 AI 安全文章都集中在单个仓库或精选的基准上;以这种方式运行整个舰队并进行跨仓库追踪,我们尚未在其他地方看到相关描述。我们的代码库涵盖了大量不同语言的混合使用,包括 Rust、Go、C、Lua、TypeScript 和 Python,同时还包括各种配置管理系统、静态配置以及各种额外的上下文信息。因此,我们必须想出一种适合我们自己的新方法。从第一次斜杠命令运行到能够覆盖 128 个不同仓库的舰队扫描器,自动查找并询问相关依赖项,整个过程大约用了六周时间。规范化工作基本上是机械性的:我们将技能的每个阶段提升到自己的代理中,为其背后设置数据库,并在前端添加一个协调器。映射几乎是 1:1 的。

整个舰队在一个统一的框架上运行,无需针对每种语言进行调整,并追踪仓库之间的依赖关系。虽然将语法卸载到模型上使系统语言无关,但其区别在于其能够追踪仓库之间的依赖关系。框架本身并不关心它是在查看 C 指针还是 TypeScript 文件;它专注于安全编排的高层逻辑。这使我们能够在数百个不同的代码库之间进行扩展,而无需编写自定义的语言解析器。

两阶段的漏洞研究工作流程

我们的整个漏洞研究工作流程都建立在一个两阶段的操作框架之上:漏洞发现框架(VDH)和漏洞验证系统(VVS)。

VDH 作为我们的发现引擎,主动扫描代码库以揭示潜在的安全问题。一旦漏洞进入 VVS(允许多个框架向其输入),它们会经历去重、判断和最终修复等阶段,我们将在后面详细讨论。

我们为 VDH 使用一个模型,但为 VVS 使用一个完全不同的模型,因此这两个模型实际上是在相互验证。这在安全性方面有明显的好处:通过迫使模型 B(VVS)判断模型 A(VDH)的输出,你可以确保发现结果是由一组完全不同的逻辑权重和训练数据进行评估的——这些数据作为一个无偏见的、对抗性的第三方,其唯一职责是无情地测试模型 A 的假设。在操作上,我们从将模型提供者视为可互换的商品中获益。模型提供者可以随着时间的推移,甚至在同一个模型版本中,更改温度、缓存和推理努力预算。我们不是构建一个依赖模型行为随时间保持一致的系统,而是构建了一个能够吸收下游波动而不崩溃的框架。

第一阶段:漏洞发现框架(VDH)

第一部分已经介绍了每个代理/阶段的作用,我们将讨论其中未涉及的部分:阶段之间的粘合剂,以及决定所有这些是否能正常工作的几个细节。

代理/阶段

主要职责

子代理/工具

绘制目标架构并映射潜在的威胁向量

3 个并行的 Recon 子代理生成 architecture.md

按类别运行攻击,编译片段,探测二进制文件

它会生成兄弟代理(这些代理根据模型的不同,处理舰队任务的 9% 到 20%)。它会与 Wishlist 工具进行交互并写入其中。

机械地检查发现,然后对抗性地推翻它

以两轮运行:第一轮普通代码处理初始的模式/路径检查,然后一个独立的代理尝试在发现可以被记录之前推翻该发现。

Gapfill

为覆盖率为空的单元生成新的狩猎任务

为任何测试不足(区域 × 攻击类别)的单元生成新的狩猎任务,确保这些单元仍然显得薄弱

Dedup

识别并合并重叠的发现

结合确定性代码和代理,按根本原因对发现进行聚类,并实时合并

Trace

遍历依赖图;生成消费者仓库任务

遍历图,将狩猎任务添加到每个已识别的消费者仓库中,以确保跨仓库的错误被发现

Feedback

从现有报告中学习并优化未来的运行

从验证失败、浅层运行和重复遗漏中,即时重写排队的提示,使未来的任务更加精准

生成可读的报告

只是一个脚本,不需要模型

表1:漏洞发现工具(VDH)

第4到第8阶段作为连续的生产者-消费者循环运行。随着初始狩猎的推进,Gapfill、Feedback和Trace代理生成新的任务;Dedup将重叠的发现重新合并在一起,循环的其余部分继续处理队列。这确保了在循环后期发现的漏洞仍然会被验证、报告并与其他代码进行检查,以确保它不包含相同的错误,所有这些都在同一运行中完成。

这样拆分流程可以确保严格的上下文控制。如果你填满了上下文窗口,模型将开始产生幻觉。我们让每个代理的任务高度聚焦,保持上下文使用量低于总窗口的25%。采用“读取所有文件”的天真方法会每次都会超过这个限制。

我们遇到的一个问题是,在并行处理之前需要考虑持久性。你不希望因为一个不可预见的错误而丢失一个五小时的运行。每个阶段都写入一个SQLite数据库,键为(run_id,repo,stage)。任何阶段都可以恢复、重试或被拉入到后续的运行中,而无需重复工作。发现会实时流式传输并保存,因此崩溃只会导致飞行中的任务丢失,而不会丢失其他内容。

建议:有时,一个短暂的API错误会以文本形式出现在(200 OK)响应流中,而不是抛出代码异常。对于协调器来说,这看起来就像一个任务干净地完成。你必须明确分类响应文本,而不仅仅是信任异常类型,否则你可能会将空运行记录为成功。

动态威胁建模

在Recon阶段,代理会编写威胁模型,而不是被提供一个。除了大约十种内置的攻击类别(包括各种注入方式、内存损坏、协议解析、时间侧信道等),Recon代理可以即时发明特定于仓库的类别,每个类别都有自己的方法。它会为该代码库编写一个定制的分类法,用于更精确地限定Hunter代理的范围。

仅仅阅读源代码不足以理解其在压力下的行为,尤其是在C和其他低级语言中存在微妙的未定义行为错误时。Hunter代理会超越代码阅读,进入主动执行阶段。它们会编译片段、构建小型版本并攻击它们。质量的最大飞跃来自于为Hunter提供一个沙箱(基于unshare构建),以便崩溃二进制文件。

建议:如果 harness 本身在 Docker 中运行,那么该沙箱需要设置 seccomp=unconfined 和 apparmor=unconfined,否则它将默默地启动失败。这是一个只需一行的修复方法,如果你不是嵌套容器化的专家(比如我们),它能帮你节省一天的头痛时间。

微分叉和愿望清单

除了核心流水线阶段之外,我们还添加了两个专门的机制,使猎人能够显著自主地调整其关注点并请求外部资源,而不会影响正在进行的分析:

同级分叉:这有助于确保如果猎人代理发现了一个超出当前范围的有趣代码路径,它不会偏离轨道。它使用工具调用来分叉一个具有精确结构种子的同级代理。在整体舰队中,这约占任务的 9%,但该比率高度依赖于模型——从接近零到约五分之一,具体取决于哪个模型在进行狩猎。

愿望清单:当代理需要一个它没有的工具时,例如验证者确认概念证明(PoC)或猎人想要构建某物(如特定的构建环境、虚拟机或某些生产配置文件),它会写入一个中央愿望清单。它为系统提供足够的上下文,以便在人类提供依赖项后,系统可以自动重新运行该任务。其中一些任务可以部分自我修复:如果容器需要在运行后重新构建并进行一些更改,可以通过一个通用的编码 harness 监控日志,实现自动完成。

自愿望清单添加以来,它已被写入 25,472 次,涉及 128 个仓库。这是代理与我们沟通的主要方式。在我们撰写本文时,有一个愿望清单条目是:“我需要一个 FreeBSD 虚拟机来确认这个 PoC 的端到端。”

全舰队跨仓库追踪

在初步清理之后,一个追踪代理会检查不同软件组件之间的连接方式。它寻找特定的路径:潜在攻击者是否能从外部向系统中的某个易受攻击部分发送有害输入?如果答案是肯定的,追踪代理会自动在消费者仓库中生成新的狩猎任务。为了使这工作,你需要一个统一的跨仓库符号索引和准确的依赖关系图。这使你能够发现标准单仓库扫描所遗漏的深层次系统性缺陷。

在我们的 harness 跨整个舰队的仓库运行后,我们发现了两个只有在大规模执行时才浮现的教训。

首先,去重本身就是一个问题,大到需要专门的代理来处理。当你扫描少量的仓库时,你可以手动检查重叠的漏洞。简单的字符串匹配或文件路径检查在这里帮不上忙。判断两个复杂的逻辑漏洞是否确实是同一个根本漏洞听起来很简单,但实际上并非如此。它需要如此多的认知推理,以至于我们不得不部署专门的去重代理来清理噪音,同时还配备了它们自己的启发式方法和减少工作量的方式。

其次,不要过早地引入静态分析。我们全程使用了 Semgrep,但猎人在一个月的运行中从未调用它一次。他们更愿意阅读并运行代码。相比之下,愿望清单是系统中使用最频繁的工具。关注代理实际使用的工具,而不是你认为他们想要的工具,是值得的。

代理会修改源代码,使其自身的攻击手段能够奏效,然后得意洋洋地报告它刚刚制造的漏洞。它会编写一个测试,证明一些完全同义反复的结论,比如“exec() 执行事物,因此是关键漏洞”。或者它构建一个能够运行但毫无意义的攻击,因为其背后的威胁模型本身就是荒谬的。如果你的框架没有积极地对抗这种行为,那么你所构建的只不过是一种更快地制造垃圾的方式。

一个 Hunter 在被允许提交任何内容之前,必须明确说明威胁模型。它必须准确地定义攻击者是谁,以及漏洞跨越了什么边界或打破了什么假设。输出模式的排序强制执行了这一点。这一要求消除了那些空洞的发现,比如“如果用户拥有数据库写入权限,他们就可以写入数据库”这类毫无意义的发现。

每个确认的发现都会附带一个 PoC,以测试的形式编写,该测试针对原始、未修改的代码库运行。这可以防止代理修改源文件以强制攻击成功。如果没有可行的 PoC,我们将该发现视为虚假。实际上,这可能是一个 Hunter 编写了一个三十行的解析循环,启用内存保护后运行它,并演示错误读取的步长是从堆栈地址而不是预期的消息体中产生的。你可以自己重新运行它。此外,每个确认的发现还必须附带一个建议的补丁。最终到达我们审核队列的是一个经过验证的漏洞、一个可运行的测试和一个功能性的 git diff,而不是仅仅对问题的模糊文字描述。

在攻击路径能够存活之前,确定性代码(以普通代码编写,而不是另一个模型)会机械地验证所引用的文件和路径是否确实存在,并确认补丁和测试是否解析正确。这个验证器不能自己记录发现;它的唯一任务是积极地反驳 Hunter 的理论。如果允许 Hunter 自己来评判自己的作业,它将自信地验证其输出的一切。

我们不会声称我们的系统有误报率。代码库中没有所有真实漏洞的标记集合,因此任何声称的召回率数字都是完全推测的。我们能够观察的是,重新运行是否持续发现新漏洞(确实如此),以及在多次运行中覆盖率是否仍在增长。这只是一个代理指标,因为你无法确定单个代码库中到底存在多少漏洞,但这是一种衡量有效性的足够好的方法。

第二阶段:漏洞验证系统(VVS)

从框架中得出的发现只是分拣过程的开始,所有发现都会进入一个单一的、共享的 VVS,目前该系统总共包含 145 个仓库中的 13,841 个发现。对如此大量发现进行分拣本身就是一个巨大的工程问题,它与漏洞发现同样重要。这个分拣引擎使用与框架不同的模型,分为三个不同的任务。

生成/子代理/工具

识别漏洞是否已经存在于系统中,或者是否已经被作为内部 Jira 问题提出

确定性:普通代码构建文件、函数、信任边界和罕见标记的倒排索引,然后为每个发现生成一个简短的候选列表

概率性:去重代理在该简短列表上进行推理,使用稳定的跨运行键重新打开现有记录

判断

生产可达性和验证

单个代理 —— 从 MCP 服务器构建有关漏洞的上下文,以了解服务在生产环境中的大致情况。它会搜索维基、Jira、git、配置以及所有其他可用来源,以判断该漏洞是否确实适用于我们的生产环境,并据此对漏洞进行评分。它还会将漏洞与源代码进行验证,以了解该漏洞是否仍然存在于最新的主分支上。

修复

生成补丁,运行回归测试

在修复前后运行回归测试(仅限受影响的测试;只有在无法按测试过滤时才运行完整套件)。要清除关卡,目标测试需要在修复前后实现干净的失败→通过翻转。如果修复后的测试失败,或者全局运行检测到下游回归,提交将自动被阻止并标记为需要人工干预。

表 2:漏洞验证系统(VVS)

去重

使用 LLM 将每个发现与所有其他发现进行比较,其复杂度为 O(N^2),在规模扩大时会完全崩溃。为了将模型移出关键路径,确定性代码会构建反向索引,以结构化数据(修改的文件/函数、信任边界、稀有标记)为基础,生成一个简短的候选列表。只有在那时,代理才会查看这个简短列表,以判断一个修复是否可以关闭多个漏洞。稳定的跨运行键确保重新发现的漏洞会重新打开现有记录,而不是生成新的记录。

上下文判断

判断是对幸存下来的内容进行第二次、独立的检查。代理会重新检查最新信息,从部署、环境和配置上下文中提取信息,以确定代码路径是否可以在生产环境中到达,并识别仓库所有者。这个过程将“现在可被利用”从“真实但潜在”和“真实但提交到错误组件”中筛选出来。它将一堆混乱的发现转化为以风险驱动的编排工作流。

自动修复

Fixer 会获取建议的补丁和单元测试,将其重写为与仓库风格一致的格式,应用差异,并运行目标测试。干净的失败→通过翻转是理想的唯一自动清理情况;修复后的测试失败会阻止提交。Fixer 从不自行合并代码;必须有人审查该分支。这个关卡是不可协商的人工介入安全措施,使变更管理合规能够拥有干净且不可破坏的加密变更记录。如果允许模型自由打补丁,它可能会高兴地修复一个安全漏洞,同时悄悄地破坏一个不相关的功能或引入数十个新漏洞。

在所有三个分类任务中,每个代理都仅限于一个狭窄的任务,包裹在确定性的账簿代码中,且没有人在未对干运行进行批准的情况下向生产环境写入内容。虽然该流程将工程瓶颈从发现漏洞转移到审查和落地修复,但 Fixer 仍然是系统中最年轻、最慢的部分。

成本

在一组仓库上运行数百个代理并不便宜,但至少支出的形状是可预测的。几乎所有计算预算都直接用于搜索阶段。这使得 Gapfill 成为我们成本与覆盖率的杠杆,因为每次额外的运行成本大约是初始搜索的一半。

由于每个仓库的成本差异很大,我们按仓库而不是按运行次数进行预算。我们对每个仓库设置了严格的任务上限,并启动一个规模在 50 到 200 个之间的工作者池。这样你可以将资金花在真正发现问题的仓库上,而不是浪费在那些没有发现问题的仓库上。

这也是为什么,对我们来说,大规模扫描是周期性的积压清理,而不是针对每个 Pull Request 的检查。对一个复杂仓库进行全面扫描可能需要数小时;最糟糕的一次运行耗时仅略多于 14 小时。更便宜、更小的工具才是完成这项任务的正确选择。

我们如何判断它是否有效

我们通过跟踪自动化流程如何高效地将有意的工程噪音过滤为高质量、可操作的发现,来衡量我们系统的有效性。因为我们故意调整我们的猎人(Hunters)以过度报告可能被串联成更大攻击的微妙原始信息,我们真正的成功指标是在数据到达人类之前,我们能多精准地提炼出这些原始数据的庞大山丘。

为了衡量这一点,我们跟踪了随时间推移,每经过一个验证阶段后,原始发现的数量究竟有多少能够存活下来。由于我们侦察阶段(Recon phase)注入了更好的上下文信息,初始验证拒绝率从 40% 下降到 11%,而高完整性的发现占比则从 35% 上升到 58%(代表约 12,057 个终身发现)。

在撰写本文时,从原始候选者到可操作发现的终身分解如下。

VDH 部分

漏洞发现工具(Vulnerability Discovery Harness,VDH)

  • 原始候选者:在独立验证之前,发现工具所发出的所有内容。
  • 需要复现:看起来合理但需要手动复现才能被信任的发现。
  • 验证阶段被拒绝:验证者推翻了威胁模型、攻击路径、受影响代码或证据。
  • 重复项:被合并到同一工具其他发现上的候选者。
  • 通过验证:通过独立验证环节并进入 VVS 的发现。
  • 被转往其他地方的漏洞:故意从该流程中转出的发现。

VVS 部分

漏洞验证系统(Vulnerability Validation System,VVS)

  • 其他漏洞工具:其他自动化来源,向同一验证系统提供数据。
  • 系统中的总漏洞:经过摄入后的总池。
  • 重复项:去重过程识别出的已被其他规范发现或工单覆盖的发现。
  • 错误仓库 / 其他 / 不是风险:噪音桶:误归因的发现、纵深防御或潜在风险。
  • 发送给团队的漏洞:已确定、干净的发现,准备进行修复。
  • 判定为可被互联网利用:高优先级的发现,现实攻击者可以在生产环境中触发。
  • 未判定为可被互联网利用:低优先级但可操作的漏洞(生产问题、依赖风险或配置错误)。
  • 最终严重性分类:用于为工程团队分配优先级的分类。

工具的核心指标不是推测性的召回率分数,而是尽可能将未确认的发现数量控制在接近零的水平。架构必须是一个不断过滤的漏斗。

  • 在 VDH 生成的 20,799 个原始候选者中,只有约 12,057 个通过了验证。
  • 当这些候选者被推送到 VVS,并与另一个工具的发现合并后,中央池的总数达到了 13,841 个。
  • 去重代理将 5,442 个发现标记为重复项。
  • 其中有 1,154 个被路由到队列中,标记为“错误仓库”或“低风险”,并在适当的情况下重新循环回系统中。
  • 最终,这为工程团队留下了 7,245 个可操作的发现结果。

传统的合规规则基于静态的 CVSS 分数来规定任意的修复时间窗口(例如,“30 天内修复所有高风险问题”)。我们的上下文判断层将这种合规性检查转变为真正的风险管理。

该架构能够追踪发现结果的来源,这意味着修复一个根本原因可以解决一整群发现结果,而不是仅仅修补个别问题。VDH 系统性能的衡量方法是将仓库划分为(区域 x 攻击类别)单元,并反复运行 Gapfill 代理,直到它不再产生新的发现结果。每当更新底层提示时,我们会将其与一个保留的仓库进行测试,以查看该总覆盖率单元数量是否确实发生变化。

Harness 通过将自动健康信号连接到流水线中,以尽早发现系统故障。如果一次搜索异常快速完成,并且未能生成子搜索或间隙任务,通常表明依赖项崩溃,而不是代码库干净。为了解决这个问题,系统会将任何以零发现结果完成的 Hunter 代理标记为“浅层”,并立即将其重新排队以进行新一轮运行。

最后,我们系统鲁棒性通过前面提到的独立分类处理得到加强。通过使用不同的模型和独立的逻辑权重重新评估所有提交内容,我们确保了与发现所用的具体模型无关的无偏、对抗性验证,从而提供了一层持久的信任机制。

这一切远未结束。我们不断改进系统,它还远未达到完美的科学水平。但目前,原始候选发现结果的成本已经变得很低,唯一值得做的工作是将它们转化为可靠、可验证的代码修复。

构建你自己的 harness 意味着接受 AI 模型的波动性,但你的编排层不必如此。通过将安全逻辑与任何单一供应商解耦,强制进行对抗性验证,并自动化你的分类流水线,你可以将大量 LLM 噪声转化为可靠、覆盖整个舰队的防御引擎。

我们的“北极星”指标:衡量实际世界中的速度

每个代码库都有所不同,为了向你展示这在现实世界中是如何运作的,我们基于标准仓库运行映射出一个现实的基准。请注意,这代表对一个仓库的一次性处理;随着时间的推移,由于持续的舰队循环去重、过滤并重新利用发现结果,它将整个生命周期候选数量减少了约 65%。

通过自动化补丁节省的工程工时:我们不关注静态基线,而是通过其技术吞吐量、处理速度以及消除手动分类瓶颈的能力来衡量流水线的健康状况:

  • 初始验证削减:对于一个标准仓库(约 3 万行代码),这会生成 100 个初始发现结果,完整运行需要 3 到 4 小时,并在整个过程中保持高度专注的上下文窗口。
  • 压缩:去重和上下文判断层并行处理这些候选结果。在 3 小时内,系统将大约 100 个原始候选结果压缩并精炼为 80 个独特的、高保真度的错误。
  • 修复措施:自动化修复工具以平均每只虫子5分钟的速度处理这80种不同的漏洞。总计,系统可以在大约14小时内发现、验证、去重并打开功能性的拉取请求。

缩短关键缺陷的平均修复时间:当然,你不能一次性将80个补丁全部部署到生产环境,否则会导致问题。为了确保部署的安全性,我们的系统采用分层发布策略:

  • 关键暴露控制:系统将关键、高风险和可利用的漏洞(平均80个中的10个)隔离出来。我们优先安排这些漏洞进行人工审查,并将其引入发布周期,确保它们在5天内完全修补。
  • 逐步强化:其余的潜在风险、次要配置异常和低优先级漏洞将在15到20天的时间窗口内逐步部署到生产环境中,以确保平台的稳定性。

我们如何处理所有这些补丁

这些发现来自于一个隔离、封闭的实验,旨在对我们的代码进行压力测试。它们并不代表我们实时生产环境中存在未修补的活跃漏洞。

由于该工具在我们的测试环境中持续运行,当你阅读到这段文字时,这些具体的数字已经完全过时了。流水线中发现的每一个漏洞都附带了一个工作测试用例,用于演示漏洞和一个草稿补丁。我们的安全团队正在系统地处理这些报告并应用必要的修复,这意味着你每天使用的Cloudflare产品已经针对这些攻击向量进行了主动加固。

随着这篇博文的发布,我们还发布了用于开发该工具的初始技能。在发布之前,我们对这个技能进行了轻微的清理,使其更容易理解和集成,但技能本身基本上保持不变。希望该工具能够尽快发布。这可以作为你自己的漏洞工具、技能或其他需求的起点:github.com/cloudflare/security-audit-skill

如果你的团队正在处理相同的问题,并希望进行交流,请通过 [email protected] 与我们联系。

[if astro]>server-island-start<![endif]

安全

AI

工程

研究

漏洞