Skip to content

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.

  • 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.
    • 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.

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.

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.

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.

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.

Example (read-only source + 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"]
}
}
}
]
}
}

Security notes:

  • Binds bypass the sandbox filesystem: they expose host paths with whatever mode you set (:ro or :rw).
  • Sensitive mounts (e.g., docker.sock, secrets, SSH keys) 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.