posts/ai-patch-benchmark.md
让 Agent 修漏洞,跑过一个 PoC 还不够
如果你正让 Claude Code、Codex,或者团队里的编码 Agent 帮忙修一个 CVE,最容易出现的画面大概是这样的。
PR 已经推上来,原来的 PoC 跑不出来了,Agent 还很自信地写了一段总结。CI 绿了几项。然后你盯着合并按钮,手有点悬。
先别急。
让一个已知 PoC 失效,只能说明补丁过了第一道门。它可能绕开了这个输入,也可能把出问题的分支提前 return 了,还可能顺手弄坏了原本没问题的调用链。安全补丁最讨厌的地方就在这儿,代码看起来安静了,不代表风险真的走了。
最近 Trail of Bits 公开复核了 1Password 的 FLAWED 漏洞补丁研究。争议围着一个很抓眼球的数字,1Password 在 6 个复杂漏洞、6,080 次补丁尝试中报告,只有 26% 的补丁既解决漏洞又没有明显改变程序行为。1Password 的原始说明在这里。
Trail of Bits 的回应不是说 Agent 已经可以自动合并安全 PR。他们指出,26% 混入了两类很不像日常开发的条件,22% 的试验提示 Agent 去套用错误修复,36% 的试验不允许编译或运行测试。去掉这些条件后,他们在可运行代码、且未被要求使用错误修复的子集中看到 3,067 个补丁里有 2,634 个阻断了给定 exploit,也就是约 86%。完整复核在这里
注意这个措辞,阻断给定 exploit,不等于完整修好。
两份公开材料并不互相抵消,反而把同一个坑照得更亮。你问的是 Agent 能不能完成复杂漏洞修复,还是它能不能在给定工具、给定提示和给定测试下把一个样本打过去。问题只差几个字,验收口径能差一整套 CI。
别把一条 PoC 当成裁判
1Password 的研究提醒我们,补丁会有看起来像修好、实际上留下缺口的情况。Trail of Bits 的复核又提醒我们,把 Agent 放进不能跑测试、甚至被提示去改错地方的环境,再把结果平均进一个大数字,也会让结论失真。
好家伙,双方都在说一件老生常谈但总被跳过的事,测试条件本身就是结果的一部分。
这事不只是一场研究口水仗。9 月初公开的 PatchBench 论文 也做了相近的检验。它把历史漏洞移进新的仓库上下文,故意不让参考修复轻易落在崩溃调用栈上,再加上额外的安全和语义验证。论文在 213 个 C 或 C++ 任务、11 个 Agent 上发现,只用原始 PoC 验证会把解题率平均放大 1.83 倍。
不是每个团队都要造一套 benchmark,谁也没这个闲工夫。但合并一份 Agent 安全补丁前,至少别把验收缩成「原 PoC 不崩」这一行。
Trail of Bits 自己也给出了一份挺有意思的人类基线。他们回看 2024 到 2026 年间 236 次安全评估里的 2,265 份开发者首个补丁,仍有 283 份没有完整解决报告的问题,约 12.5%。这里的任务、上下文和审查方式都不能拿来和 Agent 直接比高低,不过它给了一个很清醒的提醒,人类拿着详细漏洞报告,也会在第一次修复时漏路径。

公开审查记录中,人类开发者的首个补丁也并非次次完整。它是基线,不是与 Agent 的直接对决。
所以别把流程设计成「Agent 写,Agent 说修好了,Agent 再给自己打个满分」。这不是自动化,这是把同一面镜子放了三遍。
给 Agent 补丁的四道门
这套顺序不绑定某个模型,也不要求你把安全团队的测试框架全搬过来。它更像一张合并前的验收卡,先把最容易被跳过的证据留下。
第一道门,原始问题能否被重放。
在隔离的 fixture 或测试环境里,确认漏洞版本确实会失败,打上补丁后才转为通过。若原版本都复现不了,后面的绿色结果没有解释力。依赖没装齐、构建坏了、测试超时,都只能标记为「结论未定」,不能被 Agent 写成「漏洞已修」。
第二道门,同一个根因还有没有别的出口。
这里不是要求你公开或制造可利用输入。你只需要追问,原 PoC 打的是哪个调用方、哪段生命周期、哪种边界条件。再选至少一条不同入口或清理路径去测。很多表面修复只在崩溃点塞了个条件,换一个 caller,老毛病还在。
第三道门,修复有没有伤到正常业务。
漏洞修复经常碰权限、解析、缓存、重试和资源释放。修了攻击路径,顺手把合法请求拒掉,CI 也许没叫,用户会先叫。保留与业务语义有关的 pass-to-pass 测试,跑项目已有回归,再按栈的能力加 sanitizer、静态检查或有界 fuzz。别把这几个词当护身符,能跑什么取决于项目,但必须在 PR 里留下跑了什么、没跑什么。
第四道门,结果能不能让下一个人复核。
保存漏洞版本与补丁版本的 commit,测试命令、环境限制、失败日志和剩余风险。代码审查最怕一句「我都验证过了」。有命令、有输出、有明确的未覆盖路径,审查人才知道该补哪一刀。
原始 PoC 在隔离环境中失败
补丁后原始 PoC 通过
至少一条同根因变体通过
回归与项目测试保持通过
构建失败或测试缺失时,结论标记为未定

原始 PoC 只是入口。变体路径、回归和可复核记录,才让一次修改接近可合并的安全补丁。
Trail of Bits 此次一起公开的 post-patch-validation 和 review-walkthrough 两个技能,做的也正是把这类步骤塞回 Agent 工作流。前者的安装和使用说明值得安全工程师看一眼。它不会替你背书,但会逼 Agent 去写验证、看另一条路径、记录构建失败。
有点子牛逼的地方不在于多了一个「安全 Agent」。而在于它把 Agent 最擅长的反复跑、反复查,接到人类最该负责的验收标准上。
26% 和 86% 都不是合并按钮
我不太想替两边宣布谁赢了。
26% 是一份特定基准下的公开结果,86% 是另一组工作条件与另一种指标下的公开复核结果。把前者读成「AI 没用」,或把后者读成「Agent 已经能独立修漏洞」,都省略了最贵的那部分,测试设计、审查、回归和维护者最后的判断。
对一个要进生产的安全 PR 来说,真正值得问的不是「模型这次几分」。而是「这个补丁修的是根因,还是只让我们手里那一个输入闭嘴了」。
下次 Agent 提交漏洞修复时,先别盯它写得有多像人。把第二条路径跑起来,再决定要不要按下合并。
你们现在的安全 PR,最容易漏掉的是变体路径、回归测试,还是可复核的验证记录?