OpenClaw Docker 沙箱安全架构:代码执行的容器级隔离与七层纵深防护

摘要:AI Agent 执行代码的安全边界在哪里?OpenClaw 没有选 VM(太重),也没有选 seccomp 裸调(太底层),而是在 Docker 容器层面构建了七层纵深防御体系。本文详解其 Bind Mount 防路径穿越、Capabilities 白名单裁剪、Config Hash 热容器保留,以及文件系统桥接的符号链接硬化校验。


一、安全模型的根本选择:为什么是 Docker?

在让 AI 执行任意代码这件事上,业界有三种隔离方案:

方案隔离强度启动速度文件共享OpenClaw 的选择
VM(虚拟机)★★★★★慢(分钟级)需网络挂载
seccomp 裸调★★★困难
Docker 容器★★★★快(秒级)Bind Mount

关键在于:AI Agent 需要读写用户的真实工作目录(workspace),但又不应该访问 /etc/passwd/proc、Docker socket 等敏感路径。Docker 的 Bind Mount 恰好能精确控制"哪几个目录可以共享"——问题变成了"如何验证这些 mount 是安全的"。

七层防御

攻击面

逐层拦截

逐层拦截

逐层拦截

逐层拦截

逐层拦截

逐层拦截

逐层拦截

逐层拦截

逐层拦截

逐层拦截

逐层拦截

逐层拦截

逐层拦截

逐层拦截

逐层拦截

逐层拦截

逐层拦截

逐层拦截

逐层拦截

逐层拦截

逐层拦截

逐层拦截

逐层拦截

逐层拦截

逐层拦截

逐层拦截

逐层拦截

逐层拦截

恶意代码:cat /etc/passwd

路径穿越:../host/secret

符号链接逃逸:symlink → /root

Docker Socket 逃逸

① Capabilities 裁剪
cap-drop: ALL

② seccomp/AppArmor
系统调用白名单

③ 资源配额
CPU/内存/PID 限制

④ Bind Mount 黑名单
/etc, /proc, /sys, /dev

⑤ allowedRoots 校验
只在 workspace 内

⑥ 符号链接硬化
realpath 二次检查

⑦ 保留路径保护
/workspace, /agent 不可覆盖


二、容器生命周期:从创建到自动清理

2.1 核心流程

文件系统 Docker Daemon ensureSandboxContainer AI Agent 文件系统 Docker Daemon ensureSandboxContainer AI Agent alt [容器不存在] [容器存在但 Config Hash 变化] [容器就绪] 每 5 分钟自动巡检 请求沙箱执行代码 计算 Config Hash docker create(Cap+配额+Bind) containerId docker start docker rename(旧容器保留为热备) docker create(新配置) docker start docker exec(直接复用) docker rm -f(过期容器清理)

核心原理① — Config Hash 热容器保留:当用户修改了沙箱配置(如新增 bind mount),不是粗暴 rm 旧容器,而是将其 rename 保留。新容器就绪后,二者并存几秒过渡期,然后在下次 prune 周期清理旧容器。这确保了配置变更时正在执行的任务不会因容器突然消失而中断。

2.2 自动清理策略

参数默认值说明
idleHours24空闲超过 24h 自动删除
maxAgeDays7最长存活 7 天,无论是否活跃
巡检间隔5 分钟每 5 分钟检查一次

三、Bind Mount 安全:七层纵深防御

这是整个沙箱安全的精髓。每次构建 Docker 容器参数时,validateSandboxSecurity() 都会强制执行以下验证链:

不通过

通过

用户自定义 bind mount

① 路径是否为绝对路径?

拒绝:non_absolute

② 命中黑名单?
/etc, /proc, /sys, /dev, /root, /boot, /run, docker.sock

拒绝:blocked_host_path

③ 挂载的是根目录 /?

拒绝:covers_root

④ source 在 allowedRoots 内?
workspace + agent workspace

拒绝:outside_allowed_roots

⑤ 目标路径是否与保留路径冲突?
/workspace, /agent

拒绝:reserved_target

⑥ 解析符号链接 → realpath

⑦ 真实路径重新走一遍黑名单 + allowedRoots 检查

拒绝:symlink_escape

✓ 允许挂载

核心原理② — 符号链接硬化是最后防线:即使 source 路径 /workspace/projects/secret 通过了前五层检查,也必须在 Docker 容器内通过 realpath(解析所有 symlink)重新验证。如果 /workspace/projects 实际上是一个指向 /root 的软链接,第六层会在容器内执行 shell 命令解析真实路径后触发第七层重新检查——此时 /root 命中黑名单,拒绝。

关键的是,即使配置了 dangerouslyAllowExternalBindSources(允许挂载外部路径),仍然有三层不可绕过:

  • /etc, /proc, /sys 的黑名单始终生效
  • Docker socket 永远不可挂载
  • 根目录 / 永远不可挂载

四、Capabilities 与资源配额

4.1 Capabilities 白名单

OpenClaw 默认 cap-drop: ALL——先全部剥夺,再按需添加:

cap-drop: ALL

按需 cap-add

未添加的

Linux Capabilities
(全部 40 种)

空集(零权限)

最小权限集合

NET_BIND_SERVICE

...

全部拒绝

这比 --privileged 或默认 cap 集合要安全得多。即使 AI 生成的代码包含恶意系统调用,缺少对应 capability 的容器也无力执行。

4.2 资源配额三重限制

限制项默认值防护目标
--cpus1防止挖矿 / CPU 洪水
--memory512m防止内存炸弹
--pids-limit64防止 fork 炸弹

就算 Agent 生成了一段 while(true) { fork(); } 的代码,PID 限制 64 会让第 65 次 fork 直接失败——进程数封顶,保住了宿主机。


五、文件系统桥接的安全设计

当 AI Agent 执行 read_file /etc/passwd 时,路径解析发生在容器内。但如果用户配置了"允许 Agent 访问整个主机文件系统",那 assertPathSafety 就需要在每次文件操作前做一次额外的安全检查:

1

2

3

任一失败

任一失败

任一失败

Agent 请求文件操作
read/write path

路径映射
hostPath → containerPath

assertPathSafety
三步校验

路径规范化:消除 .. 和 //

逐段遍历:检查每一级目录
是否为符号链接

容器内 realpath 最终确认

✓ 安全

✗ 拒绝

核心原理③ — 逐段检查防止中间路径劫持:即使是 /workspace/safe/../../etc/passwd 这样的路径,通过逐段解析每一个路径组件,.. 穿越会在第一关就被捕获。而符号链接劫持——比如 /workspace/link 指向 /etc——则在第二关的逐段 symlink 检测中被拦截。


六、总结

Docker 沙箱安全

七层防御

Capabilities 裁剪

seccomp/AppArmor

资源配额

Bind 黑名单

allowedRoots

符号链接硬化

保留路径保护

生命周期

Config Hash 热保留

idleHours 24h 自动清理

maxAgeDays 7d

三级不可绕过

/etc /proc /sys 黑名单

Docker socket 禁止

根目录 / 禁止

代码执行

PIDs 上限 64

Memory 512m

CPU 1 核

OpenClaw 的 Docker 沙箱不依赖任何"假设 AI 不会写恶意代码"的安全模型。它假设最坏情况:AI 生成了 fork 炸弹、路径穿越、符号链接逃逸——然后逐层拦截。这种纵深防御策略意味着单点防线被突破并不会导致整个沙箱沦陷。


下篇预告《高可用与进程生命周期:Gateway 信号重启、进程锁与优雅关闭》

参考资料

更多推荐