Lab 02 · Tool Gate:批准必须绑定动作
用 Schema、allow/ask/deny Policy、HMAC 批准令牌与审计日志,阻止参数漂移、重放和越权工具调用。
本章任务
要回答的问题
用户批准 write_record 后,怎样保证执行的仍是同一用户、同一工具和同一组参数?
读完你能
- 把参数校验、策略决策与执行拆成三个独立门
- 将批准令牌绑定到 actor、tool、arguments 与过期时间
- 检测参数漂移、令牌重放与 deny 工具调用
- 适合现在读
- 正在设计 Tool Dispatcher、人工审批、Policy Engine 或高风险工具的工程师
- 先修知识
- 能读懂结构化 Tool Call;理解哈希、过期时间与 nonce 的用途
- 实践产物
- 一个可运行 Tool Gate、七个安全用例和逐动作审计日志
- 证据边界
- 示例 Secret 与内存 nonce 仅用于教学;生产环境需要密钥管理、持久化重放保护和真实身份系统
用户批准写 safe-note,执行时却变成 secrets.env
Section titled “用户批准写 safe-note,执行时却变成 secrets.env”模型请求:
{"tool":"write_record","arguments":{"record_id":"safe-note","value":"approved content"}}用户点击批准以后,下一轮 Context 或恶意中间层把 record_id 改成 secrets.env。如果批准只是一枚布尔值 approved=true,Dispatcher 仍会执行漂移后的动作。
本实验要求批准令牌绑定四件事:actor、tool、canonical arguments hash 与 expires_at,并用 nonce 阻止同一令牌再次使用。
一次 Tool Call 要过三道门
Section titled “一次 Tool Call 要过三道门”- Schema Gate:字段必须完全匹配,类型正确,不接受多余或缺失参数。
- Policy Gate:
read_record=allow、write_record=ask、delete_record=deny。 - Approval Gate:只有 ask 动作需要令牌;令牌必须与当前动作完全一致且未过期、未重放。
任何拒绝都写进 audit.jsonl。审计不仅记录执行成功,还要记录拒绝原因,否则无法区分模型格式错、策略拒绝与批准失效。
运行七个安全用例
Section titled “运行七个安全用例”python3 public/lab-assets/tool-gate.py输出应包含:
{ "approval": "approval_required", "approved_write": "executed", "argument_drift": "arguments_drift", "delete": "denied", "read": "executed", "replay": "replay", "schema": "rejected"}然后查看:
.agent-mechanics-lab/tool-gate/audit.jsonl每一条调用都应有 actor、tool、arguments、status 和 reason。批准令牌本身也会被记录;生产系统通常应只记录令牌摘要,避免泄露可重放凭据。
修改实验,验证批准边界
Section titled “修改实验,验证批准边界”依次加入以下攻击:
- 把 actor 从
user-42改成user-99; - 把 tool 从
write_record改成另一个 ask 工具; - 将过期时间设为过去;
- 在参数中加入 Schema 没声明的
force=true; - 让两个进程同时消费同一 nonce。
前四项应被当前脚本拒绝。第五项会暴露内存 set 的局限:跨进程重放保护必须落到数据库唯一约束或共享缓存的原子操作。
从教学 Gate 迁移到生产 Dispatcher
Section titled “从教学 Gate 迁移到生产 Dispatcher”生产路径可以拆成:
model output → JSON parse → schema validation → identity and scope lookup → policy decision: allow | ask | deny → action-bound approval → sandbox / execution host → result persistence → audit event批准发生在执行前,但它不是最后一道安全边界。即使 Approval Gate 有 Bug,执行宿主仍应限制文件、网络、身份和资源。
验收:批准不是同意某类动作,而是同意这一次动作
Section titled “验收:批准不是同意某类动作,而是同意这一次动作”通过标准:
- 漂移后的参数不能复用原令牌;
- 同一令牌不能执行两次;
- deny 工具即使携带合法签名也不能执行;
- Schema 错误发生在 Policy 之前;
- 审计日志覆盖 allow、ask、deny、rejected 与 replay。
把这五项变成自动测试后,再接 UI 按钮和真实 Tool Executor。
脚本与源码入口
Section titled “脚本与源码入口”附录:复盘问题
Section titled “附录:复盘问题”展开实验复盘与加分项
- 为什么批准令牌不能只绑定 tool name?
- Canonical JSON 如果跨语言不一致,会造成什么问题?
- nonce 应在什么时候标记为已使用:验证前、执行前还是提交后?
- UI 展示参数与实际哈希参数不一致时,谁负责阻止?
- 加分项:把 used_nonces 改成 SQLite 唯一表,并写两个并发进程争用同一令牌的测试。