Files
moltbot/docs/gateway/sandboxing.md
Vincent Koc a19a7f5e6e feat(security): Harden Docker browser container chromium flags (#23889) (#31504)
* Gateway: honor OPENCLAW_GATEWAY_URL override for remote/local calls

* Agents: fix sandbox sessionKey usage for PI embedded subagent calls

* Sandbox: tighten browser container Chromium runtime flags

* fix: add sandbox browser defaults for container hardening

* docs: expand sandbox browser default flags list

* fix: make sandbox browser flags optional and preserve gateway env auth overrides

* docs: scope PR 31504 changelog entry

* style: format gateway call override handling

* fix: dedupe sandbox browser chrome args

* fix: preserve remote tls fingerprint for env gateway override

* fix: enforce auth for env gateway URL override

* chore: document gateway override auth security expectations
2026-03-02 11:28:27 -08:00

10 KiB
Raw Blame History

summary, title, read_when, status
summary title read_when status
How OpenClaw sandboxing works: modes, scopes, workspace access, and images Sandboxing You want a dedicated explanation of sandboxing or need to tune agents.defaults.sandbox. active

Sandboxing

OpenClaw can run tools inside Docker containers to reduce blast radius. This is optional and controlled by configuration (agents.defaults.sandbox or agents.list[].sandbox). If sandboxing is off, tools run on the host. The Gateway stays on the host; tool execution runs in an isolated sandbox when enabled.

This is not a perfect security boundary, but it materially limits filesystem and process access when the model does something dumb.

What gets sandboxed

  • Tool execution (exec, read, write, edit, apply_patch, process, etc.).
  • Optional sandboxed browser (agents.defaults.sandbox.browser).
    • By default, the sandbox browser auto-starts (ensures CDP is reachable) when the browser tool needs it. Configure via agents.defaults.sandbox.browser.autoStart and agents.defaults.sandbox.browser.autoStartTimeoutMs.
    • By default, sandbox browser containers use a dedicated Docker network (openclaw-sandbox-browser) instead of the global bridge network. Configure with agents.defaults.sandbox.browser.network.
    • Optional agents.defaults.sandbox.browser.cdpSourceRange restricts container-edge CDP ingress with a CIDR allowlist (for example 172.21.0.1/32).
    • noVNC observer access is password-protected by default; OpenClaw emits a short-lived token URL that serves a local bootstrap page and opens noVNC with password in URL fragment (not query/header logs).
    • agents.defaults.sandbox.browser.allowHostControl lets sandboxed sessions target the host browser explicitly.
    • Optional allowlists gate target: "custom": allowedControlUrls, allowedControlHosts, allowedControlPorts.

Not sandboxed:

  • The Gateway process itself.
  • Any tool explicitly allowed to run on the host (e.g. tools.elevated).
    • Elevated exec runs on the host and bypasses sandboxing.
    • If sandboxing is off, tools.elevated does not change execution (already on host). See Elevated Mode.

Modes

agents.defaults.sandbox.mode controls when sandboxing is used:

  • "off": no sandboxing.
  • "non-main": sandbox only non-main sessions (default if you want normal chats on host).
  • "all": every session runs in a sandbox. Note: "non-main" is based on session.mainKey (default "main"), not agent id. Group/channel sessions use their own keys, so they count as non-main and will be sandboxed.

Scope

agents.defaults.sandbox.scope controls how many containers are created:

  • "session" (default): one container per session.
  • "agent": one container per agent.
  • "shared": one container shared by all sandboxed sessions.

Workspace access

agents.defaults.sandbox.workspaceAccess controls what the sandbox can see:

  • "none" (default): tools see a sandbox workspace under ~/.openclaw/sandboxes.
  • "ro": mounts the agent workspace read-only at /agent (disables write/edit/apply_patch).
  • "rw": mounts the agent workspace read/write at /workspace.

Inbound media is copied into the active sandbox workspace (media/inbound/*). Skills note: the read tool is sandbox-rooted. With workspaceAccess: "none", OpenClaw mirrors eligible skills into the sandbox workspace (.../skills) so they can be read. With "rw", workspace skills are readable from /workspace/skills.

Custom bind mounts

agents.defaults.sandbox.docker.binds mounts additional host directories into the container. Format: host:container:mode (e.g., "/home/user/source:/source:rw").

Global and per-agent binds are merged (not replaced). Under scope: "shared", per-agent binds are ignored.

agents.defaults.sandbox.browser.binds mounts additional host directories into the sandbox browser container only.

  • When set (including []), it replaces agents.defaults.sandbox.docker.binds for the browser container.
  • When omitted, the browser container falls back to agents.defaults.sandbox.docker.binds (backwards compatible).

Example (read-only source + an extra data directory):

{
  agents: {
    defaults: {
      sandbox: {
        docker: {
          binds: ["/home/user/source:/source:ro", "/var/data/myapp:/data:ro"],
        },
      },
    },
    list: [
      {
        id: "build",
        sandbox: {
          docker: {
            binds: ["/mnt/cache:/cache:rw"],
          },
        },
      },
    ],
  },
}

Security notes:

  • Binds bypass the sandbox filesystem: they expose host paths with whatever mode you set (:ro or :rw).
  • OpenClaw blocks dangerous bind sources (for example: docker.sock, /etc, /proc, /sys, /dev, and parent mounts that would expose them).
  • Sensitive mounts (secrets, SSH keys, service credentials) should be :ro unless absolutely required.
  • Combine with workspaceAccess: "ro" if you only need read access to the workspace; bind modes stay independent.
  • See Sandbox vs Tool Policy vs Elevated for how binds interact with tool policy and elevated exec.

Images + setup

Default image: openclaw-sandbox:bookworm-slim

Build it once:

scripts/sandbox-setup.sh

Note: the default image does not include Node. If a skill needs Node (or other runtimes), either bake a custom image or install via sandbox.docker.setupCommand (requires network egress + writable root + root user).

If you want a more functional sandbox image with common tooling (for example curl, jq, nodejs, python3, git), build:

scripts/sandbox-common-setup.sh

Then set agents.defaults.sandbox.docker.image to openclaw-sandbox-common:bookworm-slim.

Sandboxed browser image:

scripts/sandbox-browser-setup.sh

By default, sandbox containers run with no network. Override with agents.defaults.sandbox.docker.network.

The bundled sandbox browser image also applies conservative Chromium startup defaults for containerized workloads. Current container defaults include:

  • --remote-debugging-address=127.0.0.1
  • --remote-debugging-port=<derived from OPENCLAW_BROWSER_CDP_PORT>
  • --user-data-dir=${HOME}/.chrome
  • --no-first-run
  • --no-default-browser-check
  • --disable-3d-apis
  • --disable-gpu
  • --disable-dev-shm-usage
  • --disable-background-networking
  • --disable-extensions
  • --disable-features=TranslateUI
  • --disable-breakpad
  • --disable-crash-reporter
  • --disable-software-rasterizer
  • --no-zygote
  • --metrics-recording-only
  • --renderer-process-limit=2
  • --no-sandbox and --disable-setuid-sandbox when noSandbox is enabled.
  • The three graphics hardening flags (--disable-3d-apis, --disable-software-rasterizer, --disable-gpu) are optional and are useful when containers lack GPU support. Set OPENCLAW_BROWSER_DISABLE_GRAPHICS_FLAGS=0 if your workload requires WebGL or other 3D/browser features.
  • --disable-extensions is enabled by default and can be disabled with OPENCLAW_BROWSER_DISABLE_EXTENSIONS=0 for extension-reliant flows.
  • --renderer-process-limit=2 is controlled by OPENCLAW_BROWSER_RENDERER_PROCESS_LIMIT=<N>, where 0 keeps Chromium's default.

If you need a different runtime profile, use a custom browser image and provide your own entrypoint. For local (non-container) Chromium profiles, use browser.extraArgs to append additional startup flags.

Security defaults:

  • network: "host" is blocked.
  • network: "container:<id>" is blocked by default (namespace join bypass risk).
  • Break-glass override: agents.defaults.sandbox.docker.dangerouslyAllowContainerNamespaceJoin: true.

Docker installs and the containerized gateway live here: Docker

For Docker gateway deployments, docker-setup.sh can bootstrap sandbox config. Set OPENCLAW_SANDBOX=1 (or true/yes/on) to enable that path. You can override socket location with OPENCLAW_DOCKER_SOCKET. Full setup and env reference: Docker.

setupCommand (one-time container setup)

setupCommand runs once after the sandbox container is created (not on every run). It executes inside the container via sh -lc.

Paths:

  • Global: agents.defaults.sandbox.docker.setupCommand
  • Per-agent: agents.list[].sandbox.docker.setupCommand

Common pitfalls:

  • Default docker.network is "none" (no egress), so package installs will fail.
  • docker.network: "container:<id>" requires dangerouslyAllowContainerNamespaceJoin: true and is break-glass only.
  • readOnlyRoot: true prevents writes; set readOnlyRoot: false or bake a custom image.
  • user must be root for package installs (omit user or set user: "0:0").
  • Sandbox exec does not inherit host process.env. Use agents.defaults.sandbox.docker.env (or a custom image) for skill API keys.

Tool policy + escape hatches

Tool allow/deny policies still apply before sandbox rules. If a tool is denied globally or per-agent, sandboxing doesnt bring it back.

tools.elevated is an explicit escape hatch that runs exec on the host. /exec directives only apply for authorized senders and persist per session; to hard-disable exec, use tool policy deny (see Sandbox vs Tool Policy vs Elevated).

Debugging:

  • Use openclaw sandbox explain to inspect effective sandbox mode, tool policy, and fix-it config keys.
  • See Sandbox vs Tool Policy vs Elevated for the “why is this blocked?” mental model. Keep it locked down.

Multi-agent overrides

Each agent can override sandbox + tools: agents.list[].sandbox and agents.list[].tools (plus agents.list[].tools.sandbox.tools for sandbox tool policy). See Multi-Agent Sandbox & Tools for precedence.

Minimal enable example

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