Agent 容器沙箱隔离实现:不内置 Runtime 的设计思考

0 阅读6分钟

企业级 Agent 的「手」安全——在操作系统内核级别限制 Agent 的可触达范围。


一、背景:第一篇留下了什么

第一篇介绍了策略引擎 + DLP + 审批的「软防线」:

  • 路径 ACL:限制 Agent 只能读写工作区
  • 命令黑名单:禁止 rm -rf / 等危险命令
  • DLP 扫描:阻止敏感数据进入 LLM 上下文
  • 审批机制:关键操作需人类确认

但软防线有个本质局限:管不住间接攻击路径

一个例子

Agent 可以:

  1. write_file 写一个 Python 脚本到工作区(合法)
  2. exec 运行这个脚本(合法)

脚本内部做什么?路径策略和命令正则都拦不住。


二、两种场景,同一个问题

容器沙箱要解决的场景:

场景 A:企业开发环境

企业给开发者配置安全的 AI 开发环境:

  • 保护目标:代码资产、测试环境、生产系统
  • 管理者:IT 管理员
  • 配置方式:企业统一配置安全策略
  • 典型用户:企业开发者、CI/CD 环境

场景 B:个人桌面设备

个人用户使用 AI 辅助编程:

  • 保护目标:本地文件、个人数据、系统环境
  • 管理者:用户本人
  • 配置方式:用户在设置中自主选择
  • 典型用户:独立开发者、学生、个人用户

共同需求

无论哪种场景,核心需求是一样的:

隔离 Agent 的执行环境,避免它破坏你的系统。

三、解决方案:容器沙箱

容器沙箱解决的是:在操作系统内核级别限制 Agent 的可触达范围

软防线(策略 + 审批 + DLP):告诉 Agent "你不该做这个"
硬隔离(容器沙箱):让 Agent "做不了这个"

两者不是替代关系,而是纵深防御的两层。


四、核心设计原则

原则 1:灵活的配置方式

企业场景:管理员统一配置,开发者无感知

安全策略 → 强制启用容器隔离 → 开发者无法绕过

个人场景:用户自主选择

设置 → 安全级别 → 用户主动选择透明模式/容器隔离

桌面客户端的用户就坐在电脑前,有能力也有权利决定自己的安全水位。

原则 2:按需获取

沙箱所需的容器镜像不内置于安装包,用户启用时按需下载。

  • 安装包不因沙箱功能膨胀
  • 不需要沙箱的用户零开销
  • 镜像版本可独立于客户端版本更新

原则 3:零强制依赖

容器运行时(Docker / Podman)是可选组件

  • 检测到 → 启用沙箱
  • 未检测到 → 引导安装,不拦截,不阻断
  • 可以随时切换模式

原则 4:优雅降级

任何环节失败都不应导致功能不可用。

容器执行失败 → 回退到审批模式在宿主机执行
镜像下载失败 → 提示重试,当前使用透明模式
运行时不可用 → 引导安装,当前使用透明模式

五、用户流程

5.1 企业场景(管理员配置)

IT 管理员配置
    │
    ▼
企业策略强制启用"容器隔离"
    │
    ▼
开发者启动 Agent
    │
    ├── 已安装运行时 → 直接使用容器隔离
    └── 未安装运行时 → 提示联系 IT 安装

5.2 个人场景(用户自主)

设置 → 安全 → 执行环境
│
├─ ○ 透明模式(默认)
│
└─ ● 容器隔离
      │
      ▼ 环境检查
      ✓ 检测到 Podman 5.3.0
      沙箱镜像:未安装
      [下载沙箱镜像] (12 MB)

5.3 未检测到运行时

环境检查
✗ 未检测到容器运行时

容器隔离需要 Docker 或 Podman。

企业环境:联系 IT 管理员安装
个人环境:brew install podman(macOS)

[我已安装,重新检测]  [暂不安装,使用透明模式]

六、技术架构

6.1 整体位置

tool_registry.execute(name, params)
    │
    ├── Phase 1a: Policy Gate(策略检查)
    ├── Phase 1b: Plugin Hooks(审批)
    │
    ├── Phase 2: Around(执行环境)
    │   ├── sandbox = "transparent" → 宿主机直接执行
    │   └── sandbox = "isolated" → 容器执行器
    │
    └── Phase 3: After(DLP + 审计)

6.2 容器执行器

核心模块:

ContainerSandbox
├── detect()          # 检测容器运行时
├── ensure_image()    # 确保沙箱镜像已就绪
├── start()           # 启动沙箱容器
├── exec(command)     # 在容器内执行命令
├── is_running()      # 检查容器状态
└── cleanup()         # 销毁容器

6.3 容器生命周期

应用启动 + 启用容器隔离
    │
    ▼
ContainerSandbox.start()
    │
    ├── 检查是否已有运行中的沙箱容器
    │   └── 有 → 复用
    │
    └── 无 → 创建新容器
        │
        docker run -d \
          --name deskclaw-sandbox \
          -v $WORKSPACE:/workspace \
          --network none \
          --cap-drop ALL \
          --read-only \
          --memory 512m \
          --cpus 1 \
          --pids-limit 128 \
          deskclaw-sandbox:1.0.0 \
          sleep infinity
        │
        ▼
    容器就绪(持续运行直到应用退出)

容器在整个应用生命周期内保持运行,不是每条命令启一个容器。每次 exec 仅增加 ~50ms 延迟。


七,安全约束

约束参数作用
网络隔离--network none完全断网,Agent 无法通过 curl/wget 泄露数据
能力丢弃--cap-drop ALL丢弃所有 Linux capabilities
权限锁定--security-opt no-new-privileges禁止提权
只读根--read-only根文件系统只读,仅 /workspace 和 /tmp 可写
临时目录--tmpfs /tmp:size=64m限制 /tmp 大小
内存限制--memory 512m防止内存耗尽
CPU 限制--cpus 1限制 CPU 使用
进程限制--pids-limit 128防止 fork bomb
工作目录-v $WORKSPACE:/workspace仅挂载工作区

八、沙箱镜像

8.1 镜像内容

基础镜像:busybox(~1.5 MB),包含基础 shell 工具。

如果命令需要 busybox 不包含的工具(如 gitpython),沙箱执行将返回 "command not found",此时降级到审批模式在宿主机执行。

8.2 镜像分发

构建侧                          用户侧
────────                      ────────
Dockerfile                         │
    │                              │
    ▼                              ▼
docker build                  检测到"镜像未安装"
    │                              │
    ▼                              ▼
docker save -o sandbox.tar   从对象存储下载 .tar
    │                              │
    ▼                              ▼
上传到对象存储 (OSS/S3)        docker/podman load -i
                                  │
                                  ▼
                              镜像就绪

九、降级策略

三层降级

Level 0: 容器隔离(最高安全)
     容器执行失败 / 命令需要宿主机环境
    
Level 1: 审批模式(现有行为)
     用户关闭审批 / 策略设为 transparent
    
Level 2: 直接执行(最低安全)

降级触发条件

触发条件降级行为用户感知
容器运行时未安装退回透明模式提示安装
沙箱镜像未就绪退回透明模式提示下载
容器启动失败退回透明模式日志记录 + 通知
命令在容器内执行失败不降级,返回错误Agent 自行处理

十、为什么不做内置 Runtime?

这是最常见的问题:「为什么不内置 Docker?」

我们的选择:不内置

方案优点缺点
内置 Docker功能完整安装包膨胀 ~500MB、需要 daemon、开机自启
不内置,检测用户环境零膨胀、用户/企业可控需要安装

核心思路

  • 企业:IT 预装或强制安装,开发者无感知
  • 个人:引导安装,但不强制
  • 都能用:优雅降级,没有运行时也能工作

十一、与前两篇的关系

控制对象核心能力
第1篇Agent 的「手」(工具执行)策略引擎 + DLP + 审批
第2篇Agent 的「脑」(模型访问)URL 即凭证 + 动态端点
第3篇执行环境容器沙箱隔离

第一篇解决「工具能不能做」,第二篇解决「模型能不能访问」,第三篇解决「在哪里做」。


十二、总结

容器沙箱的核心设计理念:

  1. 兼顾两种场景——企业统一配置 + 个人自主选择
  2. 按需获取——不内置镜像,零膨胀
  3. 优雅降级——任何环节失败都能回退
  4. 纵深防御——软防线 + 硬隔离配合

无论是保护企业代码资产,还是保护个人电脑数据,核心思路是一样的:

在操作系统内核级别限制 Agent 的可触达范围。


本文是「企业级 Agent 安全方案」系列第 3 篇