更新于

AI 编程 Agent 沙箱设计:怎么让模型放心跑代码


编程 Agent 要真正有用,就得能执行命令、改文件、跑测试——这些动作天然带风险:模型可能因为提示词注入被诱导执行破坏性命令,也可能单纯因为幻觉写出 rm -rf 这种误伤范围过大的操作。沙箱是应对这类风险的核心机制。本文聚焦沙箱本身的执行环境隔离设计:进程、容器、虚拟机怎么选,文件系统和网络边界怎么划。权限审批”改之前要不要问用户”这类交互层设计,可参考 AI Agent 工具权限粒度设计;密钥不落地模型上下文的方案,参考 Agent 工具密钥隔离与最小权限

一、沙箱要隔离的三个层面

设计沙箱前先明确边界要挡住什么。对编程 Agent 来说,风险来自三个方向:

  1. 文件系统越界:Agent 应该只能碰它被授权的目录,不能读写系统文件、其他项目、用户主目录下的敏感文件
  2. 网络越界:命令执行过程中,代码或工具调用可能发起未授权的出站请求(比如把本地代码上传到未知地址)
  3. 资源耗尽:无限循环、fork 炸弹、内存泄漏类的命令,如果没有资源上限,会拖垮整台宿主机

三个层面需要的隔离强度不同,混用一套方案往往要么过度设计,要么留有明显漏洞。

二、隔离方案的四个层级

从轻到重,常见方案大致分四档:

层级实现方式隔离强度启动开销适用场景
进程级子进程 + 资源限制(ulimit/cgroup)几乎为零本地开发工具、可信度高的场景
命名空间级Linux namespace + seccomp毫秒级需要文件系统/网络隔离但不想要容器开销
容器级Docker / gVisor / Firecracker中高百毫秒到秒级多租户 SaaS、面向陌生代码的执行
虚拟机级完整 VM(QEMU/云厂商微 VM)秒级以上高风险场景、需要内核级隔离

选型的核心权衡是隔离强度 vs 启动延迟。一个交互式编程 Agent,如果每次执行命令都要等几秒钟启动容器,用户体验会很差;但如果为了速度放弃隔离,一旦命令有破坏性,代价可能远超那几秒钟。

实用建议:本地 IDE 场景(用户对自己的代码有信任基础)用命名空间级隔离通常足够;面向不受信任代码或多租户 SaaS 场景,容器级是最低要求,高风险场景(比如允许执行任意上传代码)应该上虚拟机级隔离,gVisor、Firecracker 这类”微虚拟机”方案在启动速度和隔离强度之间取得了不错的平衡,是目前很多 Agent 平台的实际选择。

三、文件系统边界:白名单而不是黑名单

新手常见的错误设计是”禁止访问几个危险路径”(黑名单),但危险路径列不完,而且容易被相对路径、符号链接绕过。正确做法是反过来:默认拒绝一切访问,显式授权工作目录

沙箱文件系统规则(推荐):
- 挂载点:仅工作目录(如 /workspace)可读写
- 只读挂载:必要的运行时/依赖目录(如 /usr/lib,防止篡改)
- 其余路径:完全不可见(容器内直接看不到宿主机文件系统的其他部分)

容器方案下,这一步通过 mount 配置就能实现;命名空间级隔离下,需要结合 chroot/pivot_root 手动限制可见的文件系统根。关键是让”看不见”成为默认状态,而不是靠权限检查逐个拦截。

四、网络边界:先问”这个任务真的需要联网吗”

很多编程 Agent 的任务(跑测试、格式化代码、执行 lint)根本不需要联网。网络边界设计的第一原则是默认关闭出站网络,只在明确需要时(比如安装依赖包)临时开放,且限定可访问的域名范围:

network_policy:
  default: deny
  exceptions:
    - task: install_dependencies
      allow_hosts:
        - registry.npmjs.org
        - pypi.org
      duration: single_command  # 仅本次命令生效,之后恢复 deny

这个设计能防住一大类风险:即便模型被注入了恶意指令,试图把代码或密钥外传,默认关闭的网络会直接挡住这条路径,不需要依赖”识别出这是恶意行为”这种更难做对的判断。

五、资源限制:防止单个任务拖垮环境

无论隔离方案多强,都要配合资源上限,否则一个死循环或者内存泄漏的命令能耗尽宿主资源,影响同一台机器上的其他任务:

# cgroup 层面的典型限制(Linux)
cpu.max = "50000 100000"   # 限制为 0.5 核
memory.max = "512M"
pids.max = 256              # 防止 fork 炸弹

对超时的处理,可以参考 Agent 工具超时预算设计 的分层超时思路——沙箱层面除了单命令超时,还要有整个会话的总资源预算,防止 Agent 在合规的单命令超时内反复执行大量命令,变相耗尽资源。

六、可观测性:沙箱内发生了什么必须留痕

沙箱把风险挡在外面,但不代表可以放弃审计。至少要记录:

  • 每次命令执行的完整内容和退出码
  • 文件系统的写操作(新建、修改、删除了哪些文件)
  • 网络请求尝试(包括被拒绝的出站请求——这类记录对发现提示词注入攻击特别有价值)

被拒绝的网络请求日志尤其重要:如果监控到 Agent 频繁尝试访问陌生域名,这通常是提示词注入或者模型行为异常的早期信号,比等到真正的数据泄露发生后再排查要及时得多。

七、一个分级方案示例

结合以上维度,给一个可直接参考的分级设计:

场景隔离层级文件系统网络资源上限
本地开发,用户主动触发命名空间级工作目录可写,其余只读默认关闭,装包时临时开放1 核 / 1G / 单命令 30s
SaaS 多租户,处理用户代码容器级(gVisor)仅当前任务的临时目录白名单域名,全程记录0.5 核 / 512M / 会话 5min
高风险,执行不可信第三方代码虚拟机级(Firecracker)全新临时文件系统,任务结束销毁完全隔离,禁止出站严格上限 + 独立计费隔离

八、相关阅读

搭建自己的编程 Agent 时,除了沙箱这层执行安全,模型调用本身的稳定性和成本同样关键,YoTradeApi 提供国内可直连的主流大模型 API 中转,方便在沙箱之外把调用链路一并跑通。