来自以太坊基金会协议安全团队的笔记,关于针对真实协议代码运行协同 AI 代理的经验,包括我们如何组织工作、哪些内容经得起审查,以及客户端团队和安全研究人员可以从中借鉴什么。本文是一篇独立文章;后续文章将深入探讨各个客户端。
我们运行了什么,以及什么让我们感到惊讶
在以太坊基金会的协议安全团队中,我们一直针对网络所依赖的各类系统(如系统软件、密码学代码以及必须准确无误的合约)运行协同 AI 代理。这些代理发现了真实的漏洞。其中一个现已公开:在 libp2p 的 gossipsub 中存在一个可远程触发的 panic(恐慌),这是以太坊共识客户端运行所在的点对点层的核心部分,该漏洞已被修复并披露为 CVE-2026-34219,并归功于该团队。
代理发现漏洞并不令人惊讶。令人惊讶的是,用于发现漏洞的工作量如此之少,而用于将真实漏洞与看起来像真实的漏洞区分开来的工作量却如此之大。
本文面向希望做同样事情的客户端团队和安全研究人员。它涵盖了我们如何组织代理、候选漏洞在被算作真正发现之前必须达到的标准,以及保持结果可信的习惯。
其他地方的团队也在采用相同的方法。Anthropic 的前沿红队(Frontier Red Team)构建了一个代理,该代理编写基于属性的测试并在整个 Python 生态系统中发现了真实的漏洞。Cloudflare 通过安全研究测试工具运行了一个前沿模型来测试他们自己的系统。每个人都陷入了相同的循环:将一个强大的模型指向一个代码库,让它进行搜索,并对返回的结果进行分流。因此,真正的问题是如何做到这一点,而不被听起来自信满满的噪音所淹没。
提前说明一点:代理驱动审计的工具发展迅速,任何特定的设置在几周内就会过时。因此,本文特意探讨那些持久的方法,而不是工具。漏洞披露本身就是一个独立的话题,可能会单独写一篇文章。
代理是搜索工具,而不是预言机
指向代码库的代理是一个搜索工具,非常像模糊测试器(fuzzer)。区别在于返回的结果。模糊测试器会给你一个崩溃和堆栈跟踪。而代理会给你更多东西,包括一份报告(调用链、影响声明、建议的严重程度)以及支持它的工件,比如你可以针对真实代码运行的概念验证(proof-of-concept)。
所有这些都使得结果易于阅读且易于信任,尤其是可运行的概念验证。因此,不要计算代理生成了多少个候选漏洞。要计算有多少个被证明是真实的。
工作是如何组织的
我们针对一个目标并行运行许多代理。它们通过代码库本身进行协调,在版本控制中共享状态,并且没有中央进程来分配工作。一个代理在其他代理能看到的地方写下声明,执行工作,然后提交。
我们从 Anthropic 关于使用一组代理构建 C 编译器的文章中获得了这种方法,该方法以相同的方式进行协调。没有需要构建或维护的中央协调器,出错的可能性也更小。
角色是由发现的工作生成的:
- 侦察(Recon)将攻击面转化为具体的、可测试的假设。不是“审计解码器”,而是“这个字段在这一点之后是受信任的;这是它应该保持的属性,它可能被破坏的方式,以及能够解决这个问题的证明。”
- 狩猎(Hunting)采用一个假设,追踪代码路径,并尝试构建一个复现程序。
- 填补空白(Gap-filling)查看哪些被接受、哪些被拒绝,编写下一批假设,并跟踪覆盖率,以便代理不会一直在同一领域重复工作。
- 验证(Validation)独立地重新检查每个候选漏洞,消除重复项,并做出决定。
我们并没有发明这条流水线。Cloudflare 描述了相同的阶段:侦察、并行狩猎、独立验证、去重、报告,他们的文章帮助塑造了我们的流程。
以下是候选漏洞在被算作真正发现之前的样子:
目标: 攻击者实际可以到达的组件和入口点 不变量: 必须保持的属性 机制: 可能导致其被破坏的具体方式 成功: 可观察的证明:panic(恐慌)、停滞、接受无效输入 复现程序: 针对真实代码运行的独立工件 去重: 一个键值,这样两个代理就不会追踪同一个目标
这个模式的存在是有原因的。它强制要求一个具体的、可测试的声明以及明确的完成定义。一个必须写下可观察证明的代理不能退回到“这看起来有风险”这种模糊的说法。
无法复现就等于没有发生
有一条规则比其他任何规则都重要。除非有一个独立的工件能够针对真实代码复现故障,并且能够让非编写者成功运行,否则候选漏洞就不能算作真正的发现。
复现程序不会阅读报告,也不关心模型听起来有多自信。它要么能运行,要么不能。
它的大部分价值在于它捕获的误报。其中有三种情况反复出现,每一种都是代理因为错误的原因而蒙混过关:
- 仅在调试构建(debug build)中发生的 panic。按照软件实际发布的方式编译并运行它,数值只会发生回绕(wraps around)。没有任何东西崩溃。它看起来像是一个崩溃,但实际上并不是。
- 一个手动构建某些内部值的复现程序,这些值是任何真实输入都无法产生的,因为攻击者控制的每条路径都会在更早的时候拒绝它。该漏洞仅针对一个没有任何可达路径会以这种方式调用的函数进行“复现”。
- 在形式化验证工作中,一个通过了但并不意味着你想要的结果的证明。无论代码做什么,该语句都显然为真,或者它比你想要捕获的属性更弱。验证者得到了满足,但该定理并没有约束你真正关心的行为。
这些都不是什么新鲜事。这就像一个测试通过了,仅仅是因为它实际上没有检查任何东西。新鲜的是数量。代理编写无用版本的速度与编写真实版本的速度一样快,而且同样自信。因此,检查必须是自动的。你不能指望代理自己发现问题。
信噪比是大部分工作所在
大多数候选漏洞都是错误的、重复的或超出范围的。这不是方法的问题;这就是它的工作原理。目标是快速拒绝错误的漏洞,并用难以反驳的证明来支持真实的漏洞。
每一个幸存下来的候选漏洞都会接受两项独立检查。在正常配置下,真正的攻击者能实际触达它吗?与成功后给网络造成的损失相比,攻击者实施攻击的成本是多少?任何单个对等节点都能触发的漏洞,与需要特殊访问权限或大量资源的漏洞截然不同。
所有的东西都会与一个包含已知、已修复或已拒绝问题的动态列表进行核对。如果没有这个列表,代理就会不断重新发现同一个已关闭的问题,并一次又一次地报告它。
不同目标的接受率差异很大,而这种差异本身就很有用。针对成熟的、经过严格审计的代码运行此程序,几乎没有任何漏洞能幸存下来,但这仍然值得了解。“我们努力寻找但一无所获”也是一个真实的结果。针对探索较少的代码,或者针对经过形式化验证的代码(其中机器检查的证明覆盖了一个模型,而部署的字节码只是被假定为与其匹配)运行它,就会有更多的漏洞通过。
我们并不是唯一发现分流是困难部分的人。Cloudflare 的主要结论是,狭窄的范围胜过广泛的扫描。Anthropic 的基于属性的测试代理生成了大约一千份候选报告,然后通过排名和专家审查,筛选出顶级的报告,这些报告的准确率约为 86%。生成报告是简单的部分。我不打算在这里公布我们自己的数字;因为这些数字与特定目标绑定,它们更多地说明了目标本身,而不是方法。
代理擅长什么,以及它们在哪里会产生误导
两个方向都有炒作,所以这里有一份简单的清单,列出了代理做得好的地方以及它们产生误导的地方。
| 擅长 | 产生误导的地方 |
|---|---|
| 将规范和代码结合起来阅读 | 看起来可达但实际不可达的调用链 |
| 陈述并检查真实的不变量 | 在成功检查中作弊(因为错误的原因而通过) |
| 根据一句话的想法起草复现程序 | 夸大严重程度以匹配报告听起来的戏剧性程度 |
| 在你查看之前建议根本原因 | 跨越一系列有效步骤的漏洞 |
这种划分甚至在不同任务之间也不是稳定的。Stanislav Fort 在真实漏洞上测试了一系列模型,他称之为参差不齐的前沿,或者说,一个在一个代码库上恢复了完整漏洞利用链的模型,可能会在另一个代码库上无法完成基本的数据流追踪。你不能假设一个好的结果意味着下一个结果也能站得住脚,这也是每个候选漏洞都要单独检查的另一个原因。
最后一行是重要的一行。单个代理会话擅长一次性推理,但不擅长跨越一系列步骤的漏洞,在这些步骤中,每一步都是有效的,只是顺序错了。对于这些漏洞,代理不是搜索工具。它的工作是建议哪些序列值得通过有状态的测试工具运行。以这种方式使用,效果很好。如果用作测试工具的替代品,它就会错过最昂贵的漏洞,即那些只在一系列操作中才会出现的漏洞。
保持诚实
几个习惯就能在很大程度上使代理的发现值得信赖,而且它们都不复杂。
- 每个工件的来源:是什么产生了它,在什么上下文中,针对哪个版本。一个发现应该是你在几个月后还能重新运行的东西。
- 在关键地方的确定性:一个环境,一种构建和运行的方式,因此“复现”在每台机器上都意味着同样的事情,而不仅仅是在发现它的那台机器上。
- 规范,而不是脚本:告诉代理什么才是重要的,不变量和真实发现的标准,而不是一个编号的程序。过度脚本化的代理会像过度指定的测试一样崩溃,它们会在步骤不再有意义之后继续遵循这些步骤。一项关于代码库上下文文件的研究也发现了同样的事情:额外的要求降低了任务成功率,并使成本增加了 20% 以上,作者建议将上下文保持在最低要求。
- 由人来做最终决定:代理只负责建议。它们不决定什么是真实的,什么是已知问题的重复,或者什么内容在何时被披露。
瓶颈转移了
AI 并没有取代安全研究人员。它转移了工作。过去用于提出和追踪假设的时间,现在用于大规模地判断它们,包括构建预言机、运行分流、维护已知问题列表以及处理披露。
瓶颈并没有消失。它从发现漏洞转移到了信任结果,这是一个更好的位置,因为这正是人类判断真正发挥作用的地方。但这仍然是一个瓶颈,忽视这一点,你最终就会发布一个错误的“没问题”结论。
使这项工作奏效的实践并不新鲜。可复现的故障、真实的预言机和仔细的分流,正是这些实践在过去十五年中将模糊测试从一个研究课题变成了标准实践。工具是新的。但实践不是。
工具的变化速度有多快是一个悬而未决的问题。Nicholas Carlini 一向谨慎,曾经也是个怀疑论者,他认为指数级增长的情况值得认真对待,尽管他对此保留了很大的误差范围。如果生成端攀升得如此之快,判断端也必须随之攀升,否则产生的内容与实际验证的内容之间的差距只会越来越大。
对于以太坊所依赖的系统来说,这才是重要的部分。代理让我们能够覆盖比手动操作多得多的领域。作为交换,它们要求我们在面对一大堆听起来自信满满的声明时,做出更仔细的判断。这是一笔值得做的交易,只要你记住,判断才是真正的产品。


