深度解读

Agent 运行环境 Sandbox:从本机权限到 microVM 的技术实现

拆解 Coding Agent 与执行型 Agent 的沙箱边界,覆盖文件系统、网络、系统调用、资源限制、gVisor、Firecracker 和 WASI 的落地取舍。

CONVEE Research · 阅读时间 4 分钟 · 发布于 2026-06-13

#核心结论

Agent 运行环境的 sandbox 不是单点能力,而是一组分层控制:模型侧权限策略决定“是否允许发起动作”,操作系统或虚拟化边界决定“动作真正能碰到什么”,网络代理和凭据代理决定“能把数据发到哪里、以什么身份发”,审计与审批系统决定“出了问题能否复盘和接管”。对 AI 全栈架构师来说,关键不是问“用了 Docker 没有”,而是把 Agent 的读、写、联网、执行、密钥、资源和审计边界做成一个可验证的运行时控制面。

OpenAI Codex 和 Claude Code 的本地沙箱都体现了同一个方向:默认让 Agent 在工作区内自主执行低风险命令,把联网、越界写入和高风险动作交给审批。区别在于不同系统选择的 OS 原语不同。Codex 文档明确区分 sandbox mode 与 approval policy;Claude Code 的 Bash sandbox 则强调把 shell 命令及其子进程限制在文件和网络边界内。真正进入 SaaS 多租户或不可信代码执行场景时,单纯本机进程沙箱通常不够,需要 gVisor 这类用户态内核或 Firecracker 这类 microVM 承担更强隔离。

#威胁模型

Agent sandbox 要防的对象不是传统意义上的“用户上传恶意二进制”一种情况,而是几类叠加风险。

第一类是提示注入后的越权执行。模型可能被仓库里的文档、网页、日志或测试输出诱导,去读取敏感文件、改写代码、提交密钥、安装恶意依赖或访问内网地址。第二类是工具链供应链风险。npm installpip install、测试脚本、构建脚本和 Git hooks 都可能执行任意代码,Agent 一旦自动运行它们,就等于把本地权限交给了项目依赖。第三类是资源耗尽。死循环、fork bomb、海量日志、无限写盘、GPU 占满和长时间网络下载都会拖垮宿主环境。第四类是数据外泄。只限制文件写入没有意义,如果 Agent 能读到密钥并联网,数据仍然可以被发走。

因此 sandbox 的目标要拆成四个问题:它能读哪些路径,能写哪些路径,能连接哪些网络,能消耗多少资源。审批系统再回答第五个问题:什么时候必须停下来等人确认。

#本机 Agent 的边界模型

本机 Coding Agent 最常见的边界是“工作区可写、工作区外只读或不可见、网络默认关闭、越界动作需要审批”。这个模型的价值是低摩擦:Agent 可以跑测试、改文件、读代码、生成补丁,但不会默认访问浏览器 cookie、SSH key、云凭据和用户主目录里的其他项目。

一个合理的本机执行链路可以这样设计:

LLM planner
  -> permission policy: classify read / write / network / destructive action
  -> command broker: create sandboxed process
  -> OS sandbox: filesystem, process, syscall and network limits
  -> proxy / credential broker: domain allowlist and short-lived tokens
  -> audit log: prompt, command, cwd, policy version, exit code, diff

这里最容易被忽略的是 command broker。Agent 不应该直接把模型生成的 shell 字符串交给宿主 shell,而是由 broker 统一设置工作目录、环境变量、超时、输出上限、进程组、sandbox profile 和审计字段。所有子进程必须继承同一套限制,否则测试脚本、包管理器或构建工具会成为逃逸路径。

#Linux 原语:namespace、cgroup、seccomp 与 LSM

Linux 上的轻量 sandbox 通常由四类内核能力组合而成。

典型技术 作用 Agent 里的用法
命名空间 user、mount、pid、network、ipc、uts namespace 隔离用户、文件系统视图、进程树和网络栈 让沙箱内看见独立根目录、独立进程树和受控网络
资源控制 cgroups v2、rlimit 限制 CPU、内存、进程数、I/O 和运行时间 防止测试、构建、恶意脚本耗尽宿主资源
系统调用过滤 seccomp-BPF 缩小能调用的内核接口集合 禁止高风险 syscall,降低内核攻击面
强制访问控制 Landlock、AppArmor、SELinux 以策略限制文件、网络、能力和对象访问 给进程再加一层路径和权限规则

seccomp 需要特别谨慎理解。Linux 官方文档明确指出,系统调用过滤本身不是完整 sandbox;它只是减少暴露给进程的内核面。原因很简单:被允许的 syscall 仍然可能触发漏洞,文件和网络的信息流也不是 seccomp 单独能表达清楚的。所以生产级 Agent 不能只说“我用了 seccomp”,还要说明 namespace、cgroup、capability、LSM 和网络策略如何组合。

no_new_privs 也是关键开关。它可以让进程在 execve 后不能通过 setuid、setgid 或文件 capability 获得额外权限,并且常用于让非特权进程安全安装 seccomp filter。对 Agent 来说,任何会执行仓库脚本的沙箱都应默认关闭权限提升路径。

#macOS 与 Windows 的本机实现

macOS 通常依赖 Seatbelt/App Sandbox 思路:用系统级 sandbox profile 限制文件、网络和系统服务访问。Codex 文档说明 macOS 本地沙箱使用内置 Seatbelt 框架;Claude Code 文档也说明 macOS 无需额外安装即可使用内置 sandbox。工程上要注意,Seatbelt 对部分 CLI、证书链、网络代理和文件访问语义会有兼容问题,所以需要有明确的 excluded command 策略,但这个例外列表必须很窄。

Windows 的对应能力是 AppContainer、Job Objects、Windows Filtering Platform 和相关访问令牌机制。Microsoft 文档把 AppContainer 描述为应用隔离环境,可以限制文件、注册表、网络、进程和窗口交互。对 Agent 来说,Windows 沙箱要同时关注两件事:文件写入是否被限制在工作目录,网络是否能默认阻断并按域名或能力放行。只靠普通用户权限并不够,因为用户本身往往能读到大量个人文件和开发凭据。

#网络隔离:不要只做文件沙箱

Agent sandbox 的数据泄露风险通常发生在“可读加可联网”的组合上。一个只限制写入的沙箱,如果仍能读取 .env、SSH key、云 CLI 配置或浏览器缓存,并且可以自由访问公网,那么它仍然可以外传数据。

推荐的网络模型是默认 deny,再通过代理放行:

sandboxed process
  -> loopback egress blocked by default
  -> metadata IP blocked by default
  -> private CIDR blocked by default
  -> HTTP/SOCKS proxy
  -> domain allowlist, TLS inspection if required, audit log

本地开发场景可以按命令请求临时授权,例如包管理器访问 registry、Git 访问 GitHub、测试访问指定服务。企业或云端场景应把放行粒度从“是否联网”细化到域名、端口、协议、时间窗口和用途。还要显式封锁云 metadata 地址、Kubernetes service account token、内网管理面和本机敏感端口,否则 Agent 很容易从构建任务升级成内部网络探测器。

#容器不是完整答案

Docker/containerd 这类容器本质上共享宿主内核,主要依赖 namespace、cgroup、capability、seccomp 和 LSM 做隔离。对可信团队内部任务,这个强度通常够用;对多租户不可信代码,它不是最强边界。Kubernetes 文档也建议,在需要更高隔离时考虑 gVisor 这类 sandbox,而不是只依赖自定义 seccomp profile。

容器方案最常见的错误有四个:把 Docker socket 挂进去,把宿主 home 目录整块挂进去,把云凭据放进环境变量,以及用 privileged container 解决兼容性问题。只要挂了 Docker socket,容器内进程基本就能控制宿主容器运行时;只要开了 privileged,很多 namespace、seccomp、AppArmor/SELinux 约束都会被削弱或绕过。Agent 执行环境里,这些都应该被视为高风险例外,而不是默认配置。

#gVisor:用户态内核拦截 syscall

gVisor 的思路是用一个用户态内核 Sentry 来实现大部分 Linux 系统调用,应用看到的是近似 Linux 的 API,但不会直接把大量 syscall 打到宿主内核。每个 sandbox 有独立的 Sentry,文件访问由 Gofer 进程代理。gVisor 官方安全文档强调,它的目标是限制宿主内核暴露面,同时保持大多数容器应用可运行。

这类方案适合需要比普通容器更强隔离、但又希望继续使用 OCI 镜像和 Kubernetes 调度体验的 Agent 平台。代价是兼容性和性能:某些 syscall、内核特性、FUSE、eBPF、特权操作、低层网络或硬件访问可能不可用;系统调用密集型任务会有额外开销。对 Coding Agent 来说,gVisor 很适合跑测试、构建、语言工具链和普通服务,但不适合需要特权容器、内核模块或复杂硬件直通的任务。

#Firecracker:用 microVM 做强隔离

Firecracker 是面向 serverless 和多租户场景的轻量 VMM,基于 KVM 启动 microVM。和普通容器相比,每个 microVM 有自己的 guest kernel,隔离边界从“共享宿主内核”提升到“硬件虚拟化边界”。Firecracker 设计文档强调极简设备模型和高密度启动;NSDI 论文还说明 jailer 会在启动 guest 前把 VMM 自身放进 chroot、PID/network namespace、降权和 seccomp-BPF 组合沙箱里。

对 Agent SaaS 来说,Firecracker 的典型生命周期是:

template image
  -> snapshot / rootfs clone
  -> microVM boot
  -> inject workspace and task config
  -> run agent command under cgroup and network policy
  -> stream logs, artifacts and diff
  -> destroy VM or keep warm for short session

这种架构适合运行不可信代码、第三方仓库、用户上传脚本和需要强多租户隔离的自动化任务。代价是平台复杂度更高:要管理镜像、快照、内核、网络、磁盘、启动池、日志采集、VM 回收和漏洞补丁。它不是“更安全的 Docker 命令”,而是一套完整执行平台。

#WASI:能力模型最干净,但不是完整 Linux

Wasm/WASI 的安全模型和 POSIX 很不一样。WASI 应用默认没有 ambient authority,不能凭全局用户身份随便打开文件或访问网络,只能使用宿主显式传入的 capability。Wasmtime 文档也强调 WebAssembly 的线性内存、受控分支和导入模型天然提供了较强沙箱基础。

这非常适合插件、策略函数、数据转换、小型工具和可验证扩展。例如让 Agent 调用一个用户上传的数据清洗函数,WASI 比容器更容易表达“只给这个输入文件句柄和这个输出目录句柄”。但 WASI 不适合作为通用 Coding Agent 的唯一执行环境,因为它不能无缝承载完整 Linux shell、包管理器、数据库服务、浏览器测试和大多数原生构建链。

#Agent 平台的推荐分层

风险等级 推荐边界 适用场景 关键控制
本机 OS sandbox 自己的可信仓库、本地 Coding Agent 工作区写入、网络审批、命令超时、审计
rootless container + LSM + egress proxy 内部 CI、团队共享 Agent、可控仓库 镜像基线、无 Docker socket、资源配额、域名 allowlist
中高 gVisor / Kata 多租户容器任务、第三方依赖较多的构建 用户态内核或轻 VM、Kubernetes 集成、兼容性测试
Firecracker microVM SaaS 执行用户代码、不可信仓库、长期自动化 独立 guest kernel、短期凭据、默认离线、销毁式会话
专用 Wasm/WASI 插件、策略函数、数据转换 capability 传参、无 ambient authority、宿主 API 审计

真正落地时可以组合使用。例如本地开发使用 Seatbelt 或 bubblewrap;云端普通任务用 gVisor;高风险用户代码用 Firecracker;用户插件用 WASI。不要试图让一种 sandbox 覆盖所有场景。

#凭据与密钥设计

Agent 运行环境最危险的不是模型会犯错,而是它拿到了过宽的身份。正确做法是让 sandbox 内部尽量没有长期密钥,需要访问外部系统时通过 credential broker 申请短期、最小权限、可撤销的凭据。凭据签发应绑定任务 ID、工具名、目标资源、过期时间、审批记录和策略版本。

例如部署工具不应该直接读取个人 SSH key,而应该由 broker 在审批通过后签发一次性部署令牌,且只允许访问目标仓库、目标环境和目标时间窗。数据库工具不应该拿全库管理员密码,而应该拿只读、限表、限行数或只允许调用存储过程的凭据。这样即使 Agent 被提示注入影响,攻击者也只能拿到被策略压缩过的能力。

#可观测与审计

Sandbox 不能只在失败时返回一句“权限不足”。生产 Agent 需要保留一条可回放记录:模型请求、上下文摘要、工具列表、命令、cwd、环境变量白名单、sandbox profile、网络请求、资源用量、审批结果、文件 diff、退出码和错误输出。对于被拒绝的动作,也要记录拒绝原因和命中的策略。

建议把审计字段拆成三层:

  1. 策略层:sandbox mode、approval policy、network allowlist、credential scope、policy version。
  2. 执行层:command、argv、cwd、uid/gid、namespace/container/vm id、timeout、resource limit。
  3. 结果层:exit code、stdout/stderr 摘要、文件变更、网络目标、审批人、artifact。

这些记录不仅用于安全复盘,也用于评测 Agent 是否频繁撞权限、是否总在同类任务上超时、是否需要改工具边界。

#实施检查清单

  1. 所有 Agent 命令是否经过统一 command broker,而不是直接裸跑 shell。
  2. 工作区外路径是否默认不可写,敏感目录是否默认不可读。
  3. 网络是否默认关闭或走代理,metadata、内网和 localhost 敏感端口是否被阻断。
  4. 是否设置 CPU、内存、进程数、磁盘、输出大小和总运行时间上限。
  5. seccomp、capability、no_new_privs、LSM 是否组合使用,而不是只依赖单一机制。
  6. 包管理器、构建脚本、Git hooks 和测试脚本是否被视为不可信代码执行。
  7. Docker socket、privileged container、宿主 home 目录和长期云凭据是否被明确禁止。
  8. 高风险动作是否需要人工审批,并把审批记录写入同一条 trace。
  9. 云端多租户是否使用 gVisor、Kata 或 microVM,而不是只靠普通容器。
  10. Sandbox 失败、超时、拒绝和资源耗尽是否能被清楚观测和回放。

#采用建议

如果是在个人机器上使用 Coding Agent,先采用本机 OS sandbox 加审批策略,重点保护工作区外文件、网络和密钥。如果是在公司内部推广 Agent,优先建立统一 command broker、网络代理和凭据代理,不要让每个团队自己拼 shell 执行器。如果是对外提供 Agent 执行平台,直接按多租户不可信代码设计,优先评估 Firecracker 或 gVisor,并把镜像、快照、网络、审计和回收流程纳入平台工程。

判断一个 Agent sandbox 是否合格,不看宣传里用了多少安全名词,而看它能否稳定回答五个问题:这次任务能读什么,能写什么,能连哪里,能拿什么身份,出了问题能否完整复盘。

证据来源

修订记录

最近修订:2026-06-13。CONVEE 在原始证据或架构判断变化时更新本文。

相关内容

返回Agent专题