沙箱(Sandboxing)
OpenClaw 可以在 Docker 容器内运行工具以减少爆炸半径。这是可选的,由配置(agents.defaults.sandbox 或 agents.list[].sandbox)控制。如果沙箱关闭,工具在主机上运行。网关保持在主机上;启用时工具执行在隔离的沙箱中运行。
这不是一个完美的安全边界,但当模型做了蠢事时,它能实质性地限制文件系统和进程访问。
什么被沙箱化
- 工具执行(exec、read、write、edit、apply_patch、process 等)。
- 可选的沙箱浏览器(agents.defaults.sandbox.browser)。
- 默认情况下,当浏览器工具需要时,沙箱浏览器会自动启动(确保 CDP 可访问)。通过 agents.defaults.sandbox.browser.autoStart 和 agents.defaults.sandbox.browser.autoStartTimeoutMs 配置。
- agents.defaults.sandbox.browser.allowHostControl 让沙箱会话显式定位主机浏览器。
- 可选的允许列表限制 target: "custom":allowedControlUrls、allowedControlHosts、allowedControlPorts。
未沙箱化:
- 网关进程本身。
- 任何显式允许在主机上运行的工具(例如 tools.elevated)。
- 提升的 exec 在主机上运行并绕过沙箱。
- 如果沙箱关闭,tools.elevated 不会改变执行(已经在主机上)。参见提升模式(Elevated Mode)。
模式
agents.defaults.sandbox.mode 控制何时使用沙箱:
- "off":无沙箱。
- "non-main":仅沙箱非主会话(如果你想要主机上的正常聊天,这是默认值)。
- "all":每个会话都在沙箱中运行。 注意:"non-main" 基于 session.mainKey(默认 "main"),而不是代理 ID。群组/频道会话使用它们自己的键,因此它们算作非主会话并将被沙箱化。
作用域
agents.defaults.sandbox.scope 控制创建多少个容器:
- "session"(默认):每个会话一个容器。
- "agent":每个代理一个容器。
- "shared":所有沙箱会话共享一个容器。
工作区访问
agents.defaults.sandbox.workspaceAccess 控制沙箱能看到什么:
- "none"(默认):工具看到 ~/.openclaw/sandboxes 下的沙箱工作区。
- "ro":以只读方式在 /agent 挂载代理工作区(禁用 write/edit/apply_patch)。
- "rw":以读写方式在 /workspace 挂载代理工作区。
入站媒体被复制到活动沙箱工作区(media/inbound/*)。技能注意:read 工具以沙箱为根。使用 workspaceAccess: "none" 时,OpenClaw 将符合条件的技能镜像到沙箱工作区(.../skills)以便它们可以被读取。使用 "rw" 时,工作区技能可以从 /workspace/skills 读取。
自定义绑定挂载
agents.defaults.sandbox.docker.binds 将额外的主机目录挂载到容器中。格式:host:container:mode(例如,"/home/user/source:/source:rw")。
全局和每代理绑定是合并的(不是替换)。在 scope: "shared" 下,每代理绑定被忽略。
示例(只读源 + docker socket):
{
agents: {
defaults: {
sandbox: {
docker: {
binds: [
"/home/user/source:/source:ro",
"/var/run/docker.sock:/var/run/docker.sock"
]
}
}
},
list: [
{
id: "build",
sandbox: {
docker: {
binds: ["/mnt/cache:/cache:rw"]
}
}
}
]
}
}
安全注意事项:
- 绑定绕过沙箱文件系统:它们使用你设置的任何模式(:ro 或 :rw)暴露主机路径。
- 敏感挂载(例如 docker.sock、密钥、SSH 密钥)应该是 :ro,除非绝对需要。
- 如果你只需要对工作区的读访问,结合 workspaceAccess: "ro";绑定模式保持独立。
- 参见沙箱 vs 工具策略 vs 提升了解绑定如何与工具策略和提升的 exec 交互。
镜像 + 设置
默认镜像:openclaw-sandbox:bookworm-slim
构建一次:
scripts/sandbox-setup.sh
注意:默认镜像不包括 Node。如果技能需要 Node(或其他运行时),要么烘焙自定义镜像,要么通过 sandbox.docker.setupCommand 安装(需要网络出口 + 可写根 + root 用户)。
沙箱浏览器镜像:
scripts/sandbox-browser-setup.sh
默认情况下,沙箱容器以无网络运行。使用 agents.defaults.sandbox.docker.network 覆盖。
Docker 安装和容器化网关位于此处:Docker
setupCommand(一次性容器设置)
setupCommand 在沙箱容器创建后运行一次(不是每次运行)。它通过 sh -lc 在容器内执行。
路径:
- 全局:agents.defaults.sandbox.docker.setupCommand
- 每代理:agents.list[].sandbox.docker.setupCommand
常见陷阱:
- 默认 docker.network 是 "none"(无出口),因此包安装将失败。
- readOnlyRoot: true 防止写入;设置 readOnlyRoot: false 或烘焙自定义镜像。
- user 必须是 root 才能安装包(省略 user 或设置 user: "0:0")。
- 沙箱 exec 不继承主机 process.env。使用 agents.defaults.sandbox.docker.env(或自定义镜像)用于技能 API 密钥。
工具策略 + 逃生舱口
工具允许/拒绝策略在沙箱规则之前仍然适用。如果工具在全局或每代理被拒绝,沙箱不会把它带回来。
tools.elevated 是在主机上运行 exec 的显式逃生舱口。/exec 指令仅适用于授权发送者并且每个会话持久化;要硬禁用 exec,使用工具策略拒绝(参见沙箱 vs 工具策略 vs 提升)。
调试:
- 使用 openclaw sandbox explain 检查有效的沙箱模式、工具策略和修复配置键。
- 参见沙箱 vs 工具策略 vs 提升了解"为什么这被阻止?"的心智模型。 保持锁定。
多代理覆盖
每个代理可以覆盖沙箱 + 工具:agents.list[].sandbox 和 agents.list[].tools(加上 agents.list[].tools.sandbox.tools 用于沙箱工具策略)。参见多代理沙箱和工具了解优先级。
最小启用示例
{
agents: {
defaults: {
sandbox: {
mode: "non-main",
scope: "session",
workspaceAccess: "none"
}
}
}
}