AI Agent 不再只是生成一段文本。它可能执行 Shell、安装依赖、读取仓库、调用外部 API,甚至运行刚刚生成的代码。当 Agent 的能力越来越强,核心问题就从“它能做什么”变成了“即使它做错了,影响能否被限制住”。
Docker 在 WeAreDevelopers 上介绍了 Cloud Sandboxes、开放的 Sandbox Kit 规范,并承诺推动相关 Kit 进入 CNCF,以中立治理方式继续发展。这三件事放在一起看,比单独发布一个沙箱产品更有意义:云端沙箱提供执行环境,开放规范定义集成边界,中立治理则减少生态被单一供应商锁定的风险。
Agent 需要的不是普通容器,而是明确的信任边界
传统容器常用于运行开发者已经审核过的服务镜像。Agent 工作负载却可能包含动态生成、临时下载或来自用户输入的代码,两者的风险模型并不相同。
一个 Agent 执行环境至少要回答这些问题:
- 它能读取哪些文件?源代码、SSH 密钥和云凭证是否被隔离?
- 它能访问哪些网络地址?是否允许任意出网?
- 它能启动多少进程、使用多少 CPU 和内存?
- 单次任务多久后必须终止?
- 任务结束后,文件系统和凭证是否会被销毁?
- 谁能看到命令、网络访问和产物审计记录?
因此,“使用了容器”并不自动等于“安全运行了不可信 Agent”。容器默认共享宿主机内核;错误挂载 Docker Socket、宿主目录或长期凭证,仍可能让隔离形同虚设。真正有效的沙箱需要把只读文件系统、非特权用户、能力裁剪、网络策略、资源配额、短期身份和生命周期管理组合起来。
Cloud Sandboxes、开放规范与 CNCF 治理分别解决什么
这次发布可以拆成三个层次理解。
Cloud Sandboxes 面向“在哪里运行”这个问题。对于需要临时执行代码的 Agent,托管沙箱可以减少团队自行维护隔离基础设施的成本。不过,具体的隔离强度、网络控制、日志能力和运行时限制,仍应根据产品文档和实际测试确认,不能只凭“sandbox”这个名称作安全判断。
Sandbox Kit 规范 面向“如何接入”这个问题。开放规范的价值在于让 Agent 框架、IDE、CI 系统和沙箱后端围绕共同接口协作。理想情况下,调用方只描述任务、资源和权限,而不是绑定某家平台的内部实现。
进入 CNCF 的承诺 面向“由谁决定规范未来”这个问题。如果项目最终在中立治理下演进,云厂商、Agent 框架和终端用户更容易共同定义接口,也更有机会形成多个兼容实现。需要注意的是,“承诺提交”不等于已经完成 CNCF 接纳;成熟度、治理结构和兼容性仍要看后续进展。
在本地先做一个最小隔离实验
下面的示例不是 Cloud Sandboxes 或 Sandbox Kit 的官方 API,而是一个可以直接运行的本地近似实验,用来验证几项基础控制:无网络、根文件系统只读、非 root 用户、无 Linux capabilities,以及 CPU、内存和进程数限制。
运行前需要安装 Docker。Linux、macOS 或 WSL 中可直接复制以下命令:
mkdir -p agent-sandbox-demo/workspace
cd agent-sandbox-demo
cat > Dockerfile <<'EOF'
FROM python:3.12-slim
RUN useradd --uid 10001 --create-home agent
WORKDIR /app
COPY agent.py /app/agent.py
ENV PYTHONDONTWRITEBYTECODE=1
USER 10001:10001
CMD ["python", "/app/agent.py"]
EOF
cat > agent.py <<'EOF'
from pathlib import Path
import hashlib
import socket
input_file = Path("/workspace/brief.txt")
data = input_file.read_bytes()
print("Input bytes:", len(data))
print("SHA256:", hashlib.sha256(data).hexdigest())
try:
Path("/should-not-work.txt").write_text("escape attempt")
print("Unexpected: root filesystem was writable")
except OSError as exc:
print("Root filesystem write blocked:", type(exc).__name__)
try:
socket.create_connection(("example.com", 80), timeout=2)
print("Unexpected: outbound network was available")
except OSError as exc:
print("Outbound network blocked:", type(exc).__name__)
EOF
cat > workspace/brief.txt <<'EOF'
Summarize this repository without accessing the public internet.
EOF
docker build -t agent-sandbox-demo .
docker run --rm \
--network none \
--read-only \
--tmpfs /tmp:rw,noexec,nosuid,size=64m \
--cap-drop ALL \
--security-opt no-new-privileges \
--pids-limit 64 \
--memory 256m \
--cpus 0.5 \
--mount type=bind,src="$PWD/workspace",dst=/workspace,readonly \
agent-sandbox-demo
正常情况下,程序可以读取明确挂载的输入文件,但无法写入容器根文件系统,也无法访问公网。这个示例仍然不是完整的生产沙箱:它没有任务超时、细粒度出网白名单、短期凭证、镜像签名验证、审计日志或更强的内核隔离。
如果要为未来的开放接口设计一层适配器,可以先在自己的系统中使用声明式策略。下面只是概念配置,并非官方 Sandbox Kit schema:
apiVersion: internal.example/v1
kind: AgentSandbox
metadata:
name: repository-review
spec:
image: registry.example.com/reviewer@sha256:REPLACE_WITH_DIGEST
timeoutSeconds: 300
resources:
cpu: "500m"
memory: "256Mi"
maxProcesses: 64
filesystem:
rootReadOnly: true
mounts:
- source: ./workspace
target: /workspace
mode: readOnly
network:
default: deny
allow: []
credentials:
inject: []
outputs:
maxBytes: 10485760
关键点不是字段名称,而是把权限作为任务的一部分显式声明。执行后端无论是本地 Docker、托管沙箱还是其他隔离运行时,都应根据同一份策略拒绝超额权限,而不是让 Agent 自己决定需要什么。
接入前应该验证的边界
采用任何 Agent 沙箱方案前,可以用下面的清单做一次威胁建模:
- 默认拒绝网络,只为确有需要的域名和端口开放出站访问。
- 不挂载 Docker Socket、宿主机根目录、SSH 目录或云平台长期凭证。
- 使用不可变镜像摘要,而不是可漂移的标签。
- 为每个任务设置 CPU、内存、进程数、磁盘和执行时间上限。
- 让输入只读、输出单独挂载,并限制输出体积。
- 使用一次性任务环境,完成或超时后立即销毁。
- 记录命令、镜像、策略、网络请求和产物,但避免把秘密写入日志。
- 测试逃逸、资源耗尽、提示注入和供应链污染,而不只是正常流程。
- 确认底层隔离模型是否满足自身风险等级;高风险代码可能需要虚拟机、微虚拟机或其他强化运行时。
Docker 的这次动作值得关注,不只是因为多了一个运行 Agent 的云产品,而是因为它试图把沙箱能力变成开放、可移植的基础设施接口。对开发团队而言,稳妥的采用路径是:先定义自己的最小权限策略和审计要求,再评估不同后端能否满足这些约束,最后才决定把哪些 Agent 任务交给云端沙箱。不要信任 Agent,但可以信任经过验证的边界。