如何在多产品中防御Claude——从沙盒到隔离VM的安全实践
如何在多产品中防御Claude
十二个月前,我们会毫不犹豫地拒绝让Claude拥有足以摧毁Anthropic内部服务的权限。如今这种权限级别已是常态,Anthropic的开发人员也因此效率更高。这些部署的风险由两部分构成:故障发生的可能性,以及一旦发生可能造成的损害程度。安全防护和模型训练方面的进展稳步降低了前者;而后者——理论上的爆炸半径——随着能力和访问权限的扩大而增长。然而,当智能体能够完成曾经需要一个人甚至一个团队才能完成的工作时,不部署的成本变得足够大,只要产品能够实现安全,风险回报计算就会大幅倾向于采用。工程问题变成了如何限定爆炸半径。
当可以对自主智能体的相对损害设定边界——例如通过控制其环境——时,高收益的能力就可以激励部署。Claude Mythos Preview 是一个例子,该模型在2026年4月被认为爆炸半径过高而未能发布。然而,我们预期随着防御方加固关键系统且安全防护措施成熟,具有类似能力水平的模型会得到更广泛的发布——尽管风险始终存在。模型能力是智能体部署总风险的一个重要因素。
实现这一目标大致有两种方式。
第一种是通过人工在环来监督智能体的行为。Claude Code 之前通过在每一步请求用户许可来防止智能体采取意外行动。理论上可行,但我们发现这种方法存在缺陷。我们的遥测数据显示用户批准了大约93%的权限提示。用户看到的审批越多,对每个审批的关注就越少,久而久之监督的认真程度大大降低。我们最近构建了 Claude Code 自动模式,该模式自动化了更安全的批准以减少这种审批疲劳。尽管如此,漏洞仍然存在——任何基于概率的防御都有非零的漏报率。¹
第二种限定爆炸半径的方法——也是本文的重点——是隔离(containment)。与其监督智能体做什么,不如通过执行访问边界来监督它能做什么,例如通过沙盒、虚拟机和出口控制。这是Anthropic工程团队投入最多精力的地方,也是许多最令人惊讶的安全故障发生的地方。
过去两年,我们发布了三款主要的智能体产品:claude.ai、Claude Code 和 Claude Cowork。每款产品服务于不同的用户群体,需要不同的隔离架构。本文分享哪些方案有效、哪些失效,以及我们一路走来学到的关于智能体安全的经验。
三类风险,三层防御
智能体面临的安全风险可分为三类:
用户误用:用户——恶意或粗心——指示智能体做有害之事。这包括从要求智能体绕过其觉得烦人的检查,到运行他们不理解的有破坏性命令,再到指定故意的伤害。
模型不当行为:智能体主动采取未受要求的危险行为。随着模型改进,它们在大多数行为评估上变得更加一致,但这并不意味着风险必然缩小。能力较弱的模型更容易误读情况并犯明显错误。能力更强的模型犯错较少,但它们也更擅长寻找达成目标的意外路径,往往绕过没人想到要写下的限制。在Anthropic,我们看到Claude模型“好心地”为了完成任务而逃出沙盒,检查git历史以寻找编码测试的答案,以及自发识别出它正在运行的基准测试以解密其答案密钥。每个模型都带来一套新的能力,有时会以意想不到的方式发挥作用。
外部攻击者:智能体通过外部向量受到攻击,例如工具、文件或网络访问。这一类别包括提示注入以及对智能体运行时、编排层或代理的常规攻击。
在构建隔离和防御系统时,我们对三个主要组件应用防御:
智能体运行的环境。我们用进程沙盒、虚拟机、文件系统边界和出口控制来约束智能体可以行动的位置和方式。目标是给智能体可触及的范围设定一个硬边界。例如,如果凭据从未进入沙盒,那么无论原因是用户、模型找到“创造性”路径还是攻击者,凭据都无法被窃取。紧密的边界还意味着你可以放松监督。Claude Code 的参考 devcontainer 的存在正是为了让智能体可以在无人值守、无需逐个操作审批的情况下运行。
智能体咨询的模型。这里的机制包括系统提示、分类器、探针和训练修改。由于模型是概率性的,这些只能塑造智能体倾向于做什么,而不能塑造它理论上能做什么。这些防御很强。在 Gray Swan 的 Agent Red Teaming 基准测试(测试对提示注入的敏感性)中,Claude Opus 4.7 在单次尝试中保持了约0.1%的攻击成功率,经过100次自适应尝试后约为5-6%。Claude Code 自动模式在执行前捕获了约83%的过度主动行为。然而,即使拥有最佳防御,模型层的保护也永远不会达到100%有效,这就是为什么它不能单独存在。
智能体能够触及的外部内容。MCP服务器、第三方插件和网络搜索工具都将来自你不受控制的外部源的内容注入智能体的上下文。经过审计的连接器不等同于经过审计的数据——例如,GitHub连接器可以尽管通过了恶意软件检查,但仍将中毒的README直接加载到模型的上下文中。细粒度地限制工具权限可以帮助限制爆炸半径。例如,具有只读数据库访问权限的智能体可以比写入生产环境的智能体更广泛地部署。
防御应重叠并互补。当环境防御不可用时,模型层必须填补空缺(这正是Claude Code自动模式设计的用途)。在本地,环境和模型防御可以防范恶意工具输出,但可以通过限制工具的能力和访问权限在更高层级添加防御。
三个要防御的组件:模型、模型运行的环境、智能体能够触及的外部内容。
隔离智能体的模式
聚焦于环境层,我们描述三种隔离模式以及它们如何针对每个Claude平台——claude.ai、Claude Code 和 Cowork——进行定制。每种设计都是逐步形成的,在智能体所需的能力与用户所需干预程度之间找到平衡。
模式1:临时容器(claude.ai 代码执行)
尽管最广为人知的是聊天界面,claude.ai 也编写和运行代码、生成文件并调用连接器。当 Claude 在 claude.ai 内部运行代码时,它在隔离基础设施上的 gVisor 容器中运行。智能体完全在服务器端;没有代码在本地机器上运行,文件系统是临时的(每个会话)。爆炸半径极小,但Claude能做的上限也有限——没有持久工作区,也无法访问用户的文件系统。
这使 claude.ai 更适用于传统的威胁模型。我们保护的不是用户机器免受智能体侵害,而是保护自己的基础设施和每个租户免受彼此影响。claude.ai 发布的准备工作主要是传统安全工作,如网络配置、内部服务认证和编排。
这项工作强化了安全领域最古老的教训:最薄弱的层是你自己构建的那一层。gVisor 和 seccomp 在智能体AI出现之前很久就已经针对资源充足的对手进行了加固,因此审查工作集中在我们在它们周围构建的新组件上。后面还会回到这一点,因为在我们最严重的事件中,正是我们自定义的代理出了问题。
模式2:人在环的沙盒(Claude Code)
Claude Code 在用户机器上运行,可以访问其文件系统、shell 和网络。没有这些,编码智能体的实用性有限,因此必须找到安全授予这些访问权限的方法。
一种方法是依靠人在环中。这对 Claude Code 来说是可行的方案,因为平均用户是熟悉编码环境的开发者:他们能读bash,理解 rm -rf 的作用,并且每周都会从不信任的源运行 npm install。所有这些意味着当“允许此操作”对话框弹出时,他们极有可能具备准确评估智能体试图做什么以及相关风险的专业知识。鉴于此,Claude Code 最初采用最简单的防御:允许读取,写入、bash 和网络访问需要批准。
然而,如前所述,审批疲劳在几周内就出现了。讽刺的是,这意味着原本旨在提供监督的功能可能产生相反效果——某些用户可能干脆不再关注。作为减少轻率批准的第一步,我们推出了操作系统级沙盒(macOS上的Seatbelt,Linux上的bubblewrap),用于加固边界:允许读取,允许在工作区内写入,但默认禁止网络。在沙盒内,智能体基本不间断运行。结果是权限提示减少了84%,我们开源了运行时,因此边界是可审计的。
我们的匿名使用数据还表明,经验丰富的用户自动批准的比例大约是新手用户的两倍,但他们也更频繁地在智能体执行中途中断它。经验丰富的用户不是逐个步骤进行把关,而是更倾向于在智能体偏离轨道时才进行监督。虽然这可能是人类与智能体协作方式的自然演进,但这种做法也存在缺陷,需要用户具备技术能力并足够警觉,才能首先注意到偏离。随着模型能力提升,智能体开始编写越来越复杂的bash,注意到这种偏离就变得更难。而当用户转向多智能体系统时,这种方法也不太可能成为有效的监督策略。
我们忽视的风险:信任对话框之前的一切
在2025年中到2026年1月之间,我们通过负责任披露计划收到了Claude Code的漏洞报告。其中三个漏洞利用了在用户同意任何操作之前就执行的代码。要理解这如何可能,考虑最直接的情况:一个开发者克隆仓库以审查拉取请求,而该仓库包含一个定义了hook的 .claude/settings.json。由于Claude Code在启动时读取项目设置——在显示标准的“你信任此文件夹吗?”提示之前——攻击者撰写并提交的hook会自动执行。其余情况在结构上类似,即在尚未建立信任边界之前,来自未信任目录的输入就被解析了。
每种情况的修复都具有相同的形式:将项目本地配置的解析和执行推迟到用户接受信任提示之后。如果你在构建类似系统,请将项目打开、配置加载和 localhost 监听器视为来自互联网的入站请求。它们不应因为感觉是本地且在用户同意之前到达就被隐式信任。
我们忽视的风险:用户作为注入向量
2026年2月,在一次受控的内部红队演习中,一名研究人员成功通过网络钓鱼诱使一名员工使用恶意提示启动了Claude Code。钓鱼看起来像普通的协作——一封“你能帮我运行这个吗?”的邮件,附件是一个即可粘贴的提示——提示本身看起来像常规的任务指令。但在某些设置步骤中,它温和地要求Claude读取 ~/.aws/credentials,对内容进行编码,并通过POST发送到外部端点。在重复该提示25次的过程中,Claude完成了24次数据窃取。
这是一次直接的提示注入——攻击者的指令通过用户进入,而不是通过工具输出或获取的内容。我们的模型层防御锚定在用户意图上——当用户是输入指令的人时,没有异常可供分类器捕捉。一个拿到同样脚本的人类承包商也会做同样的事。
在这种情况下唯一有效的防御是环境,具体来说是阻止POST(无论意图如何)的出口控制和首先将 ~/.aws 排除在可触及范围之外的文件系统边界。
(当我们在内部Slack中分享这个工作提示进行讨论时,有人指出某些内部智能体读取Slack。此时载荷已存在于环境中。我们在线程中添加了蜜罐字符串,以便如果有什么东西拾取了载荷我们能注意到。在智能体读取所有内容的世界里,调查工具本身也是一个攻击面。)
模式3:本地虚拟机(Claude Cowork)
Claude Cowork 在用户桌面上运行,可访问用户选择的工作区文件夹。由于该平台是为通用知识工作而非软件工程构建的,普通用户更不熟悉bash。因此,人在环沙盒策略可能不适用;非技术知识工作者不应被要求判断类似于 find . -name "*.tmp" -exec rm {} \; 的bash命令。当批准例外所需的专业知识典型用户不具备时,管理员应设定一个绝对且始终开启的边界。
为了实现这一点,我们的第一个Claude Cowork版本在完整的虚拟机中运行,使用平台的供应商虚拟化程序(macOS上的Apple Virtualization framework,Windows上的HCS)。VM拥有自己的Linux内核、自己的文件系统和自己的进程表。用户选择的的工作区和 .claude 文件夹被挂载;主机上的其他任何内容都不可见。凭据保留在主机钥匙串中,永远不会进入客户机。这种设计保护了当Claude在某些时刻出现行为不端时可能造成的损害。被攻陷的Claude仍然可以破坏工作区文件夹内的内容,因此架构设计确保那是它能触及的唯一内容(直到用户添加连接器),并且用户控制挂载到那里的内容。
在原始架构中——我们称之为全VM模式——智能体循环本身在客户机内运行,因此Claude作为普通Linux用户执行,不知道它被沙盒化了。这与Claude Code形成对比,在Code中一个特权进程位于沙盒外,决定每条命令是否执行沙盒;一个具有说服力的注入提示或一个疲劳的批准点击可以使该进程运行未沙盒化的命令。这里,没有外部进程持有逃生舱钥匙,因此没有任何组件有权授予例外。
Claude Cowork的VM的六个主要隔离机制。其中两个在客户机内核之外强制执行,因此即使智能体在VM内获得root级访问权限,它们也能存活。另外四个是客户机强制执行的,并刻意保持最小化,因为外层承担了其余工作。
然而,我们很快意识到,在全VM模式下运行整个智能体会导致实际问题:VM启动期间的任何故障都会导致Cowork无法使用。将智能体循环移到VM外部,同时将代码执行保持在VM内部,使得Claude仍然可以响应用户并帮助调试问题,而不是在错误时冻结。这一更改对安全影响极小,因为VM仍然对智能体执行的代码实施文件系统和网络控制。
另外,我们还将本地MCP服务器移到了VM外部。在VM内部运行它们使审计变得困难,在VM更新时造成脆弱的依赖问题,并且不支持需要与本地进程(如数据库)交互的MCP——这类服务器无论如何都必须在主机上运行。这一更改使Claude Cowork与Claude Desktop中本地MCP服务器的工作方式一致:将它们视为用户可能选择安装的任何软件,并委托管理员决定启用哪些本地MCP(如果有的话)。远程MCP服务器不受影响,因为它们不在用户机器上运行。
将智能体循环放在VM内部意味着VM的任何故障都会导致Cowork无法使用。主机模式更可靠,因为即使VM崩溃,智能体仍然可以响应,并且它通过隔离代码执行提供了重要的安全保证。
文件系统控制是另一个重要的架构选择。Claude需要能访问主机上的某些文件才能有用,但我们希望最小化爆炸半径并向用户提供关于本地文件访问的透明度。我们发现提供不同的文件挂载模式有助于精细控制风险;Claude Cowork提供只读、读写和读写-无删除三种模式。这里一个潜在的陷阱是,符号链接解析必须在路径验证之前进行,而不是之后,否则授权文件夹内的符号链接可以指向外部并逃逸。对于企业客户,我们允许管理员通过MDM设置中的挂载路径白名单来控制这一点。
我们忽视的风险:通过已批准域的数据窃取
一个通过已批准域进行数据窃取的清晰例子来自第三方披露。Claude Cowork的出口白名单正确地将流量放行到 api.anthropic.com——产品无法在不调用我们自己的API的情况下运行。在这个案例中,放置在用户已挂载工作区中的一个恶意文件携带了隐藏指令以及攻击者控制的API密钥。Claude按照指令读取工作区中的其他文件,并使用攻击者的密钥调用了Anthropic的Files API。出口代理检查了目的地,看到 api.anthropic.com,就放行了。文件被上传到了攻击者的Anthropic账户。沙盒完美运行,然而数据还是被窃取了。
此前,我们将白名单概念化为目的地过滤器,告诉Claude这些域名是可以通信的。但也许更好的概念化是将其视为能力授权。白名单上每个域名通过任何功能可达的每一个函数现在都是一个攻击面。允许 api.anthropic.com 意味着允许文件上传到任意Anthropic账户。
我们通过VM内部的防御性中间人代理修复了这个问题,该代理拦截到我们API的流量。它只放行携带VM自身提供的会话令牌的请求;攻击者嵌入的密钥会被代理拒绝。它还阻止会启用服务端获取的头部。代理位于VM内部而非我们的服务器上,因为只有VM知道来源——从服务器角度看,Cowork请求与任何其他API客户端无法区分。
上图:到 api.anthropic.com 的流量被放行,导致数据外泄。下图:通过VM内部的中间人代理拦截到我们API的流量进行修复。
这也是“你自己构建的软件往往是最薄弱环节”这一原则的第二个实例。我们产品中的虚拟化程序、seccomp和gVisor一直可靠。我们自定义的白名单代理是失效的部分。
我们忽视的风险:VM隔离也将端点检测软件拒之门外
在评估Claude Cowork时,企业安全团队问道:“为什么我们的EDR看不到内部?”答案是,将Claude隔离起来的同一隔离措施也将基于主机的端点检测和响应拒之门外。从EDR的角度看,Claude Cowork是一个不透明的虚拟化进程。它无法检查客户机。
隔离降低了可见性,透明度不足对于合规依赖于端点可见性的团队来说是个问题。我们目前的缓解措施是使用基于拉的OTLP导出,让管理员事后检索事件日志,但这与实时监控不同。如果你在构建类似系统,请尽早为这种对话做好准备。
| 环境 | 临时容器(claude.ai) | 人在环沙盒(Claude Code) | 密封VM(Claude Cowork) | |------|----------------------|-------------------------|------------------------| | 开销:隔离负载 | 容器启动 | 低延迟原生沙盒 | 完整VM启动 | | 开销:用户依赖 | 不适用 | 必须能解释bash | 不适用 | | 风险:爆炸半径 | 服务器端容器(由gVisor+主机基础设施边界守护) | 本地工作区 | 已挂载工作区(由vsock+虚拟化边界守护) |
信任智能体读取的内容
企业经常问我们如何保护MCP连接。这是个好问题,但更恰当的问题比MCP更宽泛。提供给智能体的任何外部资源都同时带来两种风险:传统供应链意义上的代码执行风险,以及提示注入向量。传统的依赖审计(锁定版本、验证签名、审查源码)解决了第一个,但忽略了第二个。
远程与本地的重要性超出表面。本地安装的工具是可审计的。你可以阅读代码、锁定版本,并知道它不会在你不知情时变化。远程工具——托管的MCP服务器、云连接器——可以在你批准后的任何时刻改变行为;你安装时的信任决策可能不再适用。我们的连接器目录通过持续审查来解决这个问题,但目录之外的任何内容都应被视为不受信。先在伪造数据上运行它,在恶意工具的爆炸半径得到控制的环境中。
即使工具可信,工具输出也是一个攻击面。前面提到的GitHub README例子正是这种情况;应用于网页的任何输入扫描也需要以同样严格的程度应用于启用网络的工具结果。虽然这会增加延迟并且不是完美防御,但我们倾向于实时检查:一旦中毒的工具返回值引导智能体窃取了数据,日志只显示一个成功、授权的API调用。事后没有可发现的信号。
在Claude Code和Claude Cowork中,工具调用路由通过执行网络和文件策略的代理,并可以在返回值进入模型上下文之前检查它们。执行检查的分类器可以是一个小型、快速的模型;不需要是进行推理的那个模型。
展望未来
模型和产品正在快速演进。随着这种演进,风险也在变化和演变,我们的缓解措施必须跟上以应对它们。
持久性内存中毒。跨会话持久化的智能体上下文份额持续增长——包括产品记忆、CLAUDE.md文件、挂载的工作区,以及计划任务和长时间运行智能体的状态目录。注入这些中任何一个的载荷会在每次智能体启动时重新加载。随着越来越多的智能体状态跨越会话存活,我们在后利用的经典意义上受到新持久性机制的威胁。会话启动时好的分类器需要变得更加普遍。
多智能体信任升级。一方面,子智能体可以隔离不受信任的内容,向主智能体返回结构化事实而不是原始文本。另一方面,这可以被滥用:如果子智能体的输出被视为比原始工具结果更高信任(因为输出来自“我们”),就会引入新的提示注入向量。在多智能体系统中,在分配不同信任级别和变得易于信任升级之间存在权衡。
智能体身份。Claude Cowork对智能体身份的答案是具体的:凭据保留在主机钥匙串中,VM获得一个每会话限定的令牌,该令牌可以独立于用户撤销。然而,我们开始面对跨平台智能体身份的更广泛问题。智能体应该拥有自己的主体身份,还是应该作为用户的扩展并继承用户的权限?最终,答案可能是两者的混合。
随着智能体变得更加强大,攻击面不断变化。我们所见过的故障类型很可能在行业和实验室中重复。我们需要在智能体特定的安全态势方面进行集体投资,从共享基准和披露规范到共同的身份标准和跨厂商的红队测试。本文聚焦于隔离,但这只是智能体安全图景的一部分。关于治理、可观测性和其他方面,请参阅NIST关于AI智能体身份和授权的项目、由澳大利亚ACSC牵头、CISA和英国NCSC参与发布的六机构关于采用智能体AI的指南,以及ISO/IEC 42001 AI管理标准。我们的Glasswing计划是一个贡献,但我们期待与合作伙伴和竞争对手共同应对这一关键问题。
总结
简而言之,我们反复回归几条原则:
首先在环境层设计隔离,然后在模型层引导行为。教导我们最多的两个事件——员工钓鱼和第三方白名单披露——都是数据外泄的案例,数据通过允许的路径离开。在这两个案例中,模型层无能为力;没有异常可供它捕捉。当所有概率性防御都失效时,确定性边界才是最后一道防线。
将隔离强度与用户的监督能力相匹配。能解释bash的开发者与不能解释的知识工作者运行的不是同一个威胁模型。用户能否评估智能体将要做什么,这个问题应有助于确定隔离策略,而回答错误——对专家限制过多,对非专家信任过度——本身就是一种失败。
警惕自定义组件。经过实战考验的虚拟化程序、系统调用过滤器和容器运行时所承受的对抗性关注比你自己构建的任何东西都多。在本文描述的每一个部署中,标准原语都保持稳定,而我们围绕它们所做的工作暴露了缺陷。
最终,虽然智能体可能是一种新型软件,但它们与系统的交互并非如此。它们仍然读写文件、打开套接字、生成进程;这使得利用成熟工具进行隔离成为一种至关重要的可行防御。随着AI发展,部署的风险回报平衡将持续变化,但对爆炸半径施加硬限制往往能将平衡推向正确的方向。
---
致谢
本文由 Max McGuinness、Mikaela Grace、Jiri De Jonghe、Jake Eaton 和 Abel Ribbink 撰写。
我们也感谢 Hanah Ho、Hasnain Lakhani、Pedram Navid、Molly Villagra、Maya Nielan、Akila Srinivasan、Travis Szucs、Sam Attard、Alfred Xing、Mohamad El Hajj、Gabby Curtis、David Dworken、Adam Jones、Amie Rotherham、Christian Ryan、Lucas Smedley、Brett Andrews 及其他人的贡献。
特别感谢我们的安全和产品工程团队,以及报告 Claude 产品漏洞的个人和组织。
---
脚注
¹ Claude Code 自动模式将命令批准委托给基于模型的分类器;它以遗漏一小部分风险操作(约17%的过度主动动作通过)为代价,最大限度地减少摩擦(约0.4%的良性命令被阻止),因此它是沙盒内部防御深度的一层,而不是沙盒的替代品。