Claude Code官方文档Agent SDK安全部署

Claude Agent SDK 安全部署 - 隔离 / 凭证 / 网络控制

通过隔离、凭证管理和网络控制保护 Claude Code 和 Agent SDK 部署的指南。(原文为英文,已翻译)

· 阅读约 19 分钟

Claude Code 和 Agent SDK 是功能强大的工具,可以代表你执行代码、访问文件并与外部服务交互。与具有这些功能的任何工具一样,深思熟虑地部署它们可以确保你在保持适当控制的同时获得好处。

与遵循预定代码路径的传统软件不同,这些工具基于上下文和目标动态生成其操作。这种灵活性是它们有用的原因,但这也意味着它们的行为可能受到它们处理的内容(文件、网页或用户输入)的影响。这有时被称为提示注入。例如,如果存储库的 README 包含异常说明,Claude Code 可能会以操作员未预期的方式将这些说明纳入其操作中。本指南介绍了减少此风险的实用方法。

好消息是,保护代理部署不需要外来的基础设施。运行任何半信任代码的相同原则也适用于此:隔离、最小权限和深度防御。Claude Code 包含几个有助于解决常见问题的安全功能,本指南将介绍这些功能以及对于需要更多功能的人员的其他加固选项。

并非每个部署都需要最大限度的安全性。在笔记本电脑上运行 Claude Code 的开发人员与在多租户环境中处理客户数据的公司有不同的要求。本指南介绍了从 Claude Code 的内置安全功能到强化的生产架构的各种选项,因此你可以选择适合你情况的选项。

威胁模型

代理可能由于提示注入(嵌入在它们处理的内容中的指令)或模型错误而采取意外操作。Claude 模型被设计为抵抗这种情况;有关评估详细信息,请参阅模型概述和你部署的模型的系统卡。

尽管如此,深度防御仍然是良好实践。例如,如果代理处理指示它将客户数据发送到外部服务器的恶意文件,网络控制可以完全阻止该请求。

内置安全功能

Claude Code 包含几个解决常见问题的安全功能。有关完整详细信息,请参阅安全文档

  • 权限系统:每个工具和 bash 命令可以配置为允许、阻止或提示用户批准。使用通配符模式创建规则,例如”允许所有 npm 命令”或”阻止任何带 sudo 的命令”。组织可以设置应用于所有用户的策略。请参阅权限
  • 权限的命令解析:在执行 bash 命令之前,Claude Code 将它们解析为 AST,并将结果与你的权限规则匹配。无法干净解析或不匹配允许规则的命令需要显式批准。一小组结构(例如 eval)始终需要批准,无论允许规则如何。这是一个权限门,而不是沙箱;它不会从命令的目标路径或效果推断它是否危险。
  • 网络搜索摘要:搜索结果被摘要,而不是将原始内容直接传递到上下文中,从而降低来自恶意 Web 内容的提示注入的风险。
  • 沙箱模式:Bash 命令可以在限制文件系统和网络访问的沙箱环境中运行。有关详细信息,请参阅沙箱文档

安全原则

对于需要超出 Claude Code 默认值的额外加固的部署,这些原则指导可用选项。

安全边界

安全边界分离具有不同信任级别的组件。对于高安全部署,你可以将敏感资源(如凭证)放置在包含代理的边界之外。如果代理的环境出现问题,该边界之外的资源仍然受到保护。

例如,与其让代理直接访问 API 密钥,你可以在代理的环境之外运行一个代理(proxy)将密钥注入请求中。代理可以进行 API 调用,但它本身永远看不到凭证。此模式对于多租户部署或处理不受信任的内容很有用。

最小权限

需要时,你可以限制代理只具有其特定任务所需的功能:

资源限制选项
文件系统仅挂载所需目录,优先只读
网络通过代理(proxy)限制到特定端点
凭证通过代理(proxy)注入而不是直接暴露
系统功能在容器中删除 Linux 功能

深度防御

对于高安全环境,分层多个控件提供额外保护。选项包括:

  • 容器隔离
  • 网络限制
  • 文件系统控制
  • 代理(proxy)处的请求验证

正确的组合取决于你的威胁模型和操作要求。

隔离技术

不同的隔离技术在安全强度、性能和操作复杂性之间提供不同的权衡。

ℹ️ 在所有这些配置中,Claude Code(或你的 Agent SDK 应用程序)在隔离边界(沙箱、容器或 VM)内运行。下面描述的安全控件限制代理可以从该边界内访问的内容。

技术隔离强度性能开销复杂性
Sandbox runtime良好(安全默认值)非常低
容器(Docker)取决于设置中等
gVisor出色(正确设置时)中/高中等
VM(Firecracker、QEMU)出色(正确设置时)中/高

Sandbox runtime

对于不使用容器的轻量级隔离,sandbox-runtime 在操作系统级别强制执行文件系统和网络限制。

主要优势是简单性:不需要 Docker 配置、容器镜像或网络设置。代理(proxy)和文件系统限制是内置的。你提供一个指定允许的域和路径的设置文件。

工作原理:

  • 文件系统:使用操作系统原语(Linux 上的 bubblewrap,macOS 上的 sandbox-exec)来限制对配置路径的读/写访问
  • 网络:删除网络命名空间(Linux)或使用 Seatbelt 配置文件(macOS)将网络流量通过内置代理(proxy)路由
  • 配置:基于 JSON 的允许列表,用于域和文件系统路径

设置:

npm install @anthropic-ai/sandbox-runtime

然后创建一个指定允许路径和域的配置文件。

安全考虑:

  1. 同一主机内核:与 VM 不同,沙箱进程共享主机内核。理论上,内核漏洞可能会启用逃逸。对于某些威胁模型,这是可以接受的,但如果你需要内核级隔离,请使用 gVisor 或单独的 VM。

  2. 没有 TLS 检查:代理(proxy)根据客户端提供的主机名将域列入白名单,不会终止或检查加密流量。在沙箱内运行的代码可能使用域前置或类似技术访问白名单之外的主机。如果你的威胁模型需要更强的保证,请配置 TLS 终止代理(proxy)。有关详细信息,请参阅沙箱安全限制。另外,如果代理具有允许域的宽松凭证,请确保它不能使用该域触发其他网络请求或泄漏数据。

对于许多单开发者和 CI/CD 用例,sandbox-runtime 以最小的设置显着提高了门槛。下面的部分介绍了需要更强隔离的部署的容器和 VM。

容器

容器通过 Linux 命名空间提供隔离。每个容器都有自己的文件系统、进程树和网络堆栈视图,同时共享主机内核。

安全加固的容器配置可能如下所示:

docker run \
  --cap-drop ALL \
  --security-opt no-new-privileges \
  --security-opt seccomp=/path/to/seccomp-profile.json \
  --read-only \
  --tmpfs /tmp:rw,noexec,nosuid,size=100m \
  --tmpfs /home/agent:rw,noexec,nosuid,size=500m \
  --network none \
  --memory 2g \
  --cpus 2 \
  --pids-limit 100 \
  --user 1000:1000 \
  -v /path/to/code:/workspace:ro \
  -v /var/run/proxy.sock:/var/run/proxy.sock:ro \
  agent-image

每个选项的作用如下:

选项目的
--cap-drop ALL删除可能启用权限提升的 Linux 功能(如 NET_ADMINSYS_ADMIN
--security-opt no-new-privileges防止进程通过 setuid 二进制文件获得权限
--security-opt seccomp=...限制可用的系统调用;Docker 的默认值阻止约 44 个,自定义配置文件可以阻止更多
--read-only使容器的根文件系统不可变,防止代理持久化更改
--tmpfs /tmp:...提供一个可写的临时目录,容器停止时会被清除
--network none删除所有网络接口;代理通过下面挂载的 Unix 套接字进行通信
--memory 2g限制内存使用以防止资源耗尽
--pids-limit 100限制进程计数以防止 fork 炸弹
--user 1000:1000作为非 root 用户运行
-v ...:/workspace:ro只读挂载代码,以便代理可以分析但不能修改它。避免挂载敏感的主机目录,如 ~/.ssh~/.aws~/.config
-v .../proxy.sock:...挂载连接到在容器外运行的代理(proxy)的 Unix 套接字(见下文)

Unix 套接字架构:

使用 --network none,容器根本没有网络接口。代理到达外部世界的唯一方法是通过挂载的 Unix 套接字,它连接到主机上运行的代理(proxy)。此代理(proxy)可以强制执行域允许列表、注入凭证并记录所有流量。

这与 sandbox-runtime 使用的架构相同。即使代理通过提示注入被破坏,它也无法将数据泄漏到任意服务器。它只能通过代理(proxy)通信,代理(proxy)控制哪些域可以访问。有关详细信息,请参阅 Claude Code 沙箱博客文章

其他加固选项:

选项目的
--userns-remap将容器 root 映射到非特权主机用户;需要守护进程配置,但限制容器逃逸造成的损害
--ipc private隔离进程间通信以防止跨容器攻击

gVisor

标准容器共享主机内核:当容器内的代码进行系统调用时,它直接进入运行主机的相同内核。这意味着内核漏洞可能允许容器逃逸。gVisor 通过在用户空间中拦截系统调用来解决此问题,然后再它们到达主机内核,实现其自己的兼容性层,无需涉及真实内核即可处理大多数系统调用。

如果代理运行恶意代码(可能由于提示注入),该代码在容器中运行,可能会尝试内核漏洞利用。使用 gVisor 后,攻击面要小得多:恶意代码需要先利用 gVisor 的用户空间实现,并且对真实内核的访问有限。

要在 Docker 中使用 gVisor,请安装 runsc 运行时并配置守护进程:

// /etc/docker/daemon.json
{
  "runtimes": {
    "runsc": {
      "path": "/usr/local/bin/runsc"
    }
  }
}

然后用以下命令运行容器:

docker run --runtime=runsc agent-image

性能考虑:

工作负载开销
CPU 绑定的计算约 0%(无系统调用拦截)
简单的系统调用约 2 倍较慢
文件 I/O 密集型对于繁重的打开/关闭模式最多慢 10-200 倍

对于多租户环境或处理不受信任的内容时,额外的隔离通常值得付出代价。

虚拟机

VM 通过 CPU 虚拟化扩展提供硬件级隔离。每个 VM 运行自己的内核,创建一个强边界。访客内核中的漏洞不会直接危及主机。但是,VM 不会自动比 gVisor 等替代方案”更安全”。VM 安全性在很大程度上取决于管理程序和设备仿真代码。

Firecracker 专为轻量级 microVM 隔离设计。它可以在不到 125 毫秒内启动 VM,内存开销小于 5 MiB,剥离不必要的设备仿真以减少攻击面。

使用这种方法,代理 VM 没有外部网络接口。相反,它通过 vsock(虚拟套接字)进行通信。所有流量通过 vsock 路由到主机上的代理(proxy),代理(proxy)在转发请求之前强制执行允许列表并注入凭证。

云部署

对于云部署,你可以将上述任何隔离技术与云原生网络控件相结合:

  1. 在没有互联网网关的私有子网中运行代理容器
  2. 配置云防火墙规则(AWS Security Groups、GCP VPC firewall)以阻止除你的代理(proxy)之外的所有出口
  3. 运行一个代理(proxy)(例如使用其 credential_injector 过滤器的 Envoy),验证请求、强制执行域允许列表、注入凭证并转发到外部 API
  4. 为代理的服务帐户分配最小的 IAM 权限,尽可能通过代理(proxy)路由敏感访问
  5. 在代理(proxy)记录所有流量以供审计

凭证管理

代理通常需要凭证来调用 API、访问存储库或与云服务交互。挑战在于提供此访问权限而不暴露凭证本身。

代理(proxy)模式

推荐的方法是在代理的安全边界之外运行一个代理(proxy),将凭证注入到出站请求中。代理发送不带凭证的请求,代理(proxy)添加它们,并将请求转发到其目标。

这种模式有几个好处:

  1. 代理永远看不到实际的凭证
  2. 代理(proxy)可以强制执行允许端点的列表
  3. 代理(proxy)可以记录所有请求以供审计
  4. 凭证存储在一个安全位置,而不是分发到每个代理

配置 Claude Code 使用代理(proxy)

Claude Code 支持两种通过代理(proxy)路由采样请求的方法:

选项 1:ANTHROPIC_BASE_URL(简单,但仅用于采样 API 请求)

export ANTHROPIC_BASE_URL="http://localhost:8080"

这告诉 Claude Code 和 Agent SDK 将采样请求发送到你的代理(proxy)而不是直接发送到 Claude API。你的代理(proxy)接收明文 HTTP 请求,可以检查和修改它们(包括注入凭证),然后转发到真正的 API。

选项 2:HTTP_PROXY / HTTPS_PROXY(系统范围)

export HTTP_PROXY="http://localhost:8080"
export HTTPS_PROXY="http://localhost:8080"

Claude Code 和 Agent SDK 遵守这些标准环境变量,通过代理(proxy)路由所有 HTTP 流量。对于 HTTPS,代理(proxy)创建一个加密的 CONNECT 隧道:它无法看到或修改请求内容而不进行 TLS 拦截。

实现代理(proxy)

你可以构建自己的代理(proxy)或使用现有的:

  • Envoy Proxy:生产级代理(proxy),具有用于添加身份验证头的 credential_injector 过滤器
  • mitmproxy:用于检查和修改 HTTPS 流量的 TLS 终止代理(proxy)
  • Squid:具有访问控制列表的缓存代理(proxy)
  • LiteLLM:具有凭证注入和速率限制的 LLM 网关

其他服务的凭证

除了从 Claude API 采样之外,代理通常需要对其他服务(例如 git 存储库、数据库和内部 API)进行身份验证访问。有两种主要方法:

自定义工具

通过 MCP 服务器或将请求路由到代理安全边界之外运行的服务的自定义工具提供访问权限。代理调用工具,但实际的身份验证请求在外部发生。工具调用一个代理(proxy),代理(proxy)注入凭证。

例如,git MCP 服务器可以接受来自代理的命令,但将它们转发到主机上运行的 git 代理(proxy),后者在联系远程存储库之前添加身份验证。代理永远看不到凭证。

优势:

  • 没有 TLS 拦截:外部服务直接进行身份验证请求
  • 凭证保留在外部:代理只看到工具接口,而不是底层凭证

流量转发

对于 Claude API 调用,ANTHROPIC_BASE_URL 允许你将请求路由到可以以明文检查和修改它们的代理(proxy)。但对于其他 HTTPS 服务(GitHub、npm 注册表、内部 API),流量通常是端到端加密的。即使你通过 HTTP_PROXY 通过代理(proxy)路由它,代理(proxy)也只能看到一个不透明的 TLS 隧道,无法注入凭证。

要在不使用自定义工具的情况下修改对任意服务的 HTTPS 流量,你需要一个 TLS 终止代理(proxy),它解密流量、检查或修改它,然后在转发之前重新加密。这需要:

  1. 在代理的容器外运行代理(proxy)
  2. 在代理的信任存储中安装代理(proxy)的 CA 证书(以便代理信任代理(proxy)的证书)
  3. 配置 HTTP_PROXY/HTTPS_PROXY 通过代理(proxy)路由流量

这种方法可处理任何基于 HTTP 的服务,而无需编写自定义工具,但增加了围绕证书管理的复杂性。

请注意,并非所有程序都遵守 HTTP_PROXY/HTTPS_PROXY。大多数工具(curl、pip、npm、git)都遵守,但有些可能会绕过这些变量并直接连接。例如,Node.js fetch() 默认忽略这些变量;在 Node 24+ 中,你可以设置 NODE_USE_ENV_PROXY=1 以启用支持。要全面覆盖,你可以使用 proxychains 来拦截网络调用,或配置 iptables 将出站流量重定向到透明代理(proxy)。

ℹ️ 透明代理(proxy) 在网络级别拦截流量,因此客户端不需要配置以使用它。常规代理要求客户端显式连接并使用 HTTP CONNECT 或 SOCKS。透明代理(如 Squid 或处于透明模式的 mitmproxy)可以处理原始重定向的 TCP 连接。

两种方法仍然需要 TLS 终止代理(proxy)和受信任的 CA 证书。它们只是确保流量实际到达代理(proxy)。

文件系统配置

文件系统控件决定代理可以读取和写入哪些文件。

只读代码挂载

当代理需要分析代码但不需要修改它时,请只读挂载该目录:

docker run -v /path/to/code:/workspace:ro agent-image

⚠️ 即使对代码目录的只读访问也可能会暴露凭证。在挂载之前要排除或清理的常见文件:

文件风险
.env.env.localAPI 密钥、数据库密码、密钥
~/.git-credentials明文中的 Git 密码/令牌
~/.aws/credentialsAWS 访问密钥
~/.config/gcloud/application_default_credentials.jsonGoogle Cloud ADC 令牌
~/.azure/Azure CLI 凭证
~/.docker/config.jsonDocker 注册表身份验证令牌
~/.kube/configKubernetes 集群凭证
.npmrc.pypirc包注册表令牌
*-service-account.jsonGCP 服务帐户密钥
*.pem*.key私钥

考虑只复制所需的源文件,或使用 .dockerignore 样式的过滤。

可写位置

如果代理需要写入文件,你有几个选项,取决于你是否希望更改持久化:

对于容器中的临时工作区,使用仅存在于内存中且容器停止时被清除的 tmpfs 挂载:

docker run \
  --read-only \
  --tmpfs /tmp:rw,noexec,nosuid,size=100m \
  --tmpfs /workspace:rw,noexec,size=500m \
  agent-image

如果你希望在持久化之前查看更改,叠加文件系统允许代理在不修改底层文件的情况下进行写入。更改存储在一个单独的层中,你可以检查、应用或丢弃。对于完全持久的输出,挂载一个专用卷但保持它与敏感目录分开。

延伸阅读


本文翻译自 Anthropic Claude Code 官方文档,最近一次同步:2025-05-01。