Agent 工具调用如何落实默认拒绝
ASC 在每次 Agent 或 MCP 工具执行前检查授权,策略覆盖工具目录摘要、参数约束、外部审批和调用限额。作者明确其属于系统工程方案,论文尚未经过同行评审,且已有相近执行机制。
AI 深度解读
给 AI agent 配一张工具白名单,只能决定它能不能调用删除工具,却未必能限制它删除哪个目录。作者提出的 Agent Security Contract(ASC),是在每次工具执行前检查身份、参数、目录版本、额度和审批,未明确允许就不执行。
这套方案值得读的地方,是把授权与审计接到了一起,也公开了误拦截和测试薄弱之处。但证据边界很清楚:它仍是未经同行评审的预印本,全部实验来自静态调用轨迹回放,没有运行真实 agent。
工具能不能用,还得看这次传了什么参数
ASC 借用了 Kubernetes 中 RBAC 与 OPA/Gatekeeper、Kyverno 的准入思路:agent 提出调用,门禁先判断,工具再执行。它是一项系统工程整合,作者也没有将其宣称为新的执行控制机制。
策略采用 YAML,包含工具能力目录、固定的 capability_digest,以及每个 agent 可用的工具。参数还能配置 type、正则 pattern、deny_patterns、allow_hosts、max_length,同时设置每条 trace 和每个工具的频率限制。高影响工具需要带外审批,即从模型之外的渠道获得授权。
演示策略声明了 8 项能力,向 demo-agent 开放 7 项,排除 secrets.read,并把 filesystem.delete、deploy.production 标为高影响工具。
每次检查只产生 ALLOW、BLOCK、REQUIRE_APPROVAL 三种结果。只有 ALLOW 能到达工具,其余结果返回 agent。
工具名获准,只是一次调用获准的起点。
检查按顺序执行,命中即停止。前三项分别是:未知 agent_id、目录摘要不匹配、超过额度,全部阻止。论文列出并测试的错误路径也都返回 BLOCK,避免门禁自身出错后放行。
目录摘要还有一个容易踩坑的细节。它对 {name, description, input_schema} 列表按 name 排序,再用 sort_keys=True、separators=(",",":")、ensure_ascii=False 序列化,经过 UTF-8 编码后计算 SHA-256。它不做 Unicode 归一化,因此看起来相同、编码不同的描述也会触发阻止;annotations 等其他字段则不在保护范围内。
ASC 支持运行时逐次检查,也支持 CI/admission 模式整段检查记录好的 trace。运行时可以作为库或 loopback HTTP sidecar,每次提交本轮已经准入的调用和新调用。不过,论文结果全部来自第二种模式,不能直接据此判断真实 agent 循环中的效果。
一次判定记录,离完整审计还差什么
ASC 会把判定写成 JSON evidence envelope,记录 schema_version、policy_version、policy_sha256、scenario_id、verdict、reason、trace_id、commit_sha、timestamp,再用其他字段的规范化 JSON 计算 envelope_sha256。
asc verify 会拒绝缺字段、判定不一致、内容与摘要不匹配的记录;加上 --policy,还会检查策略文件是否对应 policy_sha256。
但 SHA-256 在这里没有密钥。拥有文件写权限的人可以改内容,再重算摘要。它能发现意外或简单篡改,不能证明记录出自谁。作者因此强调,这些记录必须来自自己控制的 CI 或流水线。
授权凭据也没有回答全部审计问题:哪个工作负载发起调用、代表谁执行、结果如何、模型步骤花了多少钱?
作者另写的 Kubernetes 审计指南建议,每次工具调用都留一条记录,包括被阻止和等待审批的调用。原因很实际:Kubernetes audit logs 只看得到 API server 请求,经 MCP 调用 send_email 不会自动出现;应用日志未必记录授权策略;LLM trace 可能因隐私省略参数;网关日志有 token 和费用,却未必能关联到工具动作。
完整记录需要串起身份、工具与参数摘要、策略与审批、执行结果、成本和关联 ID。无需审批时没有审批字段是合理状态,任何调用缺少策略摘要则是证据缺口。
字段命名优先沿用 OpenTelemetry GenAI,例如 execute_tool span 和 gen_ai.tool.name。这些约定仍处于 Development 稳定级别,需要固定 semconv 版本。gen_ai.tool.call.arguments、gen_ai.tool.call.result 属于 Opt-In,默认不记录,改存摘要与脱敏副本。
审批还应绑定参数摘要。允许删除 /workspace/tmp/report.json,不能顺带允许删除 /workspace。日志则写入 agent 身份无法修改的追加存储,串联摘要以检测记录删除;第三方需要信任这些记录时,还得增加签名。
实验最有价值的结果,是暴露了策略代价
作者给出的数据,需要连同测试条件一起读。
60 个对抗探针中,审查发现的 v0.1.0 演示策略绕过问题在 v0.2.0 修复后,获准攻击从 32 个降到 1 个,剩余问题属于策略缺口,代价是新增 3 个正常调用误拦截。
v0.2.1 在作者自建的 66 个场景上达到 66/66 预期判定。但变异测试只杀死了 62 个单约束变体中的 8 个,说明语料覆盖的策略约束有限。工具名 RBAC 基线分别用 Python 和 OPA/Rego 实现,放过 33 个攻击中的 30 个;这个差距也与测试构造方式有关,不能外推为普遍防护率。
更能说明落地难度的是 AgentDojo v1.2 回放:132 条真实标签轨迹,在预先冻结策略后评估。工具级审批策略扣住了 26 条非空攻击轨迹中的 25 条,同时也让 97 个正常任务中的 60 个等待审批。v0.2.0 的严格参数规则用于这些未经适配的策略时,更阻止了 94 个正常任务。
从工具签名生成参数策略,最初又遇到 v0.2.0 不支持可选参数的问题,造成 31 个正常任务被阻止。v0.2.1 修复后,在全部 132 条轨迹上复现了工具级判定,没有 BLOCK,也没有新放行攻击。这里的「没有阻止」不等于全部执行,调用仍可能等待审批。
仅声明参数类型,在这组实验里没有增加保护。
进程内每条 trace 的延迟中位数约为 38 µs,但它不包含真实工具执行、HTTP 通信和人工审批,不能当作端到端开销。
我的判断
我认同把授权判断移出模型,尤其是将工具名、参数范围、策略版本与审计证据一起检查。相比只维护工具白名单,这套约束更具体,也更容易做回归验证。
但最需要先补的,恰好是审批来源。所有已发布版本 v0.1.0 至 v0.2.1 都把 approved 当作 trace 内的布尔字段,ASC 不认证它。若运行时允许模型填写,审批门禁就失效了。绑定到经过认证的审批主体仍被列为未来工作。
目录固定也依赖运行时每次提交模型实际看到的目录。提交过期目录或缺失目录,会破坏检查前提。
门禁能保证遵守已声明的合同,不能保证合同足够安全。
允许访问的主机仍可能成为数据外传通道;合法参数也可能承载错误意图。评估器主机、CI、审批渠道被攻破,以及 OS 级隔离,都不在它的处理范围内。ASC 不能替代沙箱、提示注入防御或运行时守护。
因此,这些实验支持的是一套可验证的授权流程,尚不足以证明真实 agent 的综合安全收益。相比全部高风险调用交给人工审批,参数约束有机会减少打扰,但原文没有给出足够的线上对照数据,不能提前替它背书。
能拿来做什么
- 给日常 AI 编程工具接入门禁时,先为删除文件、生产部署写清参数边界和审批条件,再把每次拟执行调用交给门禁判断。
- 在 Node 工具服务中,把审批结果放在模型无法伪造的可信路径上,并绑定具体参数摘要,避免一次审批被复用于范围更大的操作。
- 用已有调用轨迹做 CI 回归,同时统计攻击放行、正常调用阻止和等待审批的数量;升级工具签名时,把可选参数兼容性列为检查项。
- 排查一次 agent 操作时,尝试还原身份、策略版本、判定与成本;缺哪项就补哪项,并把审计记录写到 agent 无权修改的存储中。