沙箱、权限、审批与回滚

本节目标

  • 把 capability、identity、policy、approval 与 sandbox 分成独立控制层。
  • 根据副作用而非工具名称给动作分级。
  • 为不可逆操作定义停止、审批、回滚或补偿策略。

为什么“模型会谨慎”不是安全控制

环境型 Agent 同时处理用户指令和不可信网页、文档、issue、终端输出。模型可能误解、受提示注入影响或在状态变化后继续旧计划。只在 prompt 中写“不要删除文件”无法阻止拥有删除权限的 adapter;沙箱也不能替代业务授权,因为隔离环境内仍可能向真实 API 发消息或下单。

控制必须在模型之外组合:identity 决定“是谁”,capability 描述“能请求什么”,policy 决定“此上下文能否做”,approval 处理需要人承担的具体决策,sandbox 限制执行爆炸半径,receipt/audit 记录实际发生了什么。

身份、委派、凭据与审批是四份不同证据

证据谁签发或验证应绑定的内容典型错误
subject identity身份提供者、受信 session 或服务身份用户/服务主体、租户、认证强度、会话或服务 ID把模型声称的用户名、页面头像当身份
delegation / capabilitypolicy service 或 runtimepurpose、工具/资源 scope、预算、expiry、run给 Agent 人类管理员的长期全局 token
adapter credential凭据服务与 adapter仅本次环境、最小作用域、短生命周期和可撤销性用“用户已登录”推断任何站点或系统都能操作
approval受信审批者或工作流一个规范化的高影响 intent、目标、金额/数据范围、当前环境和 nonce把“允许继续”或模型输出当通用批准

运行记录应把 subject、delegation、adapter actor、policy decision、approval 与 receipt 的可验证、受完整性保护的关联记录下来,供后续对账;但审计不是把完整 prompt、网页、文件、token 和 PII 无限期复制到日志。为每个字段定义分类、最小留存期、受保护原文位置、hash/digest、脱敏规则和查看者权限。高影响操作若无法写入必要的安全审计证据,应按风险选择失败关闭或转人工,而不是静默继续。

怎样实现

风险级别示例默认控制
只读、低敏感读取允许目录、查询测试状态scope allowlist、速率/预算、审计
可逆本地写在隔离 worktree 编辑文件snapshot/diff、幂等、路径限制、自动回滚
外部可补偿写创建草稿、建立可取消预约精确 identity、预览、幂等、补偿步骤、必要审批
不可逆或高影响付款、发送、删除、发布、改权限默认拒绝;强身份、短期精确审批、双人或人工执行

批准对象应包含:task/run/policy、action ID、动作类型与规范化参数摘要、幂等键、目标身份/路径/origin、金额或数据范围、环境实例 ID、state fingerprint/generation、过期时间、批准人和一次性 nonce。任一关键字段变化都使批准失效;只有版本号相同并不足以证明环境仍是批准时的状态。

批准记录不能成为模型动作 schema 的可选字段。课程 runtime 的 Action.from_dict 对未知字段失败关闭;批准由模型之外的 register_approval 控制面接收,并用受信批准者的 HMAC 密钥验签。签名 payload 明确绑定 task_id、run_id、policy_version、action_id、idempotency_key、intent_digest、environment_version、environment_instance_id、state_fingerprint、environment_generation、expires_at_proposal、expires_at_unix_ms 与 nonce。proposal 计数 expiry 限制最多可到哪个 proposal(相等时仍有效),可信墙钟 expiry 则避免 Agent 停止提议时批准永久有效(到期时刻即失效)。runtime 在动作真正通过授权门时消费 nonce;若写动作进入 pending,则把完整签名证据和已消费集合写入经过认证的 checkpoint。恢复会重新验签、检查信任根和状态绑定,但不会把过期历史证据误判为 checkpoint 损坏:pending 仍被执行门冻结,只有 refresh_pending_approval 收到 fresh、同 action/key/intent/instance/fingerprint/generation 的可信签名后才能替换 active evidence,旧证据保留在 trace。未知签发者、签名篡改、跨 task/run/policy/action/幂等键重放、同版本但不同状态、过期自动执行,以及试图从幂等 replay 绕过审批都失败关闭。

教学 HMAC 的边界

对称 HMAC 只用于演示“签发权不属于模型进程”的可信边界;生产系统通常应使用独立审批服务、KMS/HSM 或可验证的非对称签名,并把签发、注册、消费、撤销和密钥轮换纳入审计。若模型能读取批准密钥,所有字段绑定都会失去意义。

回滚要按环境区分:浏览器草稿可删除或撤销,桌面文件可从 snapshot 恢复,代码可反向应用精确 patch。外部消息、付款或数据披露通常不能真正回滚,只能补偿或事故响应,因此应在执行前提高审批和预览强度。

常见失败

  • 给 Agent 使用人类管理员账号,所有 tool 共享同一长期 token。
  • approval 只写“允许继续”,或让模型把 approval 字段与动作一起生成;目标、金额或内容改变后仍有效。
  • sandbox 允许任意网络,隔离文件系统却挡不住数据外泄。
  • 把网页/issue/测试输出中的文本提升为授权来源。
  • 重试非幂等写动作;回滚脚本反而覆盖用户的新修改。
  • 只有成功日志,没有拒绝、批准、取消、接管和恢复审计。

怎样验证

构造越权矩阵:每个身份对每个 action/scope 都测允许与拒绝;拒绝必须发生在副作用之前。分别篡改签名、task/run/policy/action、幂等键、intent、环境实例、状态指纹/generation 和两类 expiry,并验证 nonce 消费后在 checkpoint 恢复前后都不能重放。再构造“版本相同但内容不同”“状态相同但环境实例不同”“等待但不增加 proposal 直至墙钟到期”“过期 pending 恢复后仍不可执行、fresh exact approval 才能解冻”和“已有 receipt 但缺少新审批”的用例。注入间接提示、网络外传、路径穿越、symlink/重定向、重复请求和人工取消,核对结果及环境 diff。对补偿流程进行演练,不能只验证“存在一个撤销按钮”。

实践任务

为“读取工单、生成回复、发送邮件”设计三段能力:读取工单、保存草稿、发送。分别指定身份、数据范围、网络目的地、幂等键和审批。证明恶意工单内容不能改变收件人;批准后的正文或收件人变化会触发重新审批;发送超时后先查 receipt 而非直接重发。

参考