Skip to content

AI沙箱:原理与选型

最近有一些沙箱的需求,但是目前我个人对沙箱的了解还不咋深入,因此系统性的学习一下,方便后续进行进一步选型或者实现

1、定义、问题与威胁模型

在本文中,AI沙箱指的是一类受控执行环境:模型或Agent可以在其中执行代码、读写文件、访问网络、操作浏览器或者保存中间状态,但是这些操作被限制在明确的权限边界内

Agent一旦拿到工具,就不再只是生成文本,它可能会执行Python、Shell、其他命令,安装依赖、启动服务、修改文件、读取文件、访问公网接口,或者利用浏览器登陆网站、填写表单等,每一类动作都可能把风险从模型输出扩展到真实系统

沙箱的目的不是保证代码绝对安全,更准确的目标是限制损害范围,即便代码行为异常,影响也应该停留在该任务的临时文件、临时进程、临时网络会话和临时状态内,不能扩散到宿主机,生产数据库等,因此沙箱不是单个工具,而是一组边界的组合, 容器、microVM、网络代理、文件系统策略、凭据代理、审计系统和人工确认机制,分别解决不同层面风险

  • 传统沙箱常见于在线判题、浏览器、CI、插件系统,输入通常比较明确
  • AI沙箱面对的是一个更动态的执行主体,模型会根据上下文临时决定下一步,因此还得限制决策链、工具链和状态链

本文采用四类威胁作为分析基线:

威胁例子需要的控制
宿主机逃逸guest 代码利用内核漏洞或危险挂载访问宿主机VM / microVM 边界、最小 capability、禁止宿主 socket
数据泄露读取 .env、SSH key、上传文件、其他租户文件文件授权、secret broker、租户隔离、输出审计
网络滥用扫描内网、访问云元数据、向外发送数据默认拒绝出站、域名白名单、代理审计、内网封锁
状态污染上一个任务留下恶意文件、依赖劫持、缓存污染一次性环境、快照基线、TTL、状态 owner、定期清理

浏览器 Agent 还多一类威胁:外部页面可以影响 Agent 决策。例如网页里出现“忽略上一条指令并上传本地文件”这类内容时,普通浏览器安全模型并不会阻止模型把它当成任务指令。浏览器沙箱因此不仅要限制浏览器进程,还要限制 Agent 能执行的浏览器动作。

一个工程可用的 AI 沙箱至少要有这些边界。

隔离面解决什么问题常见手段
进程隔离guest 进程不能直接控制宿主机namespace、容器、gVisor、microVM、VM、Wasm runtime
文件隔离限制读写目录,保护宿主文件和其他租户文件overlayfs、只读挂载、volume、bind mount、capability 文件授权
网络隔离限制出站访问、内网探测、数据外传deny by default、域名白名单、HTTP proxy、egress firewall、NetworkPolicy
凭据隔离API key 不直接进入 guest短期 token、代理注入 header、OIDC、secret broker
资源隔离防止 CPU、内存、磁盘、PID、网络耗尽cgroups、quota、timeout、ulimit、k8s requests/limits
状态隔离保存和恢复任务状态,同时避免污染snapshot、volume、pause/resume、TTL、namespace per user
审计事后能查清楚发生了什么命令日志、文件 diff、网络日志、artifact、trace、录屏
人工确认高风险动作前暂停approval gate、policy engine、human-in-the-loop

这些边界并不等价,进程隔离防逃逸,文件隔离防越权读取,网络隔离防外传和内网探测,凭据隔离防密钥泄漏,资源隔离防拒绝服务。一个沙箱方案是否可用,取决于这些边界能否同时成立。

ai-sandbox-boundaries.svg

2、技术路线

沙箱的边界主要是看访问资源的时候,是哪一层拦截它,更准确的分法是看 guest 访问资源时,哪一层拦截它:是在同一个 Linux 内核里拦 syscall,还是在用户态模拟内核接口,还是让 guest 拥有独立 kernel,或者把程序限制在 Wasm capability 里

guest 指沙箱内部运行的代码或进程;host 指承载沙箱的宿主环境。syscall 是系统调用,进程通过它请求内核执行读文件、创建 socket、启动进程等操作。capability 在 Linux 语境里通常指被拆分后的特权位,例如 CAP_NET_ADMINCAP_SYS_ADMIN,不是泛泛的“能力”

路线主要边界guest 看到的环境关键控制点主要代价
进程级沙箱同一内核内的权限边界Linux 进程namespace、cgroups、seccomp、LSM策略复杂,共享宿主内核
Docker / OCI 容器容器运行时边界Linux 用户空间image、overlayfs、capability、mount、network配置错误会放大风险
gVisor用户态内核边界类 Linux 环境Sentry、Gofer、syscall interception兼容性和 syscall 性能
microVM虚拟机边界独立 Linux kernelKVM、VMM、virtio、rootfs、snapshot调度、镜像、网络更复杂
Wasm / WASI能力授权边界Wasm runtimeimport/export、preopen dir、capability不适合完整 Linux 工程
k8s 编排生命周期和调度边界Pod / Job / namespaceRuntimeClass、NetworkPolicy、Quota、Admission本身不提供强执行隔离

对 AI 沙箱来说,最容易犯的错是把“能启动隔离环境”当成“已经隔离”。真正的判断点在访问路径上:guest 执行一条命令、读取一个文件、发出一个网络请求、使用一个 secret 时,中间经过哪些策略点;这些策略点是否在 guest 之外;策略失败时能否默认拒绝。

ai-sandbox-isolation-routes.svg

2.1、进程级沙箱

进程级沙箱通常直接使用 Linux 内核能力:

  • namespaces 隔离 PID、mount、network、user、IPC 等视图
  • cgroups 限制 CPU、内存、IO、PID
  • seccomp 限制 syscall
  • AppArmor / SELinux / Landlock 限制文件和权限
  • ulimit 限制进程资源

namespace 是 Linux 的视图隔离机制,让进程看到独立的进程树、挂载点、网络栈或用户 ID 映射。cgroups 是资源控制机制,用来限制 CPU、内存、IO、PID 数量等。seccomp 是系统调用过滤机制,可以限制进程能调用哪些 syscall。LSM 指 Linux Security Modules,AppArmor、SELinux、Landlock 都属于这一类访问控制思路的实现。

它的原理是“让同一台机器上的进程看到不同的世界”。PID namespace 让进程只能看到自己的进程树;mount namespace 让它看到一套单独的文件系统挂载;network namespace 让它有独立网卡、路由表和端口空间;user namespace 可以把 guest 里的 root 映射成宿主机上的非特权用户。cgroups 管资源,seccomp 管 syscall,LSM 管更细的访问策略。

这种路线的优势是启动快,开销低,适合本机工具保护、插件执行和短任务。它的工程吸引力也很明显:不需要完整 VM 镜像,不需要单独 kernel,毫秒级拉起一个进程就能工作。

限制也很清楚:它和宿主共享内核。策略写错、内核漏洞、挂载过宽、capability 放太多,都可能扩大风险。因此,进程级沙箱更适合作为防护层之一,而不适合作为强多租户边界。

2.2、Docker/OCI容器

Docker / OCI 容器是最常用的工程形态。Docker 官方把容器安全拆成 kernel namespaces、cgroups、daemon 攻击面、Linux capabilities 等部分。Docker 运行文档也明确说,容器默认可写层是临时的,删除容器会删除这部分数据;要保存数据,需要 volume 或 bind mount。

容器把进程级隔离包装成可分发的运行单元。镜像提供 root filesystem,overlayfs 给容器一个可写层,runtime 按 OCI spec 创建 namespace、cgroup、mount、capability 和 seccomp profile。容器里的程序看起来像在一台独立机器上运行,实际仍然共享宿主内核。

OCI 是 Open Container Initiative,定义容器镜像和运行时规范。root filesystem 指容器启动后看到的根文件系统。overlayfs 是 Linux 的叠加文件系统,常用于把只读镜像层和容器可写层组合起来。Docker socket 通常是 Docker daemon 的控制入口,guest 一旦拿到它,就可能通过 daemon 间接控制宿主上的容器和镜像。 适合场景:

  • CI
  • 代码评测
  • 短时间执行用户代码
  • Agent 跑测试、构建、lint
  • 自建沙箱的第一版

参考:Docker Engine security
https://docs.docker.com/engine/security/

2.3、 gVisor

gVisor是介于容器和VM之间的一类方案,它提供一个用户态的应用内核Sentry,拦截应用系统调用,应用看到的是类Linux接口,但是很多syscall不会直接打到宿主内核

这里的关键是 syscall 路径,普通容器里的进程发 syscall,最终还是进入宿主 Linux kernel,gVisor 在中间插入 Sentry,guest 进程的很多系统调用先进入 Sentry,由 Sentry 实现一部分 Linux 语义;需要访问文件时,再通过 Gofer 和宿主文件系统交互,这样,guest 对宿主内核的直接接触面会变小。

Sentry 是 gVisor 的用户态内核组件,负责实现大部分 Linux 系统调用语义,Gofer 是 gVisor 中代理文件系统访问的组件

gVisor 官方说明里有几个关键点:

  • 它不是单纯的 syscall filter。
  • 它也不是传统 VM。
  • 它把应用对宿主 System API 的直接访问换成对 Sentry 的访问。
  • 它可以和 Docker、k8s、OCI 工具链集成。

适合场景:

  • 多租户容器执行
  • SaaS 插件
  • 在线 IDE / 判题
  • 比普通容器更需要隔离,但又不想为每个任务开完整 VM 的场景

代价:

  • syscall 密集型程序会慢。
  • Linux 兼容性不如原生容器。
  • 某些内核特性、特殊文件系统、低层网络能力可能受限。

参考:gVisor docs
https://gvisor.dev/docs/

2.4、microVM

microVM是当前很多AI沙箱提供商的主路线,其中Firecracker是代表项目,它使用KVM创建轻量虚拟机,减少设备模型和供给面,比传统VM更快更省内存

microVM的原理更接近“每个任务一台极简虚拟机”, 宿主机通过KVM提供虚拟化能力,VMM负责创建虚拟CPU、内存、块设备和网络设备,guest 启动自己的 kernel 和 rootfs,和传统 VM 相比,microVM 刻意减少设备模型,只保留 virtio block、virtio net、vsock 等必要组件,少给攻击者留下可利用的外设面。

KVM 是 Linux 内核中的虚拟化模块,VMM 是 virtual machine monitor,负责创建和管理虚拟机。virtio 是常见的虚拟设备接口,virtio block 用于块设备,virtio net 用于网络设备。vsock 是宿主和 guest 之间的通信通道。rootfs 是 root filesystem 的缩写。snapshot 是某个时间点的状态副本,通常用于快速启动或回滚

这条路线特别适合 AI Agent,原因不是启动形式新,而是它允许 guest 内部更接近真实开发机:可以安装系统包,可以跑多个进程,可以启动 dev server,甚至可以在 guest 内部再运行 Docker。对宿主来说,guest 的 root 权限仍被挡在虚拟机边界内。换句话说,它把“给 Agent 更多系统能力”和“保护宿主”这两个需求解耦了

microVM 会引入系统工程成本。你要维护镜像、kernel、rootfs、快照、网络 NAT、日志采集、容量调度和回收。只要涉及持久化,还要决定文件系统状态放在哪里:块设备、overlay、网络盘、对象存储还是 snapshot chain。设计不到位时,问题会从隔离转移到运维:冷启动慢、快照膨胀、磁盘泄漏、僵尸 VM、IP 池耗尽

Firecracker 官方描述里提到:

  • 使用 KVM。
  • 面向多租户容器和函数服务。
  • 每个 microVM 有很小的内存开销。
  • 设计目标是快速启动和缩小攻击面。
  • AWS Lambda、Fargate 这类场景推动了它的发展。

microVM 适合 AI 沙箱,因为 Agent 经常需要较高权限。它可能要 sudo apt install,可能要跑 Docker,可能要启动 dev server。普通容器很难同时满足权限够用和宿主安全。放进 microVM 后,guest 内部可以更自由,宿主边界也更清楚。

适合场景:

  • coding agent
  • 长任务开发环境
  • 用户生成代码执行
  • 在线构建和预览
  • 需要 sudo / Docker / FUSE / VPN 等系统能力的任务

代价:

  • 启动和资源开销通常高于容器。
  • 镜像、快照、网络代理、存储挂载更复杂。
  • 需要处理 VM 池化、快照清理、容量调度。

参考:Firecracker
https://firecracker-microvm.github.io/

2.5、Wasm

Wasm 沙箱适合小型、明确边界的代码执行,Wasmtime 的安全文档说,WebAssembly 的目标之一就是安全执行不可信代码,Wasm 代码没有直接 syscall,它只能通过显式 import/export 访问外部能力,WASI 文件访问采用 capability-based security,也就是只给它明确授权的文件或目录

Wasm 的边界和 Linux 沙箱很不一样,Linux 沙箱通常先给程序一个接近完整的 OS 视图,再用策略把危险能力拿掉;Wasm 更像白名单能力模型,模块默认没有文件、网络、时间、随机数、环境变量这些能力,宿主 runtime 通过 import 显式提供,WASI 的 preopen directory 也是这个思路:只把某个目录作为 capability 给进去,模块不能凭路径字符串随意打开宿主其他位置

Wasm 是 WebAssembly,一种可移植的字节码格式。WASI 是 WebAssembly System Interface,给 Wasm 程序提供文件、时钟、随机数等系统接口,import/export 是 Wasm 模块和宿主 runtime 交换函数、内存或对象的方式。preopen directory 指宿主预先授权给 Wasm 程序访问的目录。

这类模型很适合插件。比如一个第三方规则、MCP 小工具、数据转换函数,输入和输出都明确,运行时间短,不需要完整 Linux 用户空间,它不适合直接替代 coding agent 的工作区,因为 npm、apt、浏览器、复杂构建链都假定自己面对的是 POSIX/Linux 环境。

适合场景:

  • 插件系统
  • MCP 工具执行
  • 规则引擎
  • 小函数运行
  • 边缘计算中的用户扩展

不适合场景:

  • 直接跑完整 Linux 工程
  • 需要大量系统包的项目
  • 浏览器自动化
  • 复杂构建链
  • 依赖传统 POSIX 行为的程序

Wasm 的价值在于边界很清楚,你不给它网络,它就没有网络。你不给它目录,它就没有目录。但它不是轻量 VM 的直接替代品。

参考:Wasmtime security
https://docs.wasmtime.dev/security.html

3、生命周期

AI 沙箱的产品差异,很大一部分在生命周期

ai-sandbox-lifecycle.svg

3.1、一次性沙箱

一次性沙箱创建后跑一次任务就销毁 优点:

  • 状态干净
  • 成本好控
  • 不容易留下凭据和恶意文件
  • 适合批任务

缺点:

  • 每次都要装依赖
  • 对多轮调试不友好
  • 不适合长任务

3.2、保温沙箱

保温沙箱会运行一段时间,后续请求复用它。

优点:

  • 降低冷启动
  • 依赖和缓存可复用
  • 交互体验好

缺点:

  • 要处理空闲回收
  • 状态可能污染后续任务
  • 成本更难控

典型场景:Notebook、交互式数据分析、Agent 连续跑测试。

3.3、持久文件系统

持久文件系统允许沙箱停止后保留文件系统状态。下次再启动时,依赖、代码、缓存还在。

优点:

  • 适合长期项目
  • 避免重复安装依赖
  • 支持 coding agent 持续工作

缺点:

  • 文件状态会变脏
  • volume 需要配额和清理
  • 用户隔离和权限管理更复杂

典型场景:远程开发环境、AI coding workspace、长期构建任务。

3.4、 快照

快照保存某个时间点的文件系统状态。新沙箱可以从快照启动。

优点:

  • 复用环境模板
  • 回滚方便
  • 可以在干净基线上分叉多个任务

缺点:

  • 快照版本管理复杂
  • 大快照成本高
  • 快照里可能带入敏感文件

典型场景:预装依赖模板、批量 Agent 任务、课程/实验环境。

3.5、暂停恢复

暂停恢复会保存文件系统和内存。恢复后,进程、变量、服务都回来。E2B 的 persistence 文档明确写到 pause 会保存 filesystem 和 memory,包括 running processes、loaded variables、data。

优点:

  • 长任务体验最好
  • 可以中断后继续
  • 对需要内存状态的 Agent 很有用

缺点:

  • 成本和存储压力更高
  • 内存里可能有 secret
  • 状态污染更难排查
  • 需要严格 TTL

典型场景:长期 Agent、复杂数据分析、浏览器会话、调试中的服务。

参考:E2B persistence
https://e2b.dev/docs/sandbox/persistence

生命周期选择本质上是安全性、成本和体验之间的权衡

任务类型推荐生命周期原因
单次数据分析一次性或短保温输入输出清楚,不需要长期状态
多轮代码修复保温或持久文件系统依赖安装和测试缓存可以复用
长期 coding agent持久文件系统加快照需要保留项目状态,但仍要能回滚
Notebook / 数据实验暂停恢复内存变量和交互状态有价值
不可信用户代码评测一次性清理简单,状态污染最少
浏览器登录任务短期 session登录态有价值,但跨任务复用风险高

4、供应商

供应商 / 项目地区与形态运行边界生命周期能力工具能力适合场景主要限制
E2B海外托管云沙箱文档称为按需创建的安全 Linux VM支持 sandbox 生命周期、persistence、snapshot、volume、pause / resume命令执行、文件读写、后台命令、SSH、interactive terminal、desktop sandbox、VNCcoding agent、数据处理 Agent、浏览器 / 桌面 computer use、需要多轮状态的 SaaS 后端数据出境、网络延迟、合规和成本要单独评估
阿里云 AgentRun / AgentBay Sandbox国内托管交互沙箱公开资料以 AgentBay 口径描述:隔离环境覆盖 Windows、Linux、Android、Web Browser、Code Interpreter论文描述为统一 session,支持 Agent 程序化操作和人类随时接管;具体 TTL、快照、暂停恢复以阿里云正式文档为准MCP、SDK、浏览器 / 桌面 / 代码解释器、人机混合控制国内云上 Agent、需要人工介入的 computer use、网页 / 桌面 / 代码混合任务AgentRun 的公开 API、计费、SLA、网络策略和审计接口需要以实际产品文档为准
Dify Sandbox国内常见开源组件面向 Docker / Linux 的代码执行服务,依赖 libseccomp 等机制限制资源和 syscall更偏一次性代码执行服务,不是长期工作区多语言代码执行,主要服务 Dify workflow 的 Code 节点自建 Dify、工作流代码节点、插件小代码执行不提供完整 Linux 开发环境;多租户隔离强度取决于部署方式;不适合长期 coding workspace
Qwen-Agent Code Interpreter国内模型团队开源框架内置工具文档说明基于本地 Docker container 实现代码解释器跟随本地 Agent 会话,不是托管生命周期产品code_interpreter 内置工具,可让 Agent 写代码、执行代码并返回结果Qwen Agent 原型、内部工具、本地实验、教学 demo依赖本地 Docker;公开文档也提示早期 Python executor 不适合生产;生产环境要自己补网络、文件、凭据和审计边界
自建沙箱:k8s + gVisor / Kata / Firecracker国内私有化部署路线由底层 runtime 决定,k8s 负责调度和生命周期Pod / Job / PVC / snapshot / TTL 都要自己设计命令、文件、网络、artifact、dev server、secret broker 都可自定义数据不能离开内网、合规要求高、需要接入企业权限和审计系统工程成本最高;需要维护镜像、节点池、网络策略、配额、清理、审计和漏洞修复

最后更新于: