AgenticRepair:多维程序上下文工程加持,真实漏洞修复率提升至73%
AgenticRepair: Multi-Faceted Program Context Engineering for Agentic Vulnerability Repair
在现代软件工程中,安全漏洞修复与普通的业务 Bug 修复有着本质区别。一般的功能缺陷通常局限在特定的逻辑分支或局部代码块,开发者凭借单元测试的失败断言往往就能推导问题。但内存安全这类深层安全漏洞截然不同:它们往往跨越多个文件,深埋于复杂的指针传递与生命周期管理中,甚至可能源于数月前一次看似无害的代码重构。从漏洞被披露到安全补丁真正上线,业界的中位数耗时常常超过 70 天。
ArXiv URL:https://arxiv.org/abs/2607.29422
随着基于大语言模型(LLM)的智能体(Agent)在通用软件工程基准(如 SWE-bench)上崭露头角,利用自主智能体进行自动程序修复(APR)成为了研究热点。然而,当通用编程智能体直接被丢进真实的 C/C++ 漏洞修复场景时,往往表现得极为吃力。根本原因在于:漏洞修复需要的程序上下文,远比普通 Bug 修复更深、更散,也更依赖动态与演化视角。

针对这一核心瓶颈,最新研究提出了 AgenticRepair 框架。这项工作不单是在单 Agent 循环中添加更多工具,而是提出了多维程序上下文工程(Multi-Faceted Program Context Engineering),通过拆分出三个专门的子智能体,分别捕获代码结构、运行时执行轨迹和版本演化历史,再交由专职的修复智能体闭环落地补丁。在包含 300 个真实 C/C++ 漏洞的基准数据集 SEC-Bench 上,AgenticRepair 取得了 73% 的验证修复成功率,相比此前最强的基准系统实现了高达 29% 的相对领先。
通用智能体的盲区:漏洞修复到底缺什么?
以往针对自动漏洞修复的工作主要分为三代。第一代是基于小模型(如 CodeT5)的端到端序列学习,受制于上下文窗口,只能对单个有缺陷的函数进行补丁生成;第二代采用通用大模型进行 Zero-shot 或 LoRA 微调,虽然语义理解能力增强,但仍然受困于单文件或单函数局限,缺乏跨目录与跨文件调用的全局视野;第三代则是近年兴起的 Agent 架构(如 OpenHands、SWE-Agent、Aider 等),通过调用文件读写与测试命令在整个仓库中探索。
但安全专家在分流(Triage)并修复漏洞时,从来不会只盯着当前报错的那几行代码。通用编程 Agent 在漏洞修复中频繁折戟,暴露出三种严重的信息缺失:
-
跨文件的代码结构上下文(Code-Structure Context)缺失:C/C++ 内存破坏漏洞往往涉及别名分析、跨文件污点传播以及跨模块的内存所有权转移。扁平的代码检索工具很难理清全局的数据流与控制流。
-
底层崩溃的运行时语义(Runtime-Execution Context)缺失:AddressSanitizer(ASan)抛出的报错报告往往长达数千 Token,包含大量的调用栈帧、内存阴影区(Shadow Memory)状态以及非法访问偏移量。通用 Agent 很容易被表面报错迷惑,只做边界检查或空指针阻断,治标不治本。
-
脆弱代码模式的演化历史(Commit-History Context)缺失:许多深层漏洞并非编写第一天就存在,而是在后续引入性能优化或重构时打破了原有的隐式假设。没有版本演化历史,模型就无法理解代码为何被设计成当下这种脆弱的形态。

上图所示的 CVE-2021-30027 是一个极具代表性的案例。该漏洞位于 Markdown 解析库 md4c 中,属于未初始化值使用(Use-of-Uninitialized-Value),涉及两个文件和三个独立的触发点。追溯仓库的 Git 历史会发现,这一隐患是在此前某次提交中引入 strcspn() 优化时埋下的,那次优化从根本上改变了内存处理模式。缺乏版本历史上下文的 Agent,根本无法还原脆弱代码结构的演变根源;而没有精确的数据流分析,Agent 也只能在崩溃现场盲目修补,无法同时兼顾多个跨文件关联点。
解耦与聚合:AgenticRepair 的双阶段流水线
针对上述盲区,AgenticRepair 将整个修复流程形式化为一个由环境 $\mathcal{E}$、输入报告 $\mathcal{V}$、智能体集合 $\mathcal{A}$ 和多维上下文 $\mathcal{C}$ 构成的闭环系统:
\[\textsc{AgenticRepair}=\langle\mathcal{V},\mathcal{E},\mathcal{A},\mathcal{C},P\rangle\]系统由两个核心阶段组成:多维程序上下文工程与上下文条件驱动的补丁合成。整个架构避免了让单个 Agent 承担过载的认知负担,而是采用多智能体分工机制,前置诊断信息,降低最终决策的熵。

第一阶段:三位专职智能体并行提取多维上下文
在隔离的 Docker 沙箱中,三位上下文工程子智能体($\mathcal{A}_{\text{struct}}$、$\mathcal{A}_{\text{exec}}$、$\mathcal{A}_{\text{hist}}$)以并行方式启动,均采用 ReAct(Reasoning-Action)交互范式:
-
代码结构子智能体($\mathcal{A}_{\text{struct}}$):结合 ASan 报错与漏洞描述,分类安全漏洞类型,使用代码语义分析工具提取漏洞点周围的数据流依赖、污点传播路径、控制流分支以及危险的内存操作模式(如分配、释放、偏移)。最终提炼为包含漏洞位置、数据流摘要、结构性隐患与高层修复建议的紧凑表示 $\mathcal{C}_{\text{struct}}$。
-
运行时执行子智能体($\mathcal{A}_{\text{exec}}$):负责在动态插桩环境下触发 PoC(概念验证攻击样本)。它不仅读取静态日志,还会深入分析崩溃签名、完整堆栈回溯以及崩溃瞬间的内存对象来源(如堆块何时分配、何时被释放)。随后输出结构化的运行时上下文 $\mathcal{C}_{\text{exec}}$,明确标出崩溃语义与内存破坏根因。
-
提交历史子智能体($\mathcal{A}_{\text{hist}}$):定位核心出错函数后,对目标仓库的版本控制历史进行逆向挖掘,重点分析在引入该文件或函数变更的历史提交。它提炼出关键提交的元数据、Diff 变更摘要以及修改意图评分,生成版本历史上下文 $\mathcal{C}_{\text{hist}}$,还原脆弱模式的历史由来。
随后,这三份高度压缩、各司其职的结构化洞见被融合成一份统一的多维程序上下文 $\mathcal{C}={\mathcal{C}_{\text{struct}},\mathcal{C}_{\text{exec}},\mathcal{C}_{\text{hist}}}$。
第二阶段:基于情境记忆的补丁合成与闭环验证
拥有了完备的全局上下文后,流水线进入补丁生成阶段。负责修复的子智能体 $\mathcal{A}_{\text{repair}}$ 将多维上下文 $\mathcal{C}$ 持久化注入到自身的情境记忆(Episodic Memory)$\mathcal{M}$ 中。这意味着在后续长达几十步的交互中,修复智能体始终处于结构化高阶事实的约束之下,不会在频繁修改文件后迷失方向。
$\mathcal{A}_{\text{repair}}$ 遵循“生成最小候选补丁 $\to$ 应用补丁 $\to$ 重新编译项目 $\to$ 重放 PoC 验证”的严格闭环。只有当代码成功编译、ASan 报告中的致命错误完全消失,且未引入新的内存破坏行为时,该补丁才会被判定为合格输出。
运行时上下文带来的精确定位能力
为了具体展示这种上下文工程的作用,可以观察一个 PHP 核心引擎中的真实漏洞案例(php.ossfuzz-42501106)。

在该用例中,运行时执行智能体通过 ASan 捕获到了一个典型的堆释放后使用(Heap-Use-After-Free)与双重释放(Double-Release)模式。ASan 的回溯栈清晰展现了指针在 zend_closure_free_storage() 调用 zend_string_release() 时的释放轨迹。如果缺乏运行时上下文的专门解析,模型往往会将目光放在最后崩溃的代码行,机械地添加非空检查;而 $\mathcal{A}_{\text{exec}}$ 提炼出的运行时洞见直接指明了指针所有权在释放链路中的生命周期失配,引导后续的修复智能体在正确的引用计数逻辑上施加修改。

结合代码结构智能体提取的跨文件引用关系,修复智能体得以明确哪些宏定义或内联函数正在共享底层数据结构,从而生成了语义级别完全正确的补丁。
实验评测:73% 成功率与消融分析
评测采用了包含 300 个真实 C/C++ 漏洞的基准数据集 SEC-Bench。与依赖合成接口的模糊测试基准不同,SEC-Bench 具备完整的原生构建系统、真实的漏洞触发输入,并以动态 Sanitizer 运行结果作为确定性的判定准则(Ground Truth Oracle)。
突破性的修复成功率
在与业内知名开源 Agent 框架的对比中,AgenticRepair 表现突出:
-
大幅超越通用 Agent:在基准包含的 200 个标准 CVE 实例上,早期的通用 Agent 如 OpenHands、SWE-Agent 和 Aider(即使以 Claude 3.7 Sonnet 为基底)在面对复杂的 C/C++ 内存安全漏洞时表现均显乏力;而在涵盖 300 个完整实例(含 100 个复杂 OSS-Fuzz 案例)的严格评测中,AgenticRepair 取得了 73%(220/300) 的通过率,较最强对比基准提升了 29%。
-
多维上下文不可或缺:消融实验清晰证明了三类上下文的互补性。当移除代码结构上下文时,跨文件漏洞的修复能力显著下滑;移除运行时执行上下文后,针对 Use-After-Free 和复杂越界写入的误判率大幅攀升;而去除 Git 提交历史上下文同样造成了性能损失,印证了演化溯源对理解深层设计假设的重要性。
-
架构脚手架与底模能力的协同:实验对比了多智能体脚手架(Multi-Agent Scaffold)与单智能体(Single-Agent)架构。若将所有分析任务杂糅给单个 Agent 处理,即便上下文工具完全开放,性能也会因上下文窗口污染和注意力分散而明显衰退。同时,底座模型的推理能力至关重要——将默认的 GPT-5.2 底模替换为小型号模型后,成功率呈现断崖式下跌,表明低容量模型难以胜任对多维安全分析结论的深层逻辑综合。
关键发现与深层讨论
除了宏观成功率之外,这项研究的几项深层实证分析同样值得工程界和学术界关注:
智能体并不是在死记硬背标准答案
评估自动修复时,一个常见的担忧是模型是否在训练数据中见过人类开发者的补丁,从而通过数据泄漏(Data Leakage)作弊。作者对生成的 298 个候选补丁与人类参考补丁(Gold Patch)进行了细致的比对分析:
-
Diff 精确匹配为 0:没有一个生成的补丁与人类补丁在文本层面完全一致。
-
极低的行级重合度:补丁修改行的 Jaccard 相似度均值仅为 0.1177(中位数 0.0869),内容纯重合度仅为 0.0561。
-
高度一致的修改区域:文件级别的 Jaccard 相似度高达 0.5836。
这组数据表明,AgenticRepair 并没有机械地复现人类补丁的语法写法,而是精准定位到了相同的脆弱模块与关键函数周围,通过自主合成替代性的修复逻辑(Alternative Repairs)消除了内存安全隐患,展现了真正的推理与合成能力。
失败归因:剩下的 27% 卡在哪里?
对 80 个未成功修复实例的归因分析揭示了智能体修复系统的实际短板。失败主要集中在四类情况:未产出补丁(No Patch)、补丁格式非法导致无法应用(Improper Format)、编译失败(Compilation Error)以及修补后仍可被 Sanitizer 触发漏洞(Still Vulnerable)。
其中,由于 Git Patch 格式格式微调失败或轻微语法错位导致的低级错误占了相当比例。作者指出,只要在工作流中引入轻量级的补丁语法完整性预检工具,并进一步在验证环节加入除 ASan 之外的功能正确性与资源约束测试,理论上可以消除 80 个失败案例中的 75 个(93.8%)。
工具调用的行为特征
分析四个子智能体的交互轨迹可以发现,系统成功实现了“前置诊断,轻量执行”。三位分析子智能体在最初的几十步内快速消耗较少的步骤预算,分别完成代码结构抽象、调用栈挖掘和 Commit 检索,输出高度精炼的信息摘要;而修复智能体则将超过 70% 的工具调用精力集中在代码编辑、重编译和验证反馈循环上。这种分工有效避免了通用 Agent 常见的“一边瞎改代码、一边查阅无关日志”的混乱轨迹。
总结与启示
AgenticRepair 提供了一个非常清晰的范式演进信号:在大模型软件工程领域,单纯增加 Agent 的自主步数或简单堆砌外部工具,在面对专业壁垒极高的安全场景时存在严重的边际效用递减。
面对 C/C++ 这类涉及复杂底层状态和跨文件生命周期管理的硬核任务,决定修复上限的不是模型写代码的速度,而是向其输送的信息维度。通过多智能体协作,将代码静态结构、底层动态语义以及版本演化历史系统性地工程化,转变为易于理解的情境记忆,是通向全自动安全运营(Agentic SecOps)的关键路径。对于未来的自动化漏洞响应体系而言,这种多维上下文工程的设计思路,同样适用于漏洞挖掘、可利用性评估(Exploitability Assessment)以及更广泛的复杂系统重构任务。