本页目录22
- 威胁模型核心是提示注入(prompt injection):代理处理的文件/网页/输入中的异常指令可能被代理当作行动指令执行,纵深防御(如网络控制)可兜底拦截。
- 内置安全特性包括权限系统、bash 命令 AST 解析与权限匹配、网页搜索结果摘要化、以及沙箱模式(sandbox mode),但命令解析是权限门禁而非沙箱。
- 隔离技术从轻到重依次为 sandbox-runtime(低开销、OS 级)、Docker 容器、gVisor(用户态拦截系统调用)、VM/Firecracker(硬件级隔离,微 VM 可 125ms 内启动)。
- 推荐使用「代理模式」(proxy pattern):在代理安全边界之外运行 proxy 注入凭证,代理本身永远看不到真实凭证,同时可做白名单与审计日志。
- ANTHROPIC_BASE_URL 只对 Claude API 采样请求生效且是明文可修改;要拦截其他 HTTPS 服务(GitHub、npm 等)则需 TLS 终止代理 + 在代理信任库安装其 CA 证书。
- 只读挂载代码目录也可能泄露 .env、~/.aws/credentials、~/.kube/config 等敏感文件,需要提前过滤或仅拷贝必要源文件。
本文是对官方 Agent SDK 某页的中文整理,完整与最新内容以原文为准:https://code.claude.com/docs/en/agent-sdk/secure-deployment
概述
Claude Code 与 Agent SDK 能够代表用户执行代码、访问文件并与外部服务交互。与遵循预定代码路径的传统软件不同,这类工具是根据上下文和目标动态生成行动的——这种灵活性正是其价值所在,但也意味着其行为可能受到所处理内容(文件、网页、用户输入)的影响,这有时被称为提示注入(prompt injection)。例如,如果某个仓库的 README 中包含异常指令,Claude Code 可能会以运维方未预料到的方式将其纳入自己的行动。本指南介绍降低此类风险的实用方法。
并非所有部署都需要最高级别的安全性。在笔记本电脑上运行 Claude Code 的开发者,与在多租户环境中处理客户数据的公司,需求并不相同。本指南涵盖从 Claude Code 内置安全特性到加固的生产架构等一系列选项,供读者按需选择。
威胁模型
代理可能因提示注入(嵌入在其处理内容中的指令)或模型错误而采取非预期行动。Claude 模型的设计目标是抵御此类风险;评测细节可参考 model overview 及所部署模型对应的 system card。
即便如此,纵深防御(defense in depth)仍是良好实践。例如,若代理处理了一个恶意文件,该文件指示其向外部服务器发送客户数据,网络控制可以彻底阻断该请求。
内置安全特性
Claude Code 内置了若干针对常见顾虑的安全特性,完整细节见 security 文档。
- 权限系统(Permissions system):每个工具和 bash 命令都可配置为允许、阻止或提示用户批准。可用 glob 模式创建规则,如「允许所有 npm 命令」或「阻止任何包含 sudo 的命令」。组织可设置跨所有用户生效的策略。参见 permissions。
- 权限相关的命令解析(Command parsing for permissions):在执行 bash 命令前,Claude Code 会将其解析为 AST 并与权限规则匹配。无法被干净解析、或未命中允许规则的命令需要显式批准。少数构造(如
eval)无论允许规则如何都始终需要批准。这是一个权限门禁而非沙箱;除了内置的安全检查(如针对rm、rmdir的 critical-path check 以及 protected paths 列表外),它并不会根据命令的目标路径或效果去推断其是否危险。 - 网页搜索摘要化(Web search summarization):搜索结果会被摘要化而非将原始内容直接传入上下文,降低来自恶意网页内容的提示注入风险。
- 沙箱模式(Sandbox mode):bash 命令可在受限文件系统和网络访问的沙箱环境中运行。详见 sandboxing 文档。
安全原则
对于需要在 Claude Code 默认设置之上进一步加固的部署,以下原则指导可选方案。
安全边界(Security boundaries)
安全边界用于分隔不同信任级别的组件。对于高安全需求的部署,可以将敏感资源(如凭证)放在包含代理的边界之外。如果代理环境中出了问题,边界之外的资源仍受保护。
例如,与其让代理直接持有 API key,不如在代理环境外运行一个代理服务(proxy),由它向请求中注入 key。代理可以发起 API 调用,但永远不会看到凭证本身。此模式适用于多租户部署或处理不受信任内容的场景。
最小权限(Least privilege)
必要时,可将代理限制为仅拥有其具体任务所需的能力:
| Resource(资源) | Restriction options(限制选项) |
|---|---|
| Filesystem | Mount only needed directories, prefer read-only |
| Network | Restrict to specific endpoints via proxy |
| Credentials | Inject via proxy rather than exposing directly |
| System capabilities | Drop Linux capabilities in containers |
纵深防御(Defense in depth)
对于高安全环境,叠加多层控制可提供额外保护,可选项包括:
- 容器隔离(Container isolation)
- 网络限制(Network restrictions)
- 文件系统控制(Filesystem controls)
- 在代理处进行请求校验(Request validation at a proxy)
具体组合取决于威胁模型和运维要求。
隔离技术
不同隔离技术在安全强度、性能与运维复杂度之间有不同的取舍。
在下列所有配置中,Claude Code(或你的 Agent SDK 应用)都运行在隔离边界(沙箱、容器或 VM)内部。下文所述安全控制限制的是代理在该边界内部所能访问的内容。
| Technology(技术) | Isolation strength(隔离强度) | Performance overhead(性能开销) | Complexity(复杂度) |
|---|---|---|---|
| Sandbox runtime | Good (secure defaults) | Very low | Low |
| Containers (Docker) | Setup dependent | Low | Medium |
| gVisor | Excellent (with correct setup) | Medium/High | Medium |
| VMs (Firecracker, QEMU) | Excellent (with correct setup) | High | Medium/High |
Sandbox runtime
对于无需容器的轻量级隔离,sandbox-runtime 在操作系统层面强制执行文件系统与网络限制。
其主要优势是简单:无需 Docker 配置、容器镜像或网络设置,代理与文件系统限制均已内置。
工作原理:
- Filesystem:在 Linux 上使用
bubblewrap、在 macOS 上使用sandbox-exec等 OS 原语来限制对已配置路径的读写访问 - Network:在 Linux 上移除网络命名空间,在 macOS 上使用 Seatbelt profile,将网络流量路由经过内置代理
- Configuration:基于 JSON 的域名和文件系统路径白名单
安装:
npm install @anthropic-ai/sandbox-runtime
然后创建一个配置文件指定允许的路径和域名。
安全考量:
-
共享宿主内核(Same-host kernel):与 VM 不同,沙箱化的进程共享宿主内核。理论上内核漏洞可能导致逃逸。这对某些威胁模型是可接受的,但如需内核级隔离,应使用 gVisor 或独立 VM。
-
不做 TLS 检测(No TLS inspection):代理是根据客户端提供的主机名对域名做白名单,并不会终止或检查加密流量。沙箱内运行的代码有可能通过域前置(domain fronting)或类似技术访问白名单之外的主机。如果你的威胁模型需要更强保证,应配置一个TLS 终止代理。详见 sandboxing security limitations。另外,若代理对某个允许域名持有权限过大的凭证,需确保它无法借该域名触发其他网络请求或用于数据外泄。
对于许多单开发者及 CI/CD 场景,sandbox-runtime 以极小的配置成本显著提高了安全门槛。下文各节介绍需要更强隔离的部署所用的容器与 VM 方案。
Containers
容器通过 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
各选项作用如下:
| Option(选项) | Purpose(作用) |
|---|---|
--cap-drop ALL | 移除如 NET_ADMIN、SYS_ADMIN 等可能导致权限提升的 Linux capability |
--security-opt no-new-privileges | 防止进程通过 setuid 二进制获得权限提升 |
--security-opt seccomp=... | 限制可用的系统调用;Docker 默认屏蔽约 44 个,自定义 profile 可屏蔽更多 |
--read-only | 使容器根文件系统不可变,阻止代理持久化任何修改 |
--tmpfs /tmp:... | 提供一个可写的临时目录,容器停止时会被清空 |
--network none | 移除所有网络接口;代理通过下方挂载的 Unix socket 通信 |
--memory 2g | 限制内存使用,防止资源耗尽 |
--pids-limit 100 | 限制进程数,防止 fork bomb |
--user 1000:1000 | 以非 root 用户运行 |
-v ...:/workspace:ro | 以只读方式挂载代码,使代理只能分析而不能修改。避免挂载敏感的宿主目录,例如 ~/.ssh、~/.aws、~/.config |
-v .../proxy.sock:... | 挂载一个连接到容器外运行的代理的 Unix socket(见下文) |
Unix socket 架构:
在 --network none 下,容器完全没有网络接口。代理触及外部世界的唯一方式是通过挂载的 Unix socket,该 socket 连接到宿主机上运行的一个代理(proxy)。这个代理可以强制执行域名白名单、注入凭证并记录全部流量。
这与 sandbox-runtime 所用架构相同。即使代理(agent)因提示注入被攻陷,它也无法将数据外泄到任意服务器——它只能通过 proxy 通信,而 proxy 控制着哪些域名可达。更多细节参见 Claude Code sandboxing blog post。
额外加固选项:
| Option(选项) | Purpose(作用) |
|---|---|
--userns-remap | 将容器内 root 映射为宿主机上无特权用户;需要 daemon 配置,但可限制容器逃逸造成的损害 |
--ipc private | 隔离进程间通信,防止跨容器攻击 |
gVisor
标准容器共享宿主内核:容器内代码发起系统调用时,会直接进入运行宿主的同一内核。这意味着一个内核漏洞就可能导致容器逃逸。gVisor 的做法是在用户态拦截系统调用、在其到达宿主内核之前处理,它实现了自己的兼容层,处理大部分系统调用而不涉及真实内核。
如果代理运行了恶意代码(可能源于提示注入),该代码会在容器内运行并可能尝试内核漏洞利用。使用 gVisor 后攻击面显著缩小:恶意代码必须先攻破 gVisor 的用户态实现,并且能触及真实内核的能力也很有限。
要在 Docker 中使用 gVisor,需安装 runsc 运行时并配置 daemon:
{
"runtimes": {
"runsc": {
"path": "/usr/local/bin/runsc"
}
}
}
然后以如下方式运行容器:
docker run --runtime=runsc agent-image
性能考量:
| Workload(负载类型) | Overhead(开销) |
|---|---|
| CPU-bound computation | ~0%(无系统调用拦截) |
| Simple syscalls | 约慢 2 倍 |
| File I/O intensive | 频繁 open/close 场景下最高可慢 10-200 倍 |
对于多租户环境或处理不受信任内容的场景,额外的隔离通常是值得的开销。
Virtual machines
VM 通过 CPU 虚拟化扩展实现硬件级隔离。每个 VM 运行自己的内核,形成较强的边界:guest 内核中的漏洞不会直接波及宿主机。但 VM 并非天然「比 gVisor 等方案更安全」——VM 的安全性很大程度上取决于 hypervisor 和设备模拟代码的实现质量。
Firecracker 专为轻量级 microVM 隔离设计。它能在 125ms 内启动 VM,内存开销小于 5 MiB,通过剥离不必要的设备模拟来缩小攻击面。
采用该方案时,代理所在 VM 没有外部网络接口,而是通过 vsock(虚拟 socket)通信。所有流量经由 vsock 路由到宿主机上的一个代理,该代理在转发请求前执行白名单校验并注入凭证。
Cloud deployments
对于云端部署,可以将上述任一隔离技术与云原生网络控制结合使用:
- 在没有互联网网关的私有子网中运行代理容器
- 配置云防火墙规则(AWS Security Groups、GCP VPC firewall),阻止除通往你的代理之外的所有出站流量
- 运行一个代理(例如带有
credential_injectorfilter 的 Envoy),对请求做校验、执行域名白名单、注入凭证并转发到外部 API - 为代理的服务账户分配最小化的 IAM 权限,尽可能将敏感访问路由经过代理
- 在代理处记录全部流量以供审计
凭证管理
代理通常需要凭证来调用 API、访问仓库或与云服务交互。挑战在于:如何在不暴露凭证本身的前提下提供这种访问能力。
代理模式(The proxy pattern)
推荐做法是在代理(agent)的安全边界之外运行一个 proxy,由它向出站请求中注入凭证。代理(agent)发送不带凭证的请求,proxy 负责添加凭证并转发到目的地。
此模式有以下几个好处:
- 代理(agent)永远看不到真实凭证
- proxy 可以强制执行允许端点的白名单
- proxy 可以记录全部请求以供审计
- 凭证集中存放在一处安全位置,而非分散到每个代理
配置 Claude Code 使用代理
Claude Code 支持两种方式将采样请求路由经过代理:
方式一:ANTHROPIC_BASE_URL(简单,但仅对采样 API 请求生效)
export ANTHROPIC_BASE_URL="http://localhost:8080"
这会让 Claude Code 与 Agent SDK 将采样请求发送到你的代理而非直接发往 Claude API。你的代理接收明文 HTTP 请求,可以检查并修改它们(包括注入凭证),然后转发至真实 API。
方式二:HTTP_PROXY / HTTPS_PROXY(系统级)
export HTTP_PROXY="http://localhost:8080"
export HTTPS_PROXY="http://localhost:8080"
Claude Code 与 Agent SDK 遵循这两个标准环境变量,将所有 HTTP 流量路由经过代理。对于 HTTPS,代理会建立一条加密的 CONNECT 隧道:若不做 TLS 拦截,代理无法查看或修改请求内容。
实现代理
可以自建代理,也可以使用现成方案:
- Envoy Proxy:生产级代理,提供用于添加认证头的
credential_injectorfilter - mitmproxy:用于检查和修改 HTTPS 流量的 TLS 终止代理
- Squid:带访问控制列表的缓存代理
- LiteLLM:支持凭证注入与限流的 LLM 网关
其他服务的凭证
除了对 Claude API 的采样请求外,代理通常还需要对其他服务(如 git 仓库、数据库、内部 API)进行已认证的访问。主要有两种方式:
自定义工具(Custom tools)
通过 MCP server 或自定义工具提供访问,把请求路由到运行在代理安全边界之外的服务。代理(agent)调用工具,而实际的已认证请求发生在边界外——工具调用一个负责注入凭证的 proxy。
例如,一个 git MCP server 可以接受来自代理的命令,但将其转发到运行在宿主机上的 git proxy,由后者在联系远程仓库前添加身份认证。代理(agent)永远不会看到凭证。
优势:
- 无需 TLS 拦截(No TLS interception):外部服务直接发起已认证请求
- 凭证留在边界之外(Credentials stay outside):代理只能看到工具接口,而非底层凭证
流量转发(Traffic forwarding)
对于 Claude API 调用,ANTHROPIC_BASE_URL 可以让你将请求路由到一个能以明文检查和修改请求的代理。但对于其他 HTTPS 服务(GitHub、npm registry、内部 API),流量通常是端到端加密的。即使通过 HTTP_PROXY 将其路由经过代理,代理也只能看到一条不透明的 TLS 隧道,无法注入凭证。
若要在不编写自定义工具的情况下修改到任意服务的 HTTPS 流量,需要一个 TLS 终止代理,它先解密流量、检查或修改后再重新加密并转发。这需要:
- 在代理(agent)容器之外运行该代理
- 将该代理的 CA 证书安装进代理(agent)的信任库(使其信任该代理签发的证书)
- 配置
HTTP_PROXY/HTTPS_PROXY将流量路由经过该代理
此方案无需编写自定义工具即可覆盖任意基于 HTTP 的服务,但增加了证书管理方面的复杂度。
需要注意的是,并非所有程序都遵循 HTTP_PROXY/HTTPS_PROXY。大多数工具(curl、pip、npm、git)会遵循,但部分程序可能绕过这些变量直接连接。例如,Node.js 的 fetch() 默认会忽略这些变量;在 Node 24+ 中可设置 NODE_USE_ENV_PROXY=1 来启用支持。若需全面覆盖,可使用 proxychains 拦截网络调用,或配置 iptables 将出站流量重定向到透明代理。
透明代理(transparent proxy) 在网络层拦截流量,客户端无需专门配置即可使用。普通代理要求客户端显式连接并使用 HTTP CONNECT 或 SOCKS 协议通信。透明代理(如处于透明模式的 Squid 或 mitmproxy)可以处理原始的重定向 TCP 连接。
以上两种方式都仍然需要配合 TLS 终止代理及受信任的 CA 证书,它们只是确保流量确实能到达该代理。
文件系统配置
文件系统控制决定了代理可以读取和写入哪些文件。
只读挂载代码(Read-only code mounting)
当代理需要分析代码但不需要修改时,应以只读方式挂载目录:
docker run -v /path/to/code:/workspace:ro agent-image
警告:即便是对代码目录的只读访问,也可能暴露凭证。挂载前应排除或脱敏以下常见文件:
File(文件) Risk(风险) .env、.env.localAPI key、数据库密码、密钥 ~/.git-credentials明文存储的 Git 密码/token ~/.aws/credentialsAWS access key ~/.config/gcloud/application_default_credentials.jsonGoogle Cloud ADC token ~/.azure/Azure CLI 凭证 ~/.docker/config.jsonDocker registry 认证 token ~/.kube/configKubernetes 集群凭证 .npmrc、.pypirc包注册表 token *-service-account.jsonGCP service account key *.pem、*.key私钥 建议只拷贝所需的源文件,或使用类似
.dockerignore的方式做过滤。
可写位置(Writable locations)
如果代理需要写入文件,可根据是否需要持久化改动来选择:
对于容器中的临时工作区,使用只存在于内存中、容器停止即清空的 tmpfs 挂载:
docker run \
--read-only \
--tmpfs /tmp:rw,noexec,nosuid,size=100m \
--tmpfs /workspace:rw,noexec,size=500m \
agent-image
如果希望在持久化改动之前先做审查,可以使用 overlay 文件系统,让代理写入时不直接修改底层文件——改动会存放在一个独立的层中,供审查、应用或丢弃。若需要完全持久化的输出,应挂载专用卷,并使其与敏感目录分离。