用户让助手生成一份分析报告。助手弹出“是否继续”,得到确认后,覆盖了同名文件,还调用了一个外部服务。
用户确认过这次操作吗?从按钮点击记录看,确认过;从他看到的信息看,却未必知道自己同意了什么。
这个问题可以从一个很小的工具做起:只允许在指定项目内生成一份报告。先把这条流程做清楚,再讨论更长的 Agent 任务链。

图里的确认、权限检查和执行前复核承担不同职责,任何一项都不能替代其他项。
以生成报告为例,确认界面至少要说清四件事:读取什么输入,写入什么目标,是否覆盖已有内容,是否向外部服务发送数据。
以下是一份简化的示例计划,不是可直接用于生产的完整协议:
{
"plan_id": "example-plan-17",
"revision": 3,
"action": "create_report",
"input_id": "sample-set-A",
"output_id": "report-A",
"overwrite": false,
"external_transfer": false
}这里使用逻辑标识,不让模型任意指定系统路径。执行层应将标识解析为允许访问的资源,再检查当前用户是否有对应权限。
界面上的说明也应从这份计划生成。若让模型另写一段“我会生成报告”的解释,却不给用户看真实参数,说明和动作就可能分离。
用户确认了第 3 版计划。等待执行时,助手发现文件已存在,于是把 overwrite 改成 true。这不是小修正,它改变了操作后果。
执行服务需要关联“谁确认了哪一份不可变的计划内容”。修改目标、覆盖方式或外发范围后,旧确认不能继续使用。版本号由受信任的服务管理;仅让模型在请求里自报一个旧版本号,不构成有效校验。
确认记录还需要约束可用次数和有效范围。它不能变成其他任务、其他用户或以后某次执行的通行证。
确认时目标文件不存在,不代表执行时也不存在。另一个进程可能在等待期间创建它。
因此,“先查不存在,再普通写入”并不能落实禁止覆盖的承诺。实际写入动作也要采用能拒绝覆盖或检测条件变化的机制,而不是只靠之前的布尔检查。遇到冲突就停止并说明原因,不能悄悄换个有覆盖权限的工具继续。
同样的思路适用于输入:如果报告依赖某个明确版本的数据,执行前要核对实际读取的是否仍是那个版本。只绑定计划文字、不约束它引用的资源状态,仍会留下歧义。
预演可以显示将读取的输入和将创建的报告,但“预演”必须是工具实现的行为。让模型口头承诺不写文件,并不能证明它没有调用有副作用的接口。
真正执行后,也不能只看工具返回“成功”。需要核对目标报告是否产生、格式是否符合约定,以及该结果对应哪次输入和计划。记录这些关联即可,不要默认把完整输入、凭证或全部工具输出都写入日志。
可以用下面几种情况检查实现:
刻意制造的变化 | 应观察到的结果 |
|---|---|
确认后把禁止覆盖改为允许覆盖 | 原确认失效,重新确认 |
等待期间出现同名目标 | 写入层拒绝覆盖 |
用另一用户的确认记录调用工具 | 拒绝执行 |
同一确认重复提交 | 按预先定义的单次授权规则处理 |
工具返回成功,但没有有效产物 | 不报告任务完成 |
OWASP 的 Agent 安全指南将最小权限、工具调用控制和高影响操作的人工参与列为重要措施。一个做得更清楚的确认框,只补上其中一环,不等于整套系统已经安全。
参考:OWASP AI Agent Security Cheat Sheet。
作者:超维方程技术团队。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。