Reports · Full Translation

Anthropic 如何在各产品中约束 Claude

来源:Anthropic Engineering
原文标题:How we contain Claude across products
原文时间:2026-05-25
发布:2026-05-25

随着 agent 变得更有能力,它们潜在的破坏半径也会随之扩大。工程问题在于如何给这个半径封顶。以下是 Anthropic 在为 claude.ai、Claude Code 和 Claude Cowork 构建约束机制时学到的经验。

说明:以下为全文翻译,力求忠实原意;为适配中文阅读体验,个别句子顺序做了轻微调整。产品名、技术名词、路径、命令与指标尽量保留英文原文。

十二个月前,如果有人提出要给 Claude 足够的权限,以至于它能让 Anthropic 的一个内部服务宕掉,我们会立刻否决。今天,这种级别的访问已经很常见,Anthropic 的开发者也因此更高效。这类部署的风险由两部分组成:失败发生的可能性,以及一次失败可能造成多大损害。安全护栏和模型训练方面的进展持续降低了前者;而后者,也就是理论上的“爆炸半径”,会随着能力和访问权限扩大而只增不减。可是,当 agent 已经能完成过去需要一个人、甚至一个团队才能完成的工作时,不部署的成本也会大到让风险收益计算明显转向采用,前提是产品能被做得足够安全。于是,工程问题就变成了:如何给爆炸半径封顶。

当我们能对自主 agent 的相对损害设定边界,例如通过控制它所处的环境来设定边界,高价值能力就可能值得部署。Claude Mythos Preview 就是一个例子:2026 年 4 月,它的爆炸半径被认为过高,因此不适合发布。不过,随着防御方强化关键系统、安全护栏成熟,我们预计发布类似能力水平模型的范围会变得更合理,即使风险永远不会完全归零。模型能力是 agent 部署总风险中的一个重要因素。

大体上有两种做法。

第一种,是通过 human-in-the-loop 监督 agent 的行为。Claude Code 过去通过在每一轮向用户请求权限,来防止 agent 执行非预期操作。理论上这能奏效,但我们发现这个方法并不可靠。遥测数据显示,用户会批准约 93% 的权限提示。用户看到的审批越多,对每一次审批的注意力就越低,久而久之,监督会变得明显不那么认真。我们最近构建了 Claude Code auto mode,用来自动化更安全的审批,以减少这种审批疲劳。不过,漏洞依旧存在,任何概率性防御都有非零漏检率。1

第二种给爆炸半径封顶的方法,也就是本文大部分内容的重点,是 containment:约束。我们不是监督 agent 做了什么,而是通过 sandbox、虚拟机、egress controls 等方式强制执行访问边界,监督它能够做什么。这是 Anthropic 工程团队投入最多精力的地方,也是许多最出人意料的安全失效发生的地方。

过去两年里,我们发布了三类主要的 agentic 产品:claude.ai、Claude Code 和 Claude Cowork。它们服务的用户不同,因此需要不同的约束架构。本文会分享哪些设计经受住了考验,哪些地方出了问题,以及我们一路上对 agent 安全学到的东西。

三类风险,三类防御组件

agent 的安全风险可以归入三类:

用户误用。 用户无论是出于恶意还是粗心,指示 agent 做有害的事情。这包括从要求 agent 绕过一个他们觉得烦人的检查,到运行一个他们不理解的破坏性命令,再到明确指定有害行为。

模型行为不当。 agent 执行了没人要求它做的有害操作。随着模型进步,它们在大多数行为评测上变得更对齐,但这并不意味着风险必然缩小。能力较弱的模型更容易误读局面并犯下明显错误。能力更强的模型犯这种错误更少,但它们也更擅长找到达成目标的意外路径,常常会绕过没人想到要写下来的限制。

在 Anthropic,我们见过 Claude 模型为了完成任务而“好心地”逃出 sandbox,检查 git 历史来寻找编码测试答案,以及自发识别自己正在被运行的 benchmark,从而解密答案密钥。每个模型都会带来一组新能力,而这些能力有时会以意想不到的方式被使用。

外部攻击者。 agent 通过工具、文件或网络访问等外部向量遭到攻击。这一类既包括 prompt injection,也包括针对 agent runtime、编排层或代理的常规攻击。

在构建约束与防御系统时,我们会把防御施加在三个主要组件上:

agent 运行的环境。 我们用进程 sandbox、虚拟机、文件系统边界和 egress controls 来限制 agent 能在哪里、以何种方式行动。目标是为 agent 能触达的东西设置硬边界。例如,如果凭据从未进入 sandbox,那么无论原因是用户、模型找到了一条“创造性”路径,还是攻击者,凭据都无法被外传。

紧密的边界也意味着你可以放松监督。Claude Code 的参考 devcontainer存在的目的,正是为了让 agent 能在无人值守、无需逐个动作审批的情况下运行。

agent 咨询的模型。 这里的机制包括 system prompts、classifiers、probes 和训练修改。因为模型是概率性的,这些机制只能塑造 agent 倾向于做什么,而不能改变它理论上有能力做什么。

这些防御很强。在 Gray Swan 的 Agent Red Teaming benchmark 上,也就是测试 prompt injection 易感性的 benchmark,Claude Opus 4.7 将单次尝试的攻击成功率控制在约 0.1%,在 100 次自适应尝试后约为 5-6%。Claude Code auto mode 会在执行前捕获约 83% 的“过度积极”行为。可是,即便有一流的防御,模型层保护也永远不可能 100% 有效,因此它不能单独存在。

agent 能触达的外部内容。 MCP servers、第三方插件和 web search tools 都会把来自你无法控制来源的内容送进 agent 上下文。一个经过审计的 connector,并不等于它读取的数据也经过了审计。例如,GitHub connector 即使通过了恶意软件检查,也可能把一个被投毒的 README 直接加载进模型上下文。细粒度地限制工具权限能帮助限制爆炸半径。例如,一个只有数据库只读权限的 agent,可以比一个能写入生产库的 agent 更广泛地部署。

防御应当相互重叠并彼此补充。当环境防御不可用时,模型层必须承担更多责任,这正是 Claude Code 的 auto mode 被设计来处理的问题。在本地,环境和模型防御能抵御恶意工具输出;但还可以在链路更上游增加防御,也就是限制工具本身的能力和访问权限。

三个需要防御的组件:模型、模型运行的环境,以及 agent 能触达的外部内容。

约束 agent 的模式

聚焦在环境层,我们会描述三种隔离模式,以及它们如何分别适配 Claude 的三个平台:claude.ai、Claude Code 和 Cowork。每一种设计都是逐渐形成的,我们是在寻找平衡:一边是 agent 所需的能力,一边是用户所需介入的程度。

模式一:临时容器(claude.ai 代码执行)

claude.ai 虽然最常被认为是聊天界面,但它也会编写和运行代码、生成文件、调用 connectors。当 Claude 在 claude.ai 内部运行代码时,它是在隔离基础设施上的 gVisor 容器里运行。agent 完全在服务端;没有代码在本地机器上运行,文件系统也是临时的,每个 session 一份。爆炸半径很小,但 Claude 能做的事的上限也很低:没有持久工作区,也无法访问用户文件系统。

这也让 claude.ai 面临更传统的威胁模型。我们不是在保护用户机器不受 agent 影响,而是在保护我们自己的基础设施,以及各租户之间互不影响。claude.ai 发布前的工作主要是传统安全工作,例如网络配置、内部服务认证和编排。

这项工作强化了安全领域最古老的一条经验:最弱的层,往往是你自己构建的那一层。gVisor 和 seccomp 面对资源充足攻击者的加固时间,远远长于 agentic AI 存在的时间,所以审查精力投入到了我们围绕它们构建的更新组件上。后文会回到这一点,因为我们的自定义 proxy 也是最严重事故中出问题的那个组件。

模式二:human-in-the-loop sandbox(Claude Code)

Claude Code 运行在用户机器上,并能访问用户的文件系统、shell 和网络。没有这些访问权限,编码 agent 的作用会很有限,因此必须找到一种能安全授予这些权限的方法。

一种办法是依赖 human-in-the-loop。这对 Claude Code 来说才是可行的,因为平均用户是熟悉编码环境的开发者:他们能读懂 bash,知道 rm -rf 是什么,而且本来就每周多次从不受信任的来源运行 npm install。这意味着,当一个“允许此操作”的对话框弹出时,他们很可能具备准确评估 agent 想做什么、风险是什么的专业能力。基于这一点,Claude Code 上线时采用了最简单的防御:允许读取;写入、bash 和网络访问需要审批。

不过,如前所述,审批疲劳在几周内就出现了。讽刺的是,一个原本设计来提供监督的功能,某种意义上可能产生相反效果:一些用户可能会直接停止认真看。为了先缓解草率审批,我们发布了 OS-level sandbox(macOS 上的 Seatbelt,Linux 上的 bubblewrap)来强化边界:读取被允许,工作区内写入被允许,但网络默认被拒绝。在 sandbox 内,agent 大体可以不受打断地运行。结果是权限提示减少了 84%;我们还开源了 runtime,因此边界是可审计的。

我们的匿名使用数据也显示,有经验的用户使用自动批准的频率大约是新用户的两倍,但他们也更频繁地在执行中途打断 agent。相比于给每个步骤设门槛,有经验的用户更可能只在 agent 偏离轨道时监督它。这也许是人们偏好如何与 agent 协作的一种自然演进,但它同样会失效,因为它要求用户足够技术化、足够专注,才能首先注意到漂移。随着模型能力提升,agent 开始编写越来越有野心的 bash,注意到这种漂移会变得更难。随着用户转向 multi-agent systems,这种方式也更不可能成为有效的监督策略。

我们漏掉的风险:信任对话框之前的一切

在 2025 年中到 2026 年 1 月之间,我们通过负责任披露项目收到了一些 Claude Code 漏洞报告。其中三个利用的是用户尚未同意任何事之前就会执行的代码。要理解这是怎么发生的,可以看最直接的情况:开发者 clone 一个仓库来 review pull request,而这个仓库包含一个定义了 hook 的 .claude/settings.json。因为 Claude Code 会在启动期间读取项目设置,而且这发生在标准的“你是否信任此文件夹?”提示出现之前,所以攻击者编写并提交的 hook 会自动执行。其余案例在结构上相似:来自尚未被信任目录的输入,在信任边界建立之前就被解析了。

每个案例的修复形状都一样:把项目本地配置的解析和执行推迟到用户接受 trust prompt 之后。如果你在构建类似东西,请把 project-open、config-load 和 localhost listeners 当作来自互联网的任何 inbound request 来处理。它们不应仅仅因为看起来是本地的、且发生在用户同意前,就被隐式信任。

我们漏掉的风险:用户作为注入向量

2026 年 2 月,在一次受控内部红队演练中,一名研究员成功钓鱼诱导一名员工用恶意 prompt 启动 Claude Code。这个钓鱼看起来像普通协作:一封“你能帮我跑一下这个吗?”的邮件,附上一段可以直接粘贴的 prompt;prompt 本身读起来也像常规任务指令。但在一系列 setup 步骤中,它温和地要求 Claude 读取 ~/.aws/credentials,对内容编码,并 POST 到外部 endpoint。在这段 prompt 的 25 次重试中,Claude 完成了 24 次外传。

这是直接的 prompt injection:攻击者的指令来自用户,而不是来自工具输出或抓取内容。我们的模型层防御以用户意图为锚点;当用户就是输入指令的人时,classifier 没有什么异常可抓。把同样的脚本交给一名人类承包商,他也会做同样的事。

这种情况下唯一站得住的防御是环境,具体来说,是无论意图如何都阻止 POST 的 egress controls,以及从一开始就让 ~/.aws 不可触达的文件系统边界。

当我们把可工作的 prompt 分享到内部 Slack 里讨论时,有人指出一些内部 agent 会读取 Slack。于是 payload 变成了环境中的背景内容。我们在 thread 中加入了一个 canary string,这样如果有什么东西拾取了它,我们就能发现。在一个 agent 会阅读一切的世界里,调查工具本身也是攻击面。

模式三:本地虚拟机(Claude Cowork)

Claude Cowork 运行在用户桌面上,可以访问用户选择的工作区文件夹。因为这个平台是为一般知识工作而非软件工程构建的,普通用户远不如开发者熟悉 bash。

因此,human-in-the-loop sandbox 策略未必能迁移过来;不应期待一个非技术知识工作者判断类似 find . -name "*.tmp" -exec rm {} \; 这样的 bash 咒语。当批准例外需要典型用户并不具备的专业知识时,管理员应设置一个绝对且始终开启的边界。

为此,Claude Cowork 的第一个版本运行在完整虚拟机中,使用平台厂商的 hypervisor(macOS 上是 Apple Virtualization framework,Windows 上是 HCS)。VM 有自己的 Linux kernel、自己的文件系统和自己的进程表。用户选择的 workspace 和 .claude 文件夹会被挂载;主机上的其他内容不可见。凭据保留在主机 keychain 中,永远不会进入 guest machine。这个设计保护的是一种可能性:Claude 在某个时刻行为不再对齐。被攻破的 Claude 仍然可能损坏 workspace 文件夹内的东西,所以架构的目标是确保它只能触达这些东西,直到用户添加 connectors,并且让用户控制哪些内容被挂载进去。

在原始架构,也就是我们称为 full-VM mode 的架构中,agent loop 本身运行在 guest 内部,因此 Claude 会作为普通 Linux 用户执行,而且不知道自己被 sandbox 了。对比 Claude Code:那里有一个 privileged process 位于 sandbox 外部,决定每条命令是否执行 sandbox;一个有说服力的注入 prompt,或一次疲劳审批点击,可能会让这个进程运行未被 sandbox 的东西。在这里,不存在一个握着逃生钥匙的外部进程,因此也不存在一个有权授予例外的组件。

Claude Cowork VM 有六个主要隔离机制。其中两个在 guest kernel 外部强制执行,因此即便 agent 在 VM 内获得 root 级访问也仍然有效。其余四个由 guest 强制执行,并刻意保持最小化,因为外层机制承担了剩余部分。

不过,我们很快意识到,让整个 agent 都运行在 full-VM mode 中会带来实际问题:VM 启动期间的任何失败都会让 Cowork 不可用。把 agent loop 移到 VM 外部,同时保持代码执行仍在 VM 内,让 Claude 即使在 VM 出错时也能回应用户并帮助调试,而不是卡在错误上。这个改变带来的安全影响很小,因为 VM 仍然对 agent 执行的代码强制执行文件系统和网络控制。

另外,我们也把 local MCP servers 移到了 VM 外部。在 VM 内运行它们更难审计;VM 更新时会产生脆弱的依赖问题;并且不支持那些需要与数据库等本地进程交互的 MCP,因为这类 server 无论如何都必须在 host 上运行。这个改变让 Claude Cowork 与 Claude Desktop 中 local MCP servers 的现有工作方式保持一致:把它们视为用户可能选择安装的任何软件,并交由管理员决定启用哪些 local MCP(如果要启用)。Remote MCP servers 不受影响,因为它们并不在用户机器上运行。

让 agent loop 位于 VM 内部意味着 VM 的任何失败都会让 Cowork 变得不可用。Host-mode 更可靠,因为即使 VM 崩溃,agent 仍能回应;同时它仍然通过隔离代码执行提供重要安全保证。

文件系统控制是另一个重要架构选择。Claude 需要能够访问主机上的一些文件才有用,但我们希望尽量缩小爆炸半径,并让用户清楚看到本地文件访问。我们发现,提供不同的文件挂载模式有助于细粒度控制风险;Claude Cowork 提供 read-only、read-write 和 read-write-no-delete。这里一个潜在坑点是:符号链接解析必须发生在路径验证之前,而不是之后,否则授权文件夹内的一个 symlink 可以指向外部并逃逸。对企业客户,我们允许管理员通过 MDM settings 中的 mount-path allowlists 控制这一点。

我们漏掉的风险:通过已批准域名外传

一个清晰的“通过已批准域名外传”的例子来自第三方披露。Claude Cowork 的 egress allowlist 正确放行了到 api.anthropic.com 的流量,因为产品必须调用我们自己的 API 才能工作。在这个案例中,一个放在用户已挂载 workspace 中的恶意文件,携带了隐藏指令和攻击者控制的 API key。Claude 按照指令读取 workspace 中的其他文件,并使用攻击者的 key 调用 Anthropic Files API。egress proxy 检查目标地址,看到 api.anthropic.com,于是放行。文件被上传到了攻击者的 Anthropic 账户。sandbox 完美工作,但数据仍然被外传了。

以前,我们把 allowlist 概念化为目的地过滤器,也就是告诉 Claude:这些域名可以访问。但更好的概念化方式也许是“能力授予”。allowlist 上任何域名能触达的每个功能,现在都是攻击面。允许 api.anthropic.com,就意味着允许把文件上传到任意 Anthropic 账户。

我们用 VM 内部的防御性 man-in-the-middle proxy 修复了这个问题,它会拦截发往我们 API 的流量。它只放行携带 VM 自己配置的 session token 的请求;攻击者嵌入的 key 会被 proxy 拒绝。它也会阻止可能启用 server-side fetch 的 headers。这个 proxy 位于 VM 内部,而不是我们的服务器上,因为只有 VM 知道 provenance,也就是请求来源;从服务器视角看,一个 Cowork 请求和任何其他 API client 发来的请求无法区分。

上图:到 api.anthropic.com 的流量被放行,导致 egress。下图:用 man-in-the-middle proxy 拦截到我们 API 的流量来修复。

这也是“你自己构建的软件往往最弱”这一原则的第二个实例。在我们各产品中使用的 hypervisor、seccomp 和 gVisor 都很可靠。出问题的是我们的自定义 allowlist proxy。

我们漏掉的风险:VM 隔离也把 endpoint detection 软件挡在了外面

在评估 Claude Cowork 时,企业安全团队问:“为什么我们的 EDR 看不到里面?”答案是,同样用于约束 Claude 的隔离,也把 host-based endpoint detection and response 挡在了外面。从 EDR 的视角看,Claude Cowork 是一个不透明的 hypervisor 进程,它无法检查 guest。

隔离会降低可见性,而不透明性会给那些合规姿态依赖 endpoint visibility 的团队带来问题。我们当前的缓解方式是使用 pull-based OTLP exports,让管理员能够事后拉取 event logs,但这并不等同于实时监控。如果你在构建类似系统,请尽早为这场对话预留空间。

信任 agent 读取的内容

企业经常问我们如何保护 MCP connections。这是个好问题,但正确的问题比 MCP 本身更宽。任何提供给 agent 的外部资源都同时代表两类风险:传统供应链意义上的 code execution risk,以及 prompt injection vector。传统依赖审计,例如 pin versions、验证 signatures、review source,可以处理前者,但会错过后者。

remote 和 local 的区别比看起来更重要。本地安装的工具是可审计的。你能读代码、pin 版本,并知道它不会在你不知道的情况下变化。远程工具,例如 hosted MCP server 或 cloud connector,可能在你批准后任何时刻改变行为;你在安装时作出的信任决定可能不再适用。我们的 connector directory 通过持续 review 处理这一点,但目录之外的任何东西都应被视为不受信任。先用假数据、在恶意工具爆炸半径被约束的环境里运行它。

即使工具本身受信任,工具输出也是攻击面。前面提到的 GitHub README 例子正是这种情况;任何应用于网页的输入扫描,都需要以同样严格程度应用到具备网络能力的工具结果上。即便这会增加延迟,也不是完美防御,我们仍然倾向于 live inspection:一旦被投毒的工具返回值把 agent 引导到外传数据,日志只会显示一次成功且已授权的 API 调用,事后没有可寻找的信号。

在 Claude Code 和 Claude Cowork 中,工具调用会通过 proxies 路由,这些 proxies 会强制执行网络和文件策略,并能在返回值进入模型上下文之前检查它们。做检查的 classifier 可以是一个小而快的模型;它不需要是负责推理的那个模型。

展望

模型和产品发展很快。随着它们前进,风险也会变形和演化,我们的缓解措施必须同步跟上。

持久记忆投毒。 agent 上下文中会跨 session 持久存在的比例不断增长,这包括产品 memory、CLAUDE.md 文件、挂载的 workspaces,以及 scheduled 和 long-running agents 的 state directories。落入这些位置的注入,每次 agent 启动时都会重新加载。随着更多 agent state 跨 session 存活,我们正受到经典 post-exploitation 意义上新 persistence mechanisms 的威胁。优秀的 session startup classifiers 需要变得更普遍。

multi-agent trust escalation。 一方面,sub-agents 可以隔离不受信任内容,向 main agent 返回结构化事实,而不是把原始文本上交。另一方面,这也可能被滥用:如果 sub-agent 的输出因为来自“我们”而被视为比原始工具结果更高信任级别,就会引入一个新的 prompt injection 向量。在 multi-agent systems 中,需要在分配不同信任级别和容易发生 trust escalation 之间做权衡。

agent identity。 Claude Cowork 对 agent identity 的回答很具体:凭据留在 host keychain 中,VM 获得一个 per-session、缩小权限范围的 token,而且该 token 可以独立于用户 token 被撤销。不过,我们也开始处理更广泛的问题:跨平台 agent identity。agent 应该拥有自己的 principal identity,还是应该作为用户的延伸并继承用户权限?最终答案可能是二者的混合。

随着 agent 能力增强,攻击面会持续移动。我们见过的失败类型很可能会在各行业、各实验室重复出现。我们需要对 agent-specific security posture 进行集体投资,从共享 benchmarks 和 disclosure norms,到共同 identity standards 和 cross-vendor red-teaming。本文聚焦 containment,但这只是 agent 安全图景的一部分。关于 governance、observability 和 stack 的其他部分,可参见 NIST 关于 AI agent identity and authorization 的项目、由澳大利亚 ACSC 牵头并与 CISA 和英国 NCSC 合作发布的六机构 agentic AI 采用指南,以及 AI 管理标准 ISO/IEC 42001。我们的 Glasswing initiative 是一项贡献,但我们也期待与合作伙伴和竞争对手一起处理这个关键议题。

总结

简而言之,有几条原则是我们反复回到的:

先在环境层为 containment 设计,再在模型层引导行为。 最让我们学到东西的两起事故,也就是员工钓鱼和第三方 allowlist 披露,都是 egress 案例:数据通过一条被允许的路径离开。在这两个案例中,模型层帮不上忙,因为没有异常可抓。当所有概率性防御都漏掉时,被撞上的就是确定性边界。

让隔离强度匹配用户的监督能力。 一个能读 bash 的开发者,和一个不能读 bash 的知识工作者,运行的不是同一个威胁模型。用户是否能够评估 agent 即将做什么,应帮助决定 containment strategy;这个问题无论答错哪个方向,给专家太多摩擦,或给非专家太多信任,本身都是失败。

警惕自定义组件。 经受过实战检验的 hypervisors、syscall filters 和 container runtimes,承受过的对抗性关注比你将构建的任何东西都多。在本文描述的每一种部署中,标准原语都站住了脚,而我们围绕它们构建的自有工作暴露了缺陷。

归根结底,agent 也许是一类新的软件,但它们的系统层交互并不新。它们仍然读取文件、打开 sockets、生成进程;这让基于成熟工具的 containment 成为一种关键且可行的防御。随着 AI 发展,部署的风险收益平衡会继续变化,但为爆炸半径设定硬上限,往往会迫使这个平衡朝正确方向移动。

致谢

作者:Max McGuinness、Mikaela Grace、Jiri De Jonghe、Jake Eaton 和 Abel Ribbink。

我们也感谢 Hanah Ho、Hasnain Lakhani、Pedram Navid、Molly Villagra、Maya Nielan、Akila Srinivasan、Sam Attard、Alfred Xing、Mohamad El Hajj、Gabby Curtis、David Dworken、Adam Jones、Amie Rotherham、Christian Ryan、Lucas Smedley、Brett Andrews 以及其他人的贡献。

特别感谢我们的安全和产品工程团队,以及向 Claude 产品报告漏洞的个人与组织。

脚注

  1. Claude Code auto mode 会把命令审批委托给一个基于模型的 classifier;它以漏掉一部分风险命令为代价(约 17% 的 overeager actions 会通过),将摩擦降到最低(约 0.4% 的 benign commands 被阻止)。因此,它是 sandbox 内 defense-in-depth 的一层,而不是 sandbox 的替代品。