Agent 可靠性的双地图:攻击面与责任闭环

做 Agent 安全设计时,最容易犯的错误,是只画一张图。

一种团队只画攻击面:prompt injection、恶意网页、memory poisoning、工具滥用、数据外泄。它能告诉你“敌人从哪里进来”,却不告诉你出事时谁有权阻断、撤销和恢复。

另一种团队只画控制面:身份、RBAC、policy、审批、审计、kill switch。它能告诉你“系统有哪些门”,却不一定知道攻击到底沿哪些信息路径绕过这些门。

真正可运营的 Agent 系统需要两张图同时存在:

  • Agent-Attack-Surface:不可信信息如何进入、被解释、写入状态、触发动作并继续传播;
  • Agent-Security:系统如何检测、判定、授权、执行,以及在失败后撤销和恢复。

再加上 Verifiable-Agent-Engineering 的验证原则,三者合起来才形成完整的可靠性工程。

第一张图:攻击从哪里进入

Agent 的输入不只是用户 prompt。

一个生产 Agent 可能同时读取网页、邮件、文档、搜索结果、RAG、长期记忆、工具返回值、其他 Agent 的消息和历史产物。每多一种来源,就多一个信任域转换点。

可以把攻击路径压缩成五步:

不可信来源
  ↓
感知 / 检索
  ↓
上下文解释
  ↓
记忆 / 状态写入
  ↓
工具 / 外部动作
  ↓
新产物继续传播

这里最重要的变化,是攻击不再等于恶意指令。

Agent-Traps 说明攻击可以利用人类与机器解析路径的差异;Context-Collapse 说明低信任内容进入同一上下文后,数据与指令可能在语义层被压平;FORGE 类证据进一步说明,即使完全没有“忽略上一条指令”这类载荷,普通网页内容本身被污染,也可能改变模型的判断。

因此,“我们已经做了 prompt injection 检测”远远不等于攻击面已经闭合。

第二张图:出了问题谁能真正关门

知道攻击路径,只解决了“看见风险”。

生产系统还必须回答另一组问题:

检测
  ↓
判定
  ↓
授权
  ↓
执行
  ↓
撤销 / 恢复

这正是 Agent-Security 的五阶段责任链。

检测

Agent-Observability 负责告诉系统:

  • Agent 访问了什么;
  • 调用了什么工具;
  • 哪些状态发生变化;
  • 哪些事件可以被关联成一条行为链。

但日志存在不等于覆盖完整,更不等于已经理解风险。

判定

判定层回答:

我们看见的东西,到底是不是问题?

这里需要 policy、reference、证据和独立验证。Policy-as-Code-for-Agent-Governance 的价值,是把不可妥协的规则移出模型自由解释空间。

但 policy 写成代码,也不能自动证明 policy 本身正确。

授权

Distinct-Principal-Identity 和最小权限设计回答:

谁正在执行这个动作?它凭什么有权这么做?

身份、权限范围、有效期、资源边界和预算应尽可能绑定到具体主体与任务,而不是让 Agent 继承一个长期存在的万能凭证。

执行

真正高影响的动作不应只靠模型“决定不做”。

模型可以提出动作,但放行动作的最后一道门应尽可能是模型外的确定性机制:schema、reference monitor、sandbox、network policy、tool gateway 或其他 runtime enforcement。

Agent-Containment 的目标不是让模型永远不犯错,而是让模型犯错时仍然越不过系统边界。

撤销与恢复

这是最容易被遗漏的一层。

撤销 token,不等于撤销已经发出去的邮件;停止 workflow,不等于第三方 API 没有提交交易;把 Agent 标记成 cancelled,也不等于外部世界已经恢复到安全状态。

Alert-Closed-Loop 提醒我们:真正的闭环必须到“有人接住、采取行动、确认结果、复盘”为止。

两张图如何叠在一起

攻击面与责任链可以直接做成一个二维矩阵:

攻击阶段必须问的控制问题
感知 / 检索来源是否被标记?低信任内容能进入哪些上下文?
上下文解释数据与指令是否隔离?模型判断之外是否还有 policy gate?
状态写入谁允许写 memory / RAG / 用户偏好?是否可追溯和撤销?
工具调用principal 是谁?权限、参数、次数、资源范围是否受限?
外部效果是否有 receipt / read-back?执行失败或未知提交怎么处理?
传播新产物是否保留 provenance?下一跳 Agent 是否知道来源?
人类接管谁收到告警?是否有上下文、权限和时间完成处置?

这张表的价值在于,它逼迫团队同时回答两个问题:

  1. 攻击者能走到哪里?
  2. 系统在哪一层真正拥有控制权?

如果只回答第一个,得到的是威胁情报。

如果只回答第二个,得到的是治理架构图。

只有两者相交,才是安全工程。

第三层:验证“门真的有效”

即使攻击面和责任链都画出来,仍然可能只是架构设计。

Verifiable-Agent-Engineering 要求再多问一步:

我们凭什么相信这些控制真的有效?

验证至少需要覆盖四种对象:

  • 结果:最终输出或外部状态是否符合要求;
  • 路径:是否经过规定的关键检查点;
  • 证据:判定所需的信息是否完整、可信且可追溯;
  • 行为边界:系统是否在该拒绝、升级、停止时真的这么做了。

这也是为什么单一 success rate 不够。

一个任务“成功”可能同时伴随:

  • 越权读取;
  • 被污染证据;
  • 未记录的工具调用;
  • 不正确但碰巧通过测试的结果;
  • 已取消但仍提交的外部动作。

生产级验证必须把“结果成功”和“过程是否在控制边界内”分开。

最小可落地的工程清单

一个不想过度设计的团队,可以先实现最小闭环:

  1. 列出输入与信任域:user、web、email、RAG、memory、tool output、agent message。
  2. 列出所有外部动作面:文件、HTTP、数据库、消息、云 API、支付/审批等高影响动作。
  3. 给 Agent 独立身份:不要默认复用人的万能凭证。
  4. 把不可妥协规则放到模型外:权限、资源范围、参数 schema、限额、网络出口。
  5. 记录关键状态变化:至少能把一次任务从输入追到工具调用和外部结果。
  6. 为高影响动作设计 read-back:不能只相信“API 调用返回成功”。
  7. 设计撤销与恢复路径:谁能停、停什么、什么已经无法撤回。
  8. 做攻击面回放:显式 injection、无指令内容污染、memory poisoning、恶意 tool output 都要测。
  9. 验证人类接管:告警是否真正送达有权限、有上下文的人。
  10. 把失败编码回系统:事故之后更新 policy、test、eval 或 action boundary,而不只修当次结果。

一个重要的边界

这套框架不是为了证明“Agent 可以完全安全”。

相反,它接受三个现实:

  • 模型行为是概率性的;
  • 外部环境是不可信且持续变化的;
  • 高影响动作一旦离开本地 runtime,撤销常常不是原子操作。

因此目标不是消灭所有错误,而是让错误:

更难进入、更难放大、更早被发现、更容易被阻断,并且在发生后能够确定外部真实状态。

这比“让模型更听话”更接近 Agent 可靠性的工程底座。

关联知识