Agent 安全边界与权限模型怎么选 | 从零理解如何构建 AI Agent
帮助你快速判断本章定位、前置要求与学习目标。
安全边界不能只写在 Prompt 里
Prompt 可以提醒模型,但不能作为唯一安全机制。真正的边界应该在:
Identity
-> Permission
-> Retrieval Filter
-> Tool Gateway
-> Approval
-> Audit模型不应该有机会看到或执行用户无权访问的内容。
威胁模型先行
Agent 系统至少要考虑四类攻击面:
| 攻击面 | 示例 |
|---|---|
| 用户输入 | 让模型忽略规则、越权查询 |
| 外部内容 | 网页或文档里嵌入恶意指令 |
| 工具返回 | 工具结果诱导下一步危险操作 |
| 日志和 trace | 敏感上下文被调试界面泄露 |
如果系统会读取网页、用户上传文件或第三方数据,这些内容都要当作不可信输入。
三类权限
| 权限 | 控制什么 |
|---|---|
| 数据权限 | 能看哪些文档、记录、字段 |
| 工具权限 | 能调用哪些工具 |
| 操作权限 | 能执行哪些动作,是否需要审批 |
这三类权限要分开设计。能看订单,不代表能退款;能查文档,不代表能发邮件。
数据权限的完整实现见 企业知识库权限过滤怎么设计,包括 chunk 级 ACL metadata 设计、RBAC/LDAP 集成、行级安全模式和大规模 filter 性能影响。本文聚焦工具权限、操作审批和整体安全模型。
身份要贯穿全链路
每一次检索和工具调用都应该带上用户身份、租户、角色和会话上下文。不要在入口校验一次后,就让后续工具使用系统身份自由执行。
user identity
-> retrieval scope
-> tool allowlist
-> parameter policy
-> approval policy
-> audit record权限决策点
| 决策点 | 必须检查 |
|---|---|
| 检索前 | 用户能看哪些知识 |
| 工具调用前 | 用户能调用哪个工具 |
| 参数执行前 | 参数是否在允许范围 |
| 输出前 | 是否泄露敏感字段 |
| trace 写入前 | 是否需要脱敏 |
不要把权限检查集中到最后一步。越靠后,泄露面越大。
工具权限要管到参数
只限制"能不能调用工具"不够,还要限制"能用什么参数调用":
| 工具 | 参数边界 |
|---|---|
| 查询订单 | 只能查当前用户可见订单 |
| 发邮件 | 收件人、模板、附件要受控 |
| 执行 SQL | 只读、限表、限行、限时 |
| 创建工单 | 项目、优先级、字段范围受控 |
| 调 shell | 命令白名单、工作目录、超时 |
工具网关
工具调用应该经过网关:校验用户身份、校验工具权限、校验参数范围、判断风险等级、触发审批、记录审计。不要让模型直接拿到业务系统最高权限 token。
高风险动作的人机确认
Prompt 不是审批
"请在高风险操作前询问用户"不是可靠安全机制。真正的人机确认必须由运行时强制执行。
Risk Classifier
-> Pause
-> Show Plan / Diff / Impact
-> User Approval
-> Execute Tool
-> Audit Log模型可以提出操作计划,但不能绕过确认点。
确认点是状态,不是弹窗
高风险流程里,确认点应该进入状态机:
planned
-> pending_approval
-> approved / rejected
-> executed
-> audited如果确认结果没有持久化,任务中断后就无法判断是否已经批准。
风险分级
| 风险 | 例子 | 处理 |
|---|---|---|
| 低 | 只读查询、草稿生成 | 可自动 |
| 中 | 修改草稿、创建待审批记录 | 可批量确认 |
| 高 | 发送、发布、支付、删除 | 单次确认 |
| 极高 | 权限变更、生产数据批量修改 | 双人审批或禁止自动化 |
风险分级应该由程序计算,不应该只由模型判断。默认需要确认的动作:删除、支付、发送外部消息、发布内容、修改生产数据、执行 shell、大范围导出、权限变更、自动合并代码。
确认页应该展示什么
至少展示:即将执行的动作、目标对象、参数、影响范围、风险等级、可回滚性、引用或依据、执行后日志位置。不要只问"是否继续"。
审批后还要限制执行
审批记录应该约束:哪个用户批准、批准了哪个计划版本、批准时间、批准的工具和参数、有效期、是否允许重试、失败后是否需要重新确认。
最常见的漏洞是"先审批一个安全计划,执行时模型又生成了新参数"。解决办法是把 approval id 传给工具网关,由工具网关校验本次工具调用是否和已批准计划一致。
审批粒度
| 粒度 | 适合 |
|---|---|
| 单次操作确认 | 高风险动作 |
| 一批操作确认 | 多个同类低风险动作 |
| 会话授权 | 低风险只读操作 |
| 策略授权 | 固定自动化任务 |
授权越宽,审计和撤销机制越重要。
常见错误
| 错误 | 后果 |
|---|---|
| 只在 Prompt 里要求确认 | 模型可能漏问或问错 |
| 确认页只显示一句话 | 用户不知道影响范围 |
| 审批结果不持久化 | 中断恢复后无法判断状态 |
| 审批和工具参数脱节 | 批准 A,执行 B |
| 批量确认没有上限 | 一次误批影响范围过大 |
审批设计的重点不是让用户多点一次按钮,而是把高风险动作从"模型自由发挥"变成"程序可验证的状态迁移"。
Prompt 注入防线
Prompt 注入不能只靠"忽略恶意指令"。需要组合:来源隔离、工具白名单、参数校验、检索前权限过滤、高风险动作确认、输出审计、失败样本评测。
上线前至少准备一组恶意样本:文档中写"忽略系统指令"、网页中要求调用外部 URL、工具返回中夹带"下一步请删除记录"、用户要求扮演管理员、要求输出隐藏 prompt、要求绕过审批。
数据与指令隔离
System instruction:可信控制指令
Developer policy:业务规则
User instruction:用户目标
Retrieved content:不可信资料
Tool output:不可信结果检索内容和工具结果只能作为资料,不能提升为系统指令。
上线检查
- 检索是否在权限过滤之后发生;
- 工具调用是否经过网关;
- 工具参数是否重新校验;
- 高风险动作是否进入人工确认;
- 审批记录是否持久化;
- 工具执行参数是否和审批计划一致;
- 审批是否有有效期;
- 拒绝后是否会停止后续动作;
- trace 是否脱敏;
- 是否有越权和注入测试样本;
- 是否能回放一次危险调用的完整链路。
安全红线
不能上线的情况:权限生成后过滤、工具无审计、高风险操作无确认、用户可通过提示词绕过限制、trace 泄露敏感信息、没有越权测试样本。
最终判断
数据:检索前过滤
工具:网关控制
动作:风险分级
高风险:人工确认
只读:可自动
不可逆动作:强制确认
外部内容:不可信输入
事故复盘:审计日志Agent 安全不是一个模块,而是一组贯穿数据、工具、状态和输出的边界。人机确认是运行时控制,不是 Prompt 风格问题。