漏洞修复 Agent 需要哪些上下文
文章围绕 AI Agent 修复跨语言项目中 47 个 CVE 的案例,讨论修复前应提供哪些上下文、限定哪些决策权限,以及如何验证修复有效。重点是自动修复的输入与验收边界。
AI 深度解读
AI Agent 修复了 47 个 CVE,横跨 PHP、Node.js、Python 和 Go,听起来像是模型能力的胜利。但这篇文章真正想讲的是:修复之前,系统提供了什么事实;修复之后,又靠什么证明漏洞消失了。
作者把答案归结为「上下文包」和独立验证流程。对程序员来说,它的价值是提供了一套可拆解的工程方法:让 Agent 根据依赖、漏洞和运行环境的证据修改代码,再用扫描、测试和人工审核判断结果。不过,47 个漏洞的具体修复记录,原文没有展开。
Agent 动手前,哪些事实必须先准备好
给 Agent 一个 CVE 编号和仓库权限,它通常能做出修改。但改动可能落错位置:升级了不相关的依赖,误读受影响版本范围,把上游补丁套进已经分叉六个月的代码,甚至通过删除功能消除漏洞。
作者认为,修复需要四类事实:实际安装了什么、漏洞代码能否被执行、修复会影响什么、怎样确认修复有效。上下文包负责把它们组织起来,而不是让模型临场猜测。
第一类是精确清单。原文列出 package-lock.json、poetry.lock、go.sum、composer.lock,要求获取完整解析后的依赖及版本,同时记录部署环境中的解释器和系统包。最终要以实际部署版本为准,不能只看仓库文件。
这里要补一个技术边界:go.sum 主要记录模块校验信息,不能单独当作完整的部署依赖清单。原文把它与其他锁文件并列,表述略粗。对 Node.js 项目,同样需要确认生产安装结果与锁文件是否一致。
第二类是标准化漏洞公告。每个 CVE 应包含受影响产品、机器可读的版本范围、弱点类型 CWE、攻击入口和权限要求。作者建议从 NVD、GitHub Advisory Database、osv.dev 获取信息,再转换成统一结构,减少模型对公告文字的误读。
第三类是可达性:应用发布的代码,到底会不会调用漏洞所在的函数。原文提到 npm ls、pipdeptree、go mod why 和调用图分析,并要求将结果标成 reachable、unreachable、unknown。
这些工具各有边界。依赖树能说明包为什么被安装,却不能直接证明某个漏洞函数不会执行。作者在 FAQ 中也承认,动态语言的完整调用图分析存在漏判。
无法确认是否可达,就按可达处理。
最后两类信息是修复选项与治理规则:升级、回移上游补丁、配置缓解或提交风险接受申请,各自涉及哪些破坏性变更、配置调整和迁移;服务归谁负责、是否暴露公网、处理什么数据,以及提交如何追溯和回滚。
作者称,中等服务的上下文包通常有 200–600 行结构化数据,并由工具自动生成。他们认为手写内容一周内就可能过时,但没有提供这两个判断的统计依据。
为什么修复数量不能代表安全收益
原文开头引用的热门故事有 127 个赞、1.2M 次浏览,卖点是修复了 47 个 CVE。这些数字能说明传播热度,不能证明修复质量。
作者更关心队列怎么排:先处理进入 CISA 已知被利用漏洞目录 KEV 的问题,再处理可达且暴露公网的问题,然后是可达的内部服务,最后才是不可达和仅开发环境的问题。原文部分列表存在重复,实际表达的是这套顺序。
原因很直接:漏洞有多严重,与当前服务有多容易被攻击,是两个问题。
CVSS 描述严重程度,EPSS 估计未来 30 天内被利用的概率。原文用两个例子说明差别:CVSS 9.8、EPSS 0.01,与 CVSS 7.5、EPSS 0.6,不能只按前一个分数排序。攻击入口和权限条件也应进入判断,例如 AV:N/PR:N/UI:N 表示网络攻击入口、无需权限、无需用户交互。
不过,这段向量本身不能完整描述攻击复杂度,仍要结合其他字段和服务环境。
对 Agent 的要求因此不只是「优先修高分漏洞」,还包括明确报告哪些问题被延后、为什么延后。如果它修完了大量低风险项,却让一个已被利用的远程代码执行漏洞继续等待,数量反而会制造错误的安心感。
扫描变绿之后,还要证明什么
作者给出的修复循环是:复现、最小修复、重新验证、回归测试、审查差异。
先保存修复前的证据。条件允许时,用安全测试或概念验证输入复现漏洞;做不到,至少保留扫描结果。但扫描器告警只能证明检测到了已知风险,不能替代所有运行时验证。
接着优先采用供应商修复版本,选择脱离受影响范围所需的最小升级。原文反对为了一个 CVE 一次跨越三个主版本,因为升级本身也可能引入兼容性问题。
真正关键的是重新扫描之后的追问:告警为什么消失?
可能是版本确实修好了,也可能是 Agent 排除了扫描路径、修改了扫描配置,或者选择了扫描数据库尚未覆盖的版本。直接依赖升级后,旧版本还可能通过传递依赖留在树中;甚至依赖已经安全,仓库里多年前复制进来的漏洞代码仍然存在。
扫描变绿是验证的输入,不能独自充当修复结论。
之后要跑服务自身的测试,至少覆盖变更依赖的集成位置。最后审查 diff,确认没有夹带重构,依赖声明与锁文件一致。
作者明确保留人工边界:公网服务的 diff 需要人工批准;认证、加密、个人信息和支付相关变更由人决策;风险接受必须有书面证据和到期时间;发布之前必须存在经过测试的回滚路径。原文用「30 秒审核」强调审核成本,但没有证明复杂变更能在这个时间内审完。
他们还列出了声称实际见过的失败模式,包括上下文过量、模型虚构修复版本、扫描误绿、漏掉传递依赖,以及忽略复制进仓库的代码。lodash 4.17.21 是文中举出的真实版本示例,但作者强调,不能相信模型凭记忆判断哪个版本修复了哪个漏洞。
我的判断
我认同这篇文章对职责的划分:Agent 执行修改,扫描器、测试和审核机制共同提供证据。它也提醒团队,依赖升级需要围绕实际部署环境判断,不能把版本号变化直接兑换成安全收益。
但文章更像一份操作经验清单,没有给出足以验证效果的实验报告。47 个 CVE 来自它引用的热门故事,原文没有公开逐项记录、修复 diff、失败次数,也没有和人工流程或 Dependabot 做对照。因此,不能据此判断这套方案成功率更高、成本更低。
「所有失败都是上下文失败」也说得过满。事实齐全后,模型仍可能理解错误或修改错误;测试不足同样会让错误通过。作者说误修复率不接近零就该补上下文,这个排查方向有用,但不能排除验证器和测试本身的问题。
与常见版本升级 PR 流程相比,这套方法增加的是可达性、利用概率、延后理由和验证证据。文章对 Dependabot 的描述可以帮助理解这个定位,却没有提供能力对比实验。
另外,「两个脚本加一个策略文件」是合理起点,「一个下午完成」则有明显前提。查询 OSV API 并输出 JSON 比较容易,可靠识别部署版本、动态调用路径和相关测试范围,往往才是工作量所在。
能拿来做什么
- 先选一个 Node.js 服务生成上下文 JSON,合并实际安装依赖、OSV 查询结果和服务暴露情况。可达性证据不足的条目保留为
unknown,交给后续验证与审核。 - 把验证器做成独立脚本,接收漏洞 ID,重新扫描完整依赖树并运行相关测试,逐项输出通过或失败及原因,同时检查扫描范围和配置是否改变。
- 给 AI 编程助手提供简短策略文件,写明 KEV 优先、最小修复、强制复测和人工决策边界,并要求每次提交解释延后处理的漏洞。
- 按原文建议记录两个指标:从公告出现到验证修复的时间中位数,以及需要回滚或重做的误修复率。先用一个服务检验流程,再决定是否扩大自动化范围。