Docker Sandboxes 用 microVM 隔离 AI 编程代理,但沙箱内行为无法审计
Docker 发布 Docker Sandboxes,使用 microVM 隔离 AI 编程代理,但沙箱本身无法提供沙箱…
Docker 近日正式发布 Docker Sandboxes,将 Claude Code、Codex CLI、Copilot CLI、Kiro、OpenCode 等 AI 编程代理运行在专用 microVM 中,借助自研的跨平台 VMM 同时支持 macOS、Windows 与 Linux。每个沙箱拥有独立内核、挂载的工作区以及「只允许特定域名」的网络策略,工作区直接挂在宿主机文件系统上,会话期间实时同步;沙箱状态在重启后会保留,仅在显式删除时丢弃。
容器为何长期不够
在此之前,社区常见做法是把代理放进 Docker 容器:只挂载项目目录、任务完成后删除容器。这看起来很干净,但有一个根本问题——Docker 容器与宿主机共享内核,命名空间与 cgroups 只能提供逻辑隔离,攻击者一旦突破内核边界就能影响宿主。历史上已多次出现容器逃逸类 CVE:2019 年的 runc 覆写漏洞(CVE-2019-5736)、2022 年的 cgroup 逃逸(CVE-2022-0492)、2024 年 runc 再次曝出漏洞(CVE-2024-21626)。对于可能通过 prompt injection 被操控的 AI 代理而言,这种边界并不值得默认信任。
Firecracker microVM 改变了风险结构。每个沙箱运行独立的 Linux 内核,并通过 KVM 与宿主机硬件隔离。即便 guest 内核出现 bug,也不应直接变成宿主内核 bug——这正是 AWS Lambda、Fly.io 等处理不可信客户代码时所采用的基础隔离模型。
| 隔离模型 | 共享宿主内核 | 硬件级边界 | 启动时间 |
|---|---|---|---|
| Docker 容器 | 是 | 否 | 约 50 ms |
| gVisor | 否(用户态内核) | 否 | 约 100 ms |
| Firecracker microVM | 否 | 是(KVM) | 约 125 ms |
| 完整 VM | 否 | 是 | 2–5 s |
隔离原语选对了,但问题出在边界守住之后。
沙箱能挡住的攻击面
在网络策略配合下,microVM 沙箱可显著收窄以下几类风险:
- 宿主文件系统访问:代理只能看到并写入显式挂载的项目工作区,无法读取
/.ssh/、/.aws/credentials、shell 历史等宿主机文件。 - 宿主进程访问:代理看不到宿主进程,也无法 attach 调试器、终止 VPN 客户端或干扰其他运行中的代理。
- 横向网络移动:采用「默认拒绝 + 白名单」策略后,代理无法访问内网、云元数据接口(169.254.169.254)或未批准的网络资源,只能与白名单内的域名通信。
- 销毁时的 VM 层清理:显式销毁沙箱后,VM 内安装的包、shell 历史与工作区之外的文件都会被丢弃。工作区是 live mount,代理在整个会话期间直接读写宿主机文件,而非副本。
这些控制对无人值守场景尤其重要,例如夜间重构、CI 代码评审代理、自主测试生成等任务。
沙箱挡不住的部分
隔离边界只是 microVM 周界,周界以内仍是一台忙碌的真实机器。
- 缺少对代理行为的审计轨迹:代理读文件、写文件、执行 shell 命令、发起网络连接,沙箱本身并不会在 agent 自己的 session log 之外留下结构化记录。这份日志位于沙箱内、由代理进程控制,如果代理在会话结束前自行删除,记录也就消失了。
- 代理仍可破坏项目:被 prompt injection 的代理可以删除工作区、覆盖配置,在凭证被挂载的情况下 push 到 git 远程仓库,或把源码外发到白名单内的域名。沙箱阻止了它跳出宿主机,但并未阻止它滥用被授予的访问权。
- 网络白名单粒度偏粗:实际开发中往往需要允许 api.github.com、registry.npmjs.org、pypi.org 等域名,这意味着一旦某个安装包或远端被污染,就存在合法的出站通道。白名单挡住的是随机攻击者基础设施,而非合法通道本身的滥用。
- 事后难以重建现场:沙箱会话一旦产生异常输出、删除文件或提交可疑代码,你拿不到内核级记录可供审计。代理的 session log(如果存在且未被篡改)只能告诉你模型的意图,无法告诉你系统在 syscall 层实际执行了什么。
这就是 Docker Sandboxes 当前的盲区:即便隔离机制完美工作,事后仍难以解释到底发生了什么。
eBPF 能看到的,以及看不到的
eBPF 允许在内核事件(如 syscall 进出、网络连接、文件系统操作)上挂载小程序。Cilium Tetragon、Falco 等工具正是基于此生成进程行为的结构化事件。对于容器场景,由于共享宿主内核,宿主机上运行的 Tetragon 或 Falco 可直接看到代理的每一次 open()、read()、write()、unlink() 调用及相关参数;而在 microVM 场景下,KVM 硬件边界会阻断宿主侧的 kprobe,宿主看不到 guest 路径、PID 或 argv,eBPF 必须在 guest 内部运行。
换言之,eBPF 并不能完全弥补 microVM 沙箱的审计盲点:它要么仍依赖容器共享内核,要么必须深入 VM 内部重新部署。无论哪种路径,单纯的「把代理关进 microVM」都还不足以解决 AI 代理运行时的可观测性问题。
