Skip to content

Sandboxing(沙箱化)

OpenClaw 可以把 tools 放进 Docker 容器里运行,以降低误操作的影响半径。 这是 可选项,由配置控制(agents.defaults.sandboxagents.list[].sandbox)。如果关闭 sandboxing,tools 会直接在宿主机上运行。 Gateway 进程始终运行在宿主机上;启用 sandboxing 时,tool 执行会在隔离的沙箱中进行。

这不是完美的安全边界,但当模型做出糟糕行为时,它能实质性地限制对文件系统与进程的访问范围。

哪些会被沙箱化

  • tool 执行(execreadwriteeditapply_patchprocess 等)。
  • 可选的沙箱化浏览器(agents.defaults.sandbox.browser)。
    • 默认情况下,当 browser tool 需要时,沙箱浏览器会自动启动(确保 CDP 可达)。可通过 agents.defaults.sandbox.browser.autoStartagents.defaults.sandbox.browser.autoStartTimeoutMs 配置。
    • agents.defaults.sandbox.browser.allowHostControl 允许沙箱会话显式指向宿主机浏览器。
    • target: "custom" 可由 allowlists 限制:allowedControlUrlsallowedControlHostsallowedControlPorts

不在沙箱中运行:

  • Gateway 进程本身。
  • 任何被显式允许在宿主机上运行的 tool(例如 tools.elevated)。
    • Elevated exec 在宿主机上运行,并绕过 sandboxing。
    • 如果 sandboxing 关闭,tools.elevated 不会改变执行位置(本来就在宿主机上)。参见 Elevated Mode

模式

agents.defaults.sandbox.mode 控制 什么时候 使用 sandboxing:

  • "off":不使用沙箱。
  • "non-main":只对 非 main 的 sessions 启用沙箱(如果你希望正常聊天仍在宿主机上运行,这是常见默认)。
  • "all":所有 session 都在沙箱中运行。 备注:"non-main"session.mainKey(默认 "main")为准,而不是 agent id。 群聊/频道 sessions 使用自己的 key,因此会被视为 non-main,从而会被沙箱化。

作用域(Scope)

agents.defaults.sandbox.scope 控制会创建 多少个容器

  • "session"(默认):每个 session 一个容器。
  • "agent":每个 agent 一个容器。
  • "shared":所有被沙箱化的 sessions 共享一个容器。

工作区访问

agents.defaults.sandbox.workspaceAccess 控制 沙箱能看到什么

  • "none"(默认):tools 只看到 ~/.openclaw/sandboxes 下的沙箱工作区。
  • "ro":以只读方式把 agent workspace 挂载到 /agent(会禁用 write/edit/apply_patch)。
  • "rw":以读写方式把 agent workspace 挂载到 /workspace

入站媒体会被拷贝到当前活跃的沙箱工作区(media/inbound/*)。 Skills 说明:read tool 以沙箱根目录为根。对于 workspaceAccess: "none",OpenClaw 会把可用的 skills 镜像到沙箱工作区(.../skills)以便读取;对于 "rw",workspace skills 可从 /workspace/skills 读取。

自定义 bind mounts

agents.defaults.sandbox.docker.binds 会把额外的宿主机目录挂载进容器。 格式:host:container:mode(例如 "/home/user/source:/source:rw")。

全局与 per-agent 的 binds 会 合并(不会互相替换)。在 scope: "shared" 下,per-agent binds 会被忽略。

示例(只读源码 + docker socket):

json5
{
  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"],
          },
        },
      },
    ],
  },
}

安全备注:

  • binds 会绕过沙箱文件系统:你挂载的 host path 会以你设置的模式(:ro:rw)直接暴露到容器里。
  • 敏感挂载(例如 docker.sock、secrets、SSH keys)除非绝对必要,否则应使用 :ro
  • 如果你只需要读取 workspace,请配合 workspaceAccess: "ro";bind 的模式与 workspaceAccess 相互独立。
  • 关于 binds 与 tool policy、elevated exec 的交互,见 Sandbox vs Tool Policy vs Elevated

Images + setup

默认镜像:openclaw-sandbox:bookworm-slim

构建一次即可:

bash
scripts/sandbox-setup.sh

注意:默认镜像 不包含 Node。如果某个 skill 需要 Node(或其它 runtime),要么自制镜像,要么通过 sandbox.docker.setupCommand 安装(需要网络出站 + 可写 root + root 用户)。

沙箱浏览器镜像:

bash
scripts/sandbox-browser-setup.sh

默认情况下,沙箱容器 不允许网络。 可通过 agents.defaults.sandbox.docker.network 覆盖。

Docker 安装与容器化 gateway 见: Docker

setupCommand(一次性的容器初始化)

setupCommand 会在创建沙箱容器后 只运行一次(不会每次执行都跑)。 它会在容器内通过 sh -lc 执行。

路径:

  • 全局:agents.defaults.sandbox.docker.setupCommand
  • per-agent:agents.list[].sandbox.docker.setupCommand

常见坑:

  • 默认 docker.network"none"(无出站网络),因此安装包会失败。
  • readOnlyRoot: true 会阻止写入;需要设置 readOnlyRoot: false 或自制镜像。
  • 安装包需要 root:省略 user 或设置 user: "0:0"
  • 沙箱 exec 不会继承 宿主机的 process.env。skill 的 API keys 应通过 agents.defaults.sandbox.docker.env(或自制镜像)提供。

Tool policy + 逃生阀

tool allow/deny policies 会先于 sandbox 规则生效。如果某个 tool 在全局或 per-agent 被 deny,开启 sandboxing 也不会把它“带回来”。

tools.elevated 是一个显式的逃生阀:让 exec 在宿主机上运行。 /exec 指令只对已授权的发送者生效,并且按 session 持久化;要彻底禁用 exec,应通过 tool policy deny(见 Sandbox vs Tool Policy vs Elevated)。

排障:

  • 使用 openclaw sandbox explain 查看实际生效的 sandbox mode、tool policy,以及需要修改的配置 key。
  • “为什么被挡住?”的心智模型见 Sandbox vs Tool Policy vs Elevated。 请保持严格限制。

Multi-agent 覆盖

每个 agent 都可以覆盖 sandbox + tools: agents.list[].sandboxagents.list[].tools(以及 agents.list[].tools.sandbox.tools 用于沙箱内 tool policy)。 优先级见 Multi-Agent Sandbox & Tools

最小启用示例

json5
{
  agents: {
    defaults: {
      sandbox: {
        mode: "non-main",
        scope: "session",
        workspaceAccess: "none",
      },
    },
  },
}

相关文档