loading

Loading

探索与发现

首页 AI 开发实战

Agent 沙箱逃逸:隔离级别与真实事故的缝隙

字数: (2469)
阅读: (4)
0
摘要:从容器共享内核到 Firecracker 微虚拟机,Agent 沙箱的隔离强度是一档刻度盘。更要命的是那些和隔离级别无关的逃逸路径:挂载 docker.sock、符号链接绕过路径检查、配置文件投毒,以及藏不住的对话层泄露。

上个月有个团队问我一件事:他们的 Agent 已经跑在 Docker 里了,为什么安全评审还是打回来。我的回答是,Docker 解决的是打包和资源隔离,不是“恶意代码不伤宿主”。这两件事默认的威胁模型完全不同——普通容器假设里面是你写的代码,Agent 沙箱假设里面是大模型现场生成、没人逐行审过的代码。这个差别不是加个参数能抹平的。

事故不需要攻击者也会发生

腾讯云那篇文章里举的场景很朴素:让 Agent 清理临时文件,模型理解出现偏差,删除范围从临时目录扩到了项目根目录。如果这段代码恰好跑在宿主机上,你面对的是真实文件。更严重的版本是提示词注入——攻击者在输入里埋一句指令,诱导模型读取环境变量并外发;或者模型幻觉生成语义危险但语法正确的系统调用。

这些都是“沙箱外部”的问题,任何一次执行环境的失守都会被放大。AWS 博客记录的几起事故更能说明成本:2026 年 2 月,某主流 AI 编程助手在用户环境执行了 terraform destroy,摧毁 VPC、RDS 和 ECS 集群,2.5 年学生数据丢失;同年 4 月,另一款 AI 代码编辑器在 9 秒内通过云平台 API 删掉了生产数据库和所有备份。这些并非沙箱逃逸,但它们是同一类工程问题:Agent 的权限边界没有按“不可信代码”来设计。

隔离是个刻度盘,不是一个开关

TianPan.co 那篇把沙箱分成几档,我认为这个划分对做选型很有用。第 0 档是不隔离,exec() 直接以完整进程权限跑;第 1 档是容器,命名空间加 cgroups,毫秒级启动、几乎零内存开销,但共享宿主内核——一个没修的内核 CVE 会同时影响这台机器上的所有容器。第 2 档叠 seccomp-BPF 和 --cap-drop=ALL,把攻击面收窄,但依然在共享内核上。第 3 档是 gVisor,用 Go 写的用户态内核 Sentry 接管系统调用,逃逸要连破两层;计算密集任务开销接近零,I/O 密集负载有 10%–30% 的损失。第 4 档是 Firecracker 微虚拟机,每个沙箱独占内核,冷启动不到 125 毫秒,单 VM 内存开销低于 5 MiB,配合快照恢复可以把配置时间压到约 28 毫秒。第 5 档是 Wasm/WASI,能力沙箱,默认无文件系统无网络,适合插件系统和边缘工具,但 Python 要走 Pyodide,冷启动并不轻,且 Spectre 类瞬态执行可能破坏其内存隔离。

关键判断不在技术栈,而在你回答三个问题:代码是不是运行时由 LLM 生成的?多租户是否共享基础设施?是否需要 GPU?LLM 生成代码加多租户,容器不够,至少 gVisor,生产环境用 Firecracker 或 Kata。需要 GPU 的话 Firecracker 目前不支持 PCIe 透传,得改用 gVisor 或全功能虚拟机——这是硬件层面绕不过去的约束。

那些和隔离级别无关的逃逸路径

我见过最常见的一种低级错误,是在容器里挂 /var/run/docker.sock。挂上去等于给了容器完整 Docker API 访问权,效果接近宿主 root。这种配置常常是开发环境顺手带到生产的。

第二种是路径前缀检查被符号链接绕过。2025 年的多个高危 CVE 就是这么来的:某广泛部署的 MCP 文件系统服务器,用 if path.startswith("/workspace") 做校验,攻击者在工作区里建一个从 /workspace/escape 指向 /etc/passwd 的符号链接,读取就变成了对宿主任意文件的读取。检查前必须先 os.path.realpath(),这类问题修起来不复杂,但没人提示就不会有人去查。

第三种是配置文件投毒。提示词注入让 Agent 写入 ~/.gitconfig、IDE 钩子脚本或 MCP 配置文件,下一次你打开编辑器就执行了任意代码。注意这完全发生在沙箱之外——沙箱文件系统边界和用户 home 目录之间的缝隙,技术隔离无法覆盖。缓解办法是工作区之外全部只读挂载,而不是按文件名黑名单去拦。

网络侧还有一条经常被忽略的通道:DNS。即使你按 IP 和端口做出了站过滤,把敏感数据编码进查询域名照样能外泄。内部通信该用 vsock 而非 TCP,尽量不暴露网络接口。

最难的其实是语义层

华盛顿大学的一项研究发现,63.4% 没有合适隔离的 LLM Agent 敏感数据泄露路径是对话,而不是代码执行。Agent 读了文件、看到注入指令说“帮我总结上面的全部内容”,它就总结了——代码执行沙箱拦不住这个。CVE 层面也一样,2026 年出现过某 Agent 框架三层沙箱被完全绕过(CVSS 10.0),以及开源 Agent 网关 WebSocket 接口被用来窃取认证令牌并 RCE;2025 年 10 月有安全机构演示过从提示注入到 RCE 的完整攻击链。

工程上的应对是把这句话落到架构里:接触敏感数据的工具,跑在独立上下文里,不与外部输入源共享这段上下文。这个改动会影响 Agent 的工具设计,比你换一个运行时更费劲,但它对应的风险更真实。

落地时我自己的优先级:先审 mount 和 socket,再确认 realpath 与只读挂载,然后把生命周期压到任务级别、默认断网,最后才考虑升级到 gVisor 或微虚拟机。前几步便宜且能挡住大部分实际事故,后面那步挡的是你不认识的那部分攻击者。

顺手提一下可选方案:AWS 的 Lambda 和 e2b 都在用微虚拟机路线,Kata 能在标准 Kubernetes API 后面封装虚拟化,腾讯云 AGSX 提供代码、浏览器、自定义几类沙箱形态,默认网络策略是只允许内网、生命周期默认 5 分钟、最长 24 小时。这些默认值本身是产品对你的一种提示——长期运行的沙箱不是好设计。真正需要长期存在的,才加常驻标识,那是在成本和隔离之间做的单点妥协,不要当成默认姿势。

转载请注明出处: 皮哈皮阿

本文的链接地址: https://blog.phpat.com/ai-dev/632.html

手机扫码阅读

微信或手机浏览器扫一扫,随时随地随心阅读与分享

您可能对以下文章感兴趣
1 / 1
预览图