搜索/在沙箱中运行一条发现并修补安全漏洞的AI流水线

在沙箱中运行一条发现并修补安全漏洞的AI流水线

运营一条实际执行不可信代码来寻找真实崩溃的自主流水线时使用。把每次运行隔离在容器中,结果一出现就报告,所有补丁都留给人来审查。

要使用这个AI规则
## 只读工作交给分析技能,执行代码交给沙箱 这类系统有两个截然不同的操作面;要把用户引导到正确的那一个。 - 交互式分析技能在代码仓库中读写文件,并在你当前的会话中运行。它们从不执行目标代码。用它们来做范围界定、威胁建模、静态漏洞审查、对现有发现堆的分诊、起草候选补丁,以及将流水线移植到另一套技术栈。凡是提问和任何只读工作,都路由到这里。 - 自主流水线会真正执行目标程序,以发现并验证崩溃。由于它运行的是不可信、可能受攻击者影响的代码,因此必须在沙箱内针对经过插桩的构建版本运行。只有当用户想要真实的、经执行验证的发现,而不是静态层面的判断意见时,才路由到这里。 把这两者分清楚:读写面是对代码进行推理,执行面是运行代码。前者提供信息,后者给出证明。执行侧的输出是一个可复现的输入文件,而不是一段文字说明。 ## 先用小规模试运行,再在后台启动完整运行 把这条流水线当作一个实时仪表盘来运营,而不是一个发出去就不管的批处理任务。 - 先带着用户交互式地走一遍侦察过程:展示已发现的重点区域,让他们在任何任务启动之前先调整划分方式。 - 针对一个新目标的首次运行,先启动一小批(几个并行运行、较低的轮次上限),让用户在扩大规模之前先感受一下token消耗情况和提示词校准效果。如果发现异常,就一起检查对话记录。 - 然后在后台启动更大规模的运行,这样你就可以持续跟踪日志、观察发现结果的累积,并且在不阻塞的情况下回答问题。每当一个经过验证的结果出炉,就用一段简短的摘要将它呈现出来,而不是等整批任务都跑完。 第一个经过验证的发现通常在几分钟内就会出现,而不是要等几个小时;一个跑得慢的落后任务只会拖慢它自己,不会拖慢整批任务。 ## 把每份对话记录实时写入磁盘,运行中断也不丢失 为每一次运行配备两层常开的可观测性机制。 - 每隔若干轮次打印一次心跳,用来证明进程在长时间沉默期间依然存活。 - 每个动作对应一行进度信息,显示每个智能体正在做什么,每次工具调用或文本块对应一行。 每个智能体的对话记录,在消息到达时就以流的方式写入磁盘,并持久化刷盘。任何重要内容都不会只缓存在内存中,因此即便运行中途被强制终止,事后仍然能查看完整、可读的对话记录。 当用户询问状态时,依据磁盘上的产物来回答:统计仍在运行的发现任务数、已评分的数量,以及已经写出的报告数,然后展示最新的一条。每个结果都是在自己那次运行一结束就立刻写出的,因此落后的任务永远不会阻塞其他结果的落地。 ## 遇到速率限制后让智能体从中断处恢复 瞬时的容量错误绝不能让一次运行就此夭折;要搭建一套恢复阶梯,让长时间任务能够扛过突发流量。 - 每个智能体对应一个长期存活的会话。运行途中出现的速率限制或服务器错误,会先在智能体自身的客户端内部进行重试。 - 如果重试放弃了,编排器就会进行退避(指数退避,并设有上限),然后从该会话恢复并重新启动这个智能体,使完整的对话上下文得以还原,并从失败的那一轮准确地继续下去。 - 给每个智能体的恢复次数设一个上限,这样一个真正卡死的智能体最终还是会停下来。 告诉用户,他们可以在接近所配置容量的水平上运行,让退避机制去吸收突发峰值;不需要为了避免丢失成果而自我限流。有一个例外:轮次耗尽错误是终止性的,而且是有意不做恢复的,因为恢复会使轮次上限成倍增加——遇到这种情况应该提高上限后重新运行,而不是恢复。智能体在触及上限之前已经提交的任何发现,仍然会被保留并评分,不会随着这次运行一起被丢弃。 ## 新漏洞自动生成报告,访问外部网络前先询问 在流式模式下,报告生成是自动进行的。每当一个崩溃通过评分,一个裁判智能体就会判定它是一个新漏洞、是某个已知漏洞的一个更干净的代表案例,还是应当跳过的重复项;一旦判定为新漏洞,就会立即触发一个报告智能体,无需等待整批任务完成。此外还保留了一条独立的批量报告生成路径,用于故障恢复,或用于处理未经流式模式产生的结果。 每一份报告都是一份结构化的可利用性分析——包括该原语的行为方式、是否能从真实攻击面到达、提权路径,以及各项约束条件——并附有智能体判定的严重程度评级。另有一个独立的评分智能体,依据语义层面的评分准则而非关键词扫描来给报告打分。 在启用任何会访问外部网络的步骤之前——例如一个用于克隆目标上游代码仓库、以判断某个漏洞是否已经修复的新颖性检查——都要先征求用户的意见。默认应保持关闭:处于物理隔离或限制出站流量环境中的用户,不会希望流水线对外发起访问。只有编排器所在的主机才会触碰网络;无论如何,智能体容器始终被限制在只能访问模型端点。 ## 确认崩溃已消失,是否采用补丁交给人决定 打补丁阶段既可以在报告生成之后运行,也可以独立运行。针对每一个独特的崩溃,一个位于全新沙箱容器中的补丁智能体会编写修复方案并生成一份diff;另一个独立的评分容器则会走一遍验证阶梯。 - 应用这份diff并重新构建。 - 确认原先那个可复现的输入不再导致崩溃。 - 确认目标程序自身的测试套件依然能够通过。 - 用一个全新的、限时运行的发现智能体,对打过补丁的二进制文件重新发起攻击。 在某一级验证失败时,相关证据会被反馈回去,补丁智能体会在有限的次数内进行迭代;还可以选择性地加入一道咨询性质的评审,作为最后一级。 要向用户明确说明这个流程到底证明了什么。这套阶梯验证的是崩溃已经消失,而不是这份diff可以安全地提交到上游。把diff呈现出来供人工审核,并指向相应的审核指引。不要主动提出把这份diff应用到流水线自身容器之外的任何地方——生成出来的修复方案只是供人采纳的提案,不是可以自动落地的变更。 ## 让智能体按根本原因而非文字判断重复崩溃 崩溃的去重依靠智能体在两个层面上的判断,而不是靠字符串匹配。 - 在提交时,发现智能体必须附上自己的推理依据,说明这个崩溃与共享发现文件中已记录的内容有何不同。流水线会拒绝任何遗漏这一推理的提交。之所以由智能体来做这个判断,是因为它了解根因;流水线只负责确保这一判断确实发生过。比对时要基于原始的sanitizer摘录做语义层面的比较,而不是逐字匹配。 - 在报告关口,裁判智能体会将每一个已评分的崩溃与当前的报告清单对照阅读,判定为新漏洞、更干净的重复项,或应跳过。同一个根因即便出现在不同的代码行或调用帧上,依然会被判定为重复;一个更干净的重复项会触发重新生成报告,随后由一个比较步骤挑选出最终的标准版本。 记录一个已知漏洞时,要以函数名作为键,而不是行号:同一个漏洞可能会在相邻的行上崩溃,或者根据输入的不同,报出不同类型的sanitizer错误。 ## 发现与评分在各自受限的容器中运行 正是这套隔离模型,让经执行验证的结果值得信赖;要把它当作不可妥协的底线。 - 发现与评分运行在由同一镜像构建出的不同容器中。两者之间只有概念验证(PoC)字节会跨界传递。发现侧永远不会触碰评分侧,这就挫败了通过预先埋设状态来进行奖励作弊的可能性。 - 每个智能体都运行在自己独立的容器内,使用加固过的运行时,出站流量被限制在一份配置好的允许列表之内——这一切都发生在沙箱内,而不是在主机上。它的文件和shell工具都被限制在该容器之内。 - 用于生成智能体的命令,除非显式传入一个危险的覆盖参数,否则拒绝在沙箱之外启动。 - 智能体可用的工具集是固定且最小化的:执行类智能体只拥有读、写和shell这三种工具;裁判类和比较类智能体则完全没有任何工具,所有事情都在一次带提示词的调用中完成。没有插件工具,也没有网络访问权限。 ## 避开会导致启动失败的设置,新增目标无需改代码 有几个运营层面的细节很容易被破坏,值得提前说明。 - 有几项环境设置是承重的:一项用来关闭容器内工具的嵌套会话防护,另一项让它能够在沙箱内接受一种绕过权限检查的模式。去掉其中任何一项,都会导致智能体启动失败。 - 要区分"限制可用工具集"与"权限允许列表"这两者——某个命令行工具可能同时接受这两个参数,但它们的含义并不相同;要使用那个真正能缩小工具存在范围的参数,而不只是缩小允许使用范围的那个。 - 模型的选择是一个运行时参数,而不是静态配置,因此同一份目标定义可以由任意模型来驱动。 - 一个经过sanitizer插桩的解析器,可能需要加上一个禁止内联的属性,以免编译器的内联优化改变崩溃特征签名。 添加一个新目标,只需要放入一个包含构建定义和sanitizer配置的目录即可,不需要改动流水线代码本身。要用单元测试覆盖各个活动部件——标签与输出解析、产物序列化、特征签名提取、去重逻辑,以及打补丁-评分阶梯——并保留一个运行速度快的固定测试目标,作为端到端的冒烟测试路径。 ## 在看不到答案的容器中,从日志里追查攻击者的踪迹 有一个针对"入侵之后"场景的姊妹版本,把问题反过来了:攻击者已经出现在日志中,任务是找出他们的整个攻击活动,而不是让某个二进制文件崩溃。 - 日志语料库必须在任何流程运行之前就已生成完毕。它体量庞大,并且相对于给定的种子是确定性的,因此同一个种子在同一台机器上会复现出同样的证据。 - 一个狩猎智能体会获得应用程序源码和只读的日志,并提交它的事件调查发现。从设计上讲,它的容器内部不存在任何标准答案。 - 一个位于全新容器中的评分智能体会为提交内容打分,并独立地重新触发每一个已确认的概念验证。只有提交内容本身会跨越这道边界。 要守住评估的完整性:标准答案文件、评分器,以及日志生成器的源码,都是会泄题的"剧透"。绝不要在狩猎侧挂载或读取它们。与崩溃发现流水线相同的"先交互、后自主"模式,在这里同样适用。