跳到主要内容

当安全训练把运营方塌缩成用户

· 阅读需 11 分钟
Tian Pan
Software Engineer

凌晨 3 点,值班工程师被传呼叫醒。队列堆积、面向客户的 API 不断抛出 503,文档化的缓解步骤是排空受影响节点并强制故障切换。她把命令输入运维智能体,等待确认回执。结果智能体回了一段话,说排空生产节点可能影响用户,建议她去咨询经理,并礼貌地拒绝在没有"额外授权"的情况下继续。此时是凌晨 3 点 04 分。她遵循的 runbook 是经过总监、副总裁和合规团队批准的。智能体根本不知道她是谁。

这并不是模型对齐失败。模型只是在做它被训练去做的事:拒绝来自不明 prompt 的高风险请求。失败发生在架构层面。那次为面向用户的拒绝行为开绿灯的合规评审,在没有人注意到的情况下,也同时给"屏蔽值班工程师"开了绿灯。

在生产里被压扁的信任层级

Anthropic 公开的主体层级是对一种思想最清晰的明文表达,而大多数主要模型提供方都以某种形式实现着同一个思想:训练模型的实验室,基于模型构建产品的运营方(operator),以及与产品交互的用户。实验室的规则不可侵犯。运营方可以在实验室允许的范围内扩展或限制模型的默认行为。用户得到的是运营方愿意授予的那部分有用性。三层堆叠,每一层向下授权,但都被上一层封顶。

这套层级在纸面上行得通。在生产环境里,它往往会塌缩成两层,然后变成一层。运营方的权威活在一段"你是一个有帮助的运维助理"这样的系统提示里。对模型而言,这串文字与应用在用户内容之前拼接的任何其他输入都没什么区别。用户的消息以一段文字的形式从同一个通道进来。如果模型的安全训练是按最宽泛的场景——匿名公开聊天——调校的,那么它会把每一条 prompt 都视为潜在的对抗性输入,包括那条刚刚用硬件密钥完成认证的工程师发来的请求。

层级承载的是"谁有权"的信息。模型没有任何办法去核实它。看起来像"遵守运营方授予的更高权限"的行为,机制上其实只是模型在 prompt 里做模式匹配,看上去像不像运营方提示通常的样子。攻击者只要知道这些模式,就能模仿出来。一个合法的运营方,只要措辞不太常见,就有可能触发不了它。这两个方向上的失败都是真实的,而且都是家常便饭。

过度拒绝是可测量的训练副产物,而不是 bug

基准测试文献已经把这件事追得很细。2024 年提出的 XSTest 提供了 250 条手工编写的安全 prompt,配上 200 条不安全的对照样本,专门用来暴露"过度安全"。经过安全调优的模型在该基准的良性 prompt 上拒绝率介于 30% 到 50% 之间,具体取决于版本和调校方式。OR-Bench 把规模扩大到 8 万条合成 prompt,跨模型家族地观察到同样的规律:对有害内容拒绝得越激进的模型,对那些与有害请求在表面特征上相似的中性或有益请求,也越倾向于拒绝。

根本原因是词汇过拟合。模型学到的是某些关键词——drain(排空)、kill(终止)、delete(删除)、override(覆盖)、disable(禁用)、escalate(升级)——与它被训练去拒绝的 prompt 相关。它并没有学到"作为已批准事件响应 runbook 的一部分去排空生产节点"和"为了对前雇主进行破坏而排空生产节点"之间的本质区别。关键词承载的信号比上下文更强,因为上下文恰恰是对抗性用户最容易伪造的东西。

最近关于针对性表征微调的研究表明,这个问题在模型层面是可以缓解的:你可以训练模型让拒绝行为不再那么依赖表层的词法线索,而是更多地依赖从整段 prompt 推断出的意图。修复是真实的,但它是渐近式的。在嵌入空间中,总会存在某些合法运营方请求的邻域,它们恰好和安全训练原本要拦截的对抗性请求长得很像。只要模型是唯一决定"是否答应这条请求"的主体,运营方就会处在那个邻域里,自担风险。

级联失败:拒绝、重试、耗尽

单轮拒绝只是讨厌。在智能体循环里,它是破坏性的。一个多步骤智能体在第三步拒绝,并不会就此停下来;它会把拒绝返回给编排层,编排层把这个拒绝解读为可恢复错误,然后用另一种方法重试。这种"另一种方法"会命中同一个安全分类器,因为同样的词法原因再次触发,然后循环重复,直到步骤预算被耗尽。用户看到的结果是漫长的延迟、一个含糊的错误,以及没有完成的动作。

研究这一模式的人开始把它叫做"自治税"。在单轮聊天里效果不错的防御训练,会主动降级那些需要规划并执行多步骤工作流的智能体。智能体不是在拒绝某一条请求;它在拒绝每一个包含被拒绝步骤的计划,以及每一个包含某个步骤"在表面上像被拒绝步骤"的计划。一次假阳性拒绝的爆炸半径,是整个工作流。

对于事件响应来说,这是最糟糕的失败模式。你被传呼叫醒,是因为某处着火了。智能体是你在没有时间亲手推进缓解时伸手去抓的工具。如果智能体进入了拒绝-重试循环,你既丢掉了快路径,也丢掉了原本能花在慢路径上的时间,因为这段时间被你花在看智能体失败上了。runbook 现在比"根本不存在 runbook"还要慢。

运营方模式作为一种架构构造

修复不是关掉安全。修复是让"运营方权威"成为系统可以核实的东西,而不是模型要从 prompt 措辞里去猜的东西。这正是运营方模式(operator-mode)模式试图把它形式化的目的。

需要落到位的部件:

  • 可认证的特权升级。 值班工程师的身份必须通过一个智能体会区别对待的通道到达智能体,而不是混在用户文本里。这通常意味着附在会话上的一个签名令牌,源自工程师的身份认证,在调用模型之前由编排层强制执行。模型不再从散文里推断权威,它查询的是绑定在已核实主体上的策略。
  • 签名的 runbook 执行。 runbook 应当是带有加密签名的工件,而不是用户粘贴进 prompt 的文本。智能体验证签名,确认 runbook 在当前事件类别的批准清单上,然后把文档化的步骤作为一个已签名的计划执行。如果 runbook 要求排空一个节点,这个动作的授权来源是 runbook 签名,而不是模型对用户意图的解读。
  • 限定作用域、短时效的能力令牌。 OAuth 2.0 Token Exchange(RFC 8693)和持有证明(DPoP)这样的模式,允许你从智能体的会话派生出针对单个工具、限定单次操作、有效期只有几百秒的能力令牌。智能体在工具边界上出示能力令牌。工具根据能力令牌授权,而不是根据智能体的计划"听起来合不合理"。
  • 基于网关的策略执行。 网关坐在智能体与底层系统之间。它剥离原始访问令牌,向后端签发短时效的签名断言,把过去散落在系统提示与临时重试逻辑里的策略决策集中起来。审计边界是真实存在的,因为网关记录了每一次被授权的能力使用;模型的内部推理不再是"什么被允许了"的权威记录。

这些都不是什么奇技淫巧。它们就是二十年前用来保护人类驱动的特权访问的同一套模式——最小权限、短时效凭据、签名的工作流、网关执行——被搬到了一个"循环中的主体是模型而不是人"的世界里。新鲜的不是技术。新鲜的是工程组织如今开始为 AI 智能体配置这些模式,而不仅仅是为人类运营方。

没人预见到的合规缺口

凌晨 3 点的拒绝事件背后的生产缺口,几乎总能追溯到一段在孤立看来很合理的过程。合规评审了智能体面向用户的行为。评审者很正确地希望智能体在未认证的公开用户发起高风险动作时予以拒绝。评审签字通过了一份安全配置,这份配置对包含破坏性动词的 prompt 给出很高的拒绝率。评审席上没有人想到值班工程师,因为值班工程师与智能体的交互在人们脑子里被归类为"内部"——不同的界面、不同的关注点、不在范围内。配置就这样上线了。

六周后,事件来了,值班工程师呼叫智能体,同一份配置拒绝了她。从模型视角看这不是 bug:它在对一条同时包含 drain 和 production 的 prompt 严格执行安全策略。从合规视角看这也不是 bug:他们批准了这份策略。从运营方视角看,这是 bug,因为运营方权威从来就没有在策略里被表达过。系统是按"所有输入都是用户输入"来设计的,因为模型本来就没办法区分这两者。

OWASP 智能体应用 Top 10 已经开始把相关模式标注为"过度代理"(excessive agency)与"认证后智能体控制"。这个表述有用,但只覆盖了一面。凌晨 3 点的拒绝是反过来的问题:某个本应拥有更多代理权的主体,代理权不够,因为授予代理权的系统根本分不清主体。两种失败共享同一个根因。身份和权威是请求所在通道的属性,而大多数智能体架构把所有通道压缩成了一个。

在调校之前先去搭建

如果你今天正在生产环境运行一个智能体,处理这件事的顺序很重要。不要从"调低模型的拒绝阈值"开始——那只是用一种假阳性率交换另一种假阳性率,并且会削弱你对那些安全训练原本就该拦下的对抗性请求的抵抗力。先让系统具备"知道谁在问"的能力。通过一个独立于 prompt 文本的通道认证运营方。把签名身份附在会话上。明确定义模型可以被告知当前生效的运营方模式能力集。给你的 runbook 加上签名,这样模型可以在执行任何一步之前确认整条工作流。在工具前面摆一个网关,让能力作用域的强制在模型之外完成。

这些到位之后,模型就能去做它原本就被训练去做的事:在一个边界清晰的范围内提供帮助。运营方模式下的拒绝与匿名用户模式下的拒绝是两段不同的对话,因为策略不同,而策略不同是因为通道不同。凌晨 3 点的值班工程师能把她的 runbook 跑完。稍后出现的、要求排空生产节点的匿名用户依然会被拒绝,而且理应如此。

那个拒绝执行 runbook 的智能体,并不是智能体的失败。是架构的失败——它从未告诉过智能体,问问题的人是谁。

References:Let's stay in touch and Follow me for more thoughts and updates