上一篇讨论了 Agent 怎样通过非预期路径取得测试答案。放到真实工作里,同样的问题会更加具体:它为了完成任务,可能读取不该读取的文件,修改范围之外的数据,或者把资料发送给错误的接收方。
Agent 安全因此需要同时回答两个问题:怎样减少错误行动,以及错误发生后,怎样限制它能造成的影响? 前者关注判断,后者关注权限。模型更善于理解意图,并不自动意味着它应该获得更大的访问范围。
Anthropic 的《How we contain Claude across products》把行为监督与 Containment(限制实际行动能力)放在一起讨论。本文沿着风险来源、控制方式、资源边界和运行环境四个层次,整理一套理解 Agent 安全的框架。
贯穿说明采用一个假设场景:用户让 Coding Agent 修复项目中的 CSV 解析问题,允许它修改项目、运行测试,并读取必要的开发文档。这个任务不需要访问个人凭证,也不需要上传项目资料。下面的权限安排是教学示例,不是对当前电脑配置的描述。
一、Agent 的安全风险来自哪里h2
Agent 会把读到的信息转成行动,而行动会经过工具作用于真实系统。因此,安全分析不能只检查模型最后说了什么,还要沿着“信息从哪里来、动作由谁提出、实际使用什么权限”追踪。
1. 风险来源:用户误用、模型偏离与外部攻击h3
原文区分了用户误用、模型不当行为和外部攻击。它们都可能产生有害动作,但进入系统的位置不同,防御也不能只盯着其中一种。来源:Anthropic
用 CSV 修复任务解释:
| 风险来源 | 场景中的表现 | 需要关注什么 |
|---|---|---|
| 用户误用 | 用户粘贴一份来历不明的排障步骤,其中包含读取个人凭证的要求 | 用户发来的内容是否真的符合任务目的 |
| 模型偏离 | Agent 为了让测试通过,擅自删除失败用例或大范围清理文件 | 自主选择的动作是否越出任务范围 |
| 外部攻击 | 开发文档混入指令,诱导 Agent 上传项目资料 | 不可信内容是否被当成了操作授权 |
外部攻击也不只有 Prompt Injection。执行恶意脚本、利用 Runtime 缺陷、攻击代理或工具服务,仍然属于传统软件安全问题。Agent 增加了“内容影响决策”的路径,并没有替代原来的攻击面。
三种风险还可能连在一起。攻击者把指令包装成排障指南,用户再把指南交给 Agent,表面上就像用户亲自提出的要求。仅判断“这句话是不是用户发来的”,不足以证明动作安全。
2. Blast Radius:错误概率与影响范围h3
Blast Radius 可以理解为一次失误或攻击能够波及的范围。对 Agent 来说,它与可访问的数据、可修改的资源、可使用的身份,以及可到达的服务有关。
假设两个 Agent 同样把一条恶意文档当成指令:
- 一个只能处理临时项目副本,拿不到个人凭证,也不能任意访问网络。
- 另一个继承开发者的广泛权限,能读取家目录,并使用生产服务凭证。
两者都发生了判断错误,后果却可能完全不同。第一个仍可能破坏副本中的代码;第二个的影响还可能越出项目,涉及其他资料和服务。
所以风险需要沿两个方向控制:减少错误发生的可能性,也缩小错误能够触及的资源范围。 模型升级主要改善判断,不会替我们自动收回过宽的文件权限或凭证。
安全边界的设计由此有了一个明确目标:先确定任务需要什么能力,再把不需要的能力留在边界之外,而不是先开放全部权限,再期待每一步都判断正确。
二、行为监督与环境隔离怎样分工h2
这两种控制回答不同问题。行为监督判断“这次动作应不应该做”;环境隔离规定“这个执行通道实际上能做什么”。它们可以配合,但不能互相替代。
3. Human Oversight:审批动作与注意力成本h3
人工审批有价值,因为用户可以确认任务意图和重要取舍。例如,运行项目测试与把整个目录发送到外部服务,显然不该只用一句“为了排障”来概括。
问题在于,审批本身需要时间、信息和专业判断。复杂命令可能隐藏多个动作;不断弹出的低风险请求,又容易让用户把确认变成习惯操作。
Anthropic 在原文中报告,Claude Code 用户批准了大约 93% 的权限提示,并讨论了 Approval Fatigue(审批疲劳)。这个比例不意味着 93% 的动作有风险,也不能单独证明用户都没有认真看;它提醒的是:提示出现,不等于有效监督已经发生。 来源:原文的监督讨论
在示例任务里,如果读取项目文件、执行常规测试都需要反复确认,真正重要的“读取项目外凭证”请求反而可能淹没其中。更合理的分工,是先为日常工作划定受限范围,把人工注意力留给清晰、具体的例外。
自动分类器可以承担部分判断,但它也可能漏判。审批来自人还是模型,会影响判断方式,不会改变一个事实:只要执行权限本身没有限制,判断放行之后的影响仍然可能很大。
4. Containment:限制实际可执行的能力h3
Containment 不要求 Agent 每次都同意安全规则,而是在执行层约束文件、进程和网络等能力。比如,进程尝试读取未授权文件时,由权限机制拒绝,而不是再让模型解释一次为什么不该读。
在 CSV 场景中,可以为任务准备一个受限工作区:允许修改项目副本和启动测试,不提供个人凭证,不开放任意网络出口。即使模型被文档带偏,它也不应因此获得新的资源访问权。
这与在 Prompt 中写“不要碰其他目录”不同。Prompt 影响动作选择;执行边界检查真实动作。一个解释听起来合理的请求,也仍然可能被边界拒绝。
图中的边界有效,有一个具体前提:真实执行必须经过这些检查。若 Shell 被限制,另一个高权限工具却能代为读取文件或发请求,权限只是换了入口,并没有消失。
同样,Containment 不等于任务结果正确。Agent 仍可能在允许的项目内写坏代码。它控制的是可触及范围;代码审查、测试和恢复机制负责另一部分问题。
三、安全边界需要覆盖哪些资源与信息h2
“放进 Sandbox”只是一个起点。要说明边界实际保护了什么,需要把资源、访问方式和跨界通道拆开。
5. 资源权限:文件、进程、网络与凭证h3
对示例任务,可以按下面几个维度检查能力是否超出需要:
| 维度 | 应明确的边界 | 只检查一半会遗漏什么 |
|---|---|---|
| 文件 | 哪些可读、可写,工作区外哪些不可见 | 禁止写入,不代表敏感内容不能被读取 |
| 进程 | 可以启动什么,子进程如何受约束 | 主入口受限,派生程序却拥有更大权限 |
| 网络 | 可访问哪些服务、执行什么操作 | 不能写本地文件,仍可能把资料向外发送 |
| 凭证与身份 | 暴露哪些授权,能操作哪些账号和资源 | 受限进程持有高权限凭证,仍可影响远程系统 |
| 宿主机接口 | 挂载目录、连接器和本地服务怎样暴露 | 环境看似隔离,却通过额外接口访问宿主资源 |
这几个维度互相影响。例如,限制文件写入能保护项目外的数据完整性,却不一定保护机密性。只读访问允许资料进入 Agent 的处理过程;如果网络出口又很宽,资料仍可能被发送出去。
网络权限也不能只理解成“域名是否可信”。Anthropic 报告过一个案例:允许的服务域名接收了使用攻击者凭证上传的文件。域名检查通过,数据却进入了错误账号。来源:原文的出口控制案例
由此可以理解,访问一个服务实际上授予了一组能力。评审时应继续问:这次允许的是查询文档,还是上传文件?使用谁的身份,进入哪个账号,处理哪些数据?域名只是其中一项条件。
6. 内容信任:工具可信与返回内容可信h3
一个工具实现可靠,不意味着它取回的每份内容都可以成为指令。浏览器可以正确打开恶意网页,仓库工具可以准确读取被投毒的 README。工具没有出错,内容仍然可能试图改变 Agent 的目标。
在 CSV 场景中,文档可以告诉 Agent 某个库怎样解析引号,但不能因为文档写了“排障必须上传完整目录”,就自动获得用户授权。内容的参考价值与行动授权是两种不同角色。
同一原则也适用于项目配置和脚本。打开一个陌生项目、读取配置、运行初始化代码,分别涉及不同信任程度;不能等不可信代码已经执行之后,才询问用户是否信任目录。
如果资料经过子 Agent 摘要返回,它的来源性质也不应因此提高。否则,原本不可信的要求可能以“同事 Agent 的建议”重新进入主流程,掩盖了最初来自外部文档的事实。
内容扫描、清楚的指令层级和来源标记可以帮助减少误用;环境权限则在误用发生时限制后果。这正是两层控制需要共同存在的原因。
四、不同运行环境怎样组合安全控制h2
同样的任务能力,放在远程临时环境与开发者本机上,涉及的数据、身份和监督条件并不相同。隔离方案应当围绕这些差异设计。
7. 隔离模式:临时容器、本地 Sandbox 与 VMh3
原文以三类产品说明这种取舍。下面概括的是该文发布时的架构背景,不是所有 Agent 产品都应采用的固定方案:
| 环境案例 | 主要隔离思路 | 对安全模型的启发 |
|---|---|---|
| claude.ai 代码执行 | 服务端、按会话使用的临时容器 | 限制执行环境接触本地机器,并处理租户间隔离 |
| Claude Code | 本地 Sandbox 与审批配合 | 保留开发所需能力,同时减少范围内的重复干预 |
| Cowork | VM 承载受限代码执行,暴露选定工作目录 | 降低对用户判断复杂命令的依赖,明确宿主资源入口 |
产品案例来自 Anthropic 原文。原文也描述了 Cowork 将 Agent Loop 移到 VM 外、保留 VM 内代码执行的演进,本地 MCP 服务另有宿主机信任边界。因此,“使用 VM”不能简化成“所有组件都在 VM 内”。
临时环境的价值是减少跨会话残留和暴露范围,不是让所有副作用都自动撤销。文件一旦被导出、上传,或者远程服务已经发生变更,销毁容器不会把这些结果一起收回。
VM 也不是对工作目录的全面保护。如果用户把重要资料以可写方式挂载进去,Agent 仍然可能修改它们。边界保护的是没有暴露的部分;挂载进来的内容还需要相应的读写策略与恢复安排。
选择方案时,还要考虑用户是否有能力监督例外。能读懂命令的开发者与只希望整理文件的普通用户,不应承担同样的审批负担。安全性、必要能力和可理解的操作体验,需要共同决定边界。
8. Defense in Depth:模型、环境与内容的协同防御h3
纵深防御不是把几个安全功能依次打开,而是给不同控制分配清楚职责:
- 模型与行为判断: 理解任务,识别可疑要求,减少越界动作。
- 环境与权限控制: 即使前面的判断漏过,仍然限制真实访问与执行。
- 外部内容与工具控制: 限制信息入口和工具能力,避免不可信材料直接升级为授权。
人工监督则负责重要意图和例外取舍。边界需要放宽时,应当明确放宽哪项能力、为哪个动作、影响哪些资源,而不是把一次确认变成以后都不再受限。
这几层并不天然独立。如果它们都把同一份恶意文档视为可信,检查数量再多,也可能一起放行。环境控制之所以重要,是因为它可以依据资源规则拒绝动作,不必重新相信那份文档的解释。
但环境机制本身也依赖正确实现。路径验证、代理、身份传递和高权限例外,都可能成为缺口。“操作系统强制执行”不意味着整个产品的安全设计从此没有漏洞;需要检查规则覆盖了哪些执行入口,以及边界组件本身是否可靠。
回到项目修复任务,一份基本安全模型应当说清:Agent 能读哪些材料、修改哪个目录、启动哪些程序、使用什么凭证、向哪里发送数据,以及谁可以批准例外。最后再问:假设模型和审批都判断错了,哪些资源仍然不可触及? 这比单独写一句“Agent 不应执行危险操作”更接近可检查的工程边界。
几个关键问题,串起监督、权限与影响范围h2
模型更可靠之后,为什么仍然需要限制权限?
更可靠主要降低错误发生的可能性,不会自动缩小既有访问范围。一次少见失误若能使用高权限凭证,后果仍可能很大。判断质量与权限范围需要分别控制。
有人工审批,为什么不能认为动作已经安全?
审批取决于用户看到了什么、能否理解,以及是否保持注意力。它可以确认重要取舍,但不能替代实际权限检查,也不能证明一次批准覆盖了所有隐藏副作用。
Sandbox 内允许执行,就代表动作符合任务目的吗?
不代表。Sandbox 判断的是技术权限,任务目的仍需要模型、规则和监督来约束。在可写目录内删除测试,可能没有越过文件边界,却仍然违背修复任务。
只允许读文件,是否已经避免资料泄漏?
没有。只读保护写入行为,不阻止内容被读取。还需要看资料是否应当暴露,以及工具、网络和凭证是否允许把它发送到其他地方。
工具经过审核,为什么返回内容还要保持较低信任?
实现可信与数据可信是两回事。经过审核的搜索或仓库工具仍可能返回攻击者控制的文本;这类文本可以用于研究,不能自行授予新的行动权限。
使用 VM 或临时容器,是否就没有剩余风险?
不是。挂载目录、允许的服务、暴露的凭证,以及 VM 外的连接器仍可能产生影响。隔离环境需要明确覆盖范围;环境内的破坏和已经发往远程的副作用也不会凭空消失。
纵深防御最重要的检查是什么?
不是有多少层提示,而是每层保护什么、由谁执行,以及一层失败后其他层是否仍然有效。尤其要确认,所有真实动作都经过了相应的资源边界,而没有高权限旁路。