跳转到主要内容

安全智能体如何跨过那行它“看不见”的注释,升级了被固定的依赖

阅读需 1 分钟Tian PanTian Pan

一位西班牙客户投诉称,她的年度续费被提前一天计费了。支持工单在经历了三个队列后,终于转到了一位工程师面前,他敏锐地察觉到了问题的端倪:这是一个日期格式化的回归(regression)问题,且仅出现在欧洲用户群中。他在 date-formatting 模块上运行了 git log,却一无所获。该模块已经 11 天没动过了。而 11 天前真正被改动的,是它的 package.json —— lodash 的版本从 4.17.20 升级到了 4.17.22。这次升级是由一个安全代理(security agent)发起的,由值班人员批准,并在没有任何评论的情况下合并了。

在同一个文件中,版本字符串上方两行有一条 18 个月前写的注释:// do not upgrade — breaks the snapshot tests in date-formatting, see FRONT-2418(请勿升级 —— 会破坏 date-formatting 中的快照测试,详见 FRONT-2418)。安全代理没有阅读它。或者更准确地说:安全代理阅读了整个文件,但它的提示词(prompt)指令是查找有漏洞的版本字符串,而不是衡量周围注释的权重。这条注释是承载关键信息的机构知识(institutional knowledge)。而代理却将其视为无关紧要的背景装饰。

这是一个两个互不知晓正在发生碰撞的系统之间的协同失效。安全代理履行了它的职责。写下注释的原工程师履行了他的职责。每次修改文件都遵守固定(pin)版本的开发代理也履行了它的职责。唯独没有人决定谁该负责在它们之间进行调解。

两个代理,一个仓库,没有协议

该团队的配置按照 2026 年的标准来看并无特别之处。安全策略代理按计划每晚运行,扫描依赖图中的已知 CVE,并提交 PR 以升级版本。功能开发代理每天早晨处理 Jira 工单,创建一个分支,并针对工单涉及的包提交 PR。两个代理读取同一个事实来源 —— 代码仓库 —— 并且都通过相同的拉取请求(PR)机制进行写入。

它们所不共享的是对彼此前置条件的任何认知。安全代理的提示词编码了一个单一目标:升级有漏洞的依赖。功能代理的提示词编码了另一个目标:实现工单功能。两个提示词都没有提到另一个代理。两个代理都没有读过另一个代理的提示词。每个代理的规划器(planner)在查看代码库时,都仿佛自己是唯一的编写者。

版本控制擅长检测两个编写者修改了同一行。它不擅长检测两个编写者出于互不兼容的原因修改了不同的行。安全代理和功能代理从未产生过合并冲突,因为它们很少在同一天针对同一个包提交 PR。碰撞发生在一个更缓慢的维度 —— 跨越数周,跨越多个 PR,针对那些两个代理都没有被训练去遵守的、存在于注释中的共享机构知识。

复盘后的架构认知是:在多代理操作下的代码库是一个多写系统(multi-writer system),其冲突解决取决于每个代理的提示词恰好编码了什么。这里没有共享锁,没有协商。哪个代理先运行,它就写入了其他代理所继承的状态。

注释不是文档,而是契约

在 18 个月前的原始 PR 中,查看固定 4.17.20 行的审阅者写下了那条注释,因为他花了四天时间在欧洲语言环境的快照测试中排查一个日期偏移一天的 bug。他将回归问题锁定在 lodash 的 _.isDate 与团队使用的区域感知日期解析器交互的具体变化上。他将版本降级到了 4.17.20,在注释中记录了原因,提交了工单 FRONT-2418,并发布了修复。这条注释是代码中唯一保存该知识的地方。工单是纯文本中唯一保存该知识的地方。两者通过一个安全代理提示词无法解析的字符串链接在一起。

这种模式很常见,但被低估了。固定版本旁边的注释不是关于代码的评注 —— 它们是解释代码为何如此而非彼样的契约(contract)。它们以压缩的形式编码了之前的事故。当一个代理(或人类)在不阅读注释的情况下升级固定版本时,它不只是丢失了上下文,它覆盖了团队在代理存在之前做出的决定。

安全代理的提示词本可以包含一条指令:阅读固定版本附近的注释,并将任何非空注释作为前置条件而非背景进行提级(escalate)。但它没有。团队在构建代理时假设固定版本要么是出于历史审慎(可以安全升级),要么是活跃风险(CVE),并没有“由于文档记录的原因而固定”这第三个类别。而在任何成熟的代码库中,这第三个类别是三者中规模最大的。

当能抓到 Bug 的测试被隔离时,CI 也救不了你

PR 通过了 CI。这是团队发现最难启齿的事故部分,因为它意味着他们以为拥有的安全网其实并不存在。

date-formatting 模块的快照测试在两个月前被隔离(quarantined)了。在一次 Node 版本升级后,这些测试开始间歇性失败,团队最终确定这是测试运行器中的时区处理变化。修复本需耗时一天。但当时正值季度中期,少了两位工程师,团队选择了阻力最小的路径:将测试套件标记为隔离,提交一个取消隔离的工单,然后继续。

当备选方案是让测试套件在每次合并时都像抛硬币一样不稳定时,隔离不稳定的测试套件是正确的做法。错误的做法是忘记了被隔离的套件是针对特定类别 bug 的回归检测器。从隔离标志开启的那一刻起,每个涉及 date-formatting 模块依赖的 PR 在其安全网中都有一个漏洞,而 CI 的绿色对勾让谁也看不见它。

会员专享

余下内容仅对会员开放。

会员可读完整内容 —— 每一个公开发布的观点背后,那些框架、决策与推理的全貌。

  • 完整文章,包含未公开存档的部分
  • 可落地的工作框架,附带权衡与决策依据
  • 新文章抢先看,先于公开发布

随时取消 · 一次订阅,畅读全部

参考资料

保持联系,关注我获取更多内容

阅读需 8 分钟

智能体凭据轮换:尚未被映射到 AI 领域的 DevOps 难题

自主 AI 智能体在工具集成中积累了大量长期存在的密钥,而传统的轮换策略往往会在任务执行中途导致其中断。四种架构模式——即时置备、双重刷新、工具与运行时隔离以及连接器抽象——能够确保智能体在凭据生命周期内安全运行。

insider
ai-agents
阅读需 12 分钟

当你的 CLI 开始说英语:可提示基础设施的最小权限原则

当你的 CLI 开始接受英语时,最小权限原则就失效了。每一个将意图转化为命令的封装层都变成了一个“混淆代理”。目前行之有效的模式包括:锚定已解析计划的意图绑定令牌、强制性模拟运行(dry-run)以及将提示词与动作图关联起来的审计追踪。

insider
security
阅读需 10 分钟

你的智能体在链式工具调用中获得的 OAuth 权限范围

OAuth 授权将智能体视为单用途应用,但每一次链式工具调用都扩张了审计日志必须解释的实际权限。那种一次性的授权界面将最坏的情况简化为了单一的决策。

insider
oauth
阅读需 10 分钟

当实习生在入职第一天部署 Agent

新员工入职走的是按工龄递增的权限曲线;而他们配置的 Agent 在第三天就拿到了生产级别的权限。安全评审、工具注册表与计费桶之间那条没有归属的缝隙,正在变成下一轮事故的温床。

ai-agents
iam
阅读需 9 分钟

智能体临时目录:无人盘点的无主文件系统 PII 暴露面

智能体工作线程在无人分类的磁盘上累积了临时文件系统状态——提取的 PDF、转录的音频、缓存的附件。解决方案在于为这一层级命名,而非追求架构上的复杂性。

insider
ai-agents