Sandboxing — Administrator Guide
WednesdayAI runs agent tools inside Docker containers when sandboxing is enabled. The Gateway stays on the host; tool execution is isolated. This is not a perfect security boundary, but it materially limits filesystem and process access when the model does something unexpected.What gets sandboxed
- Tool execution:
exec,read,write,edit,apply_patch,process, and more. - Optional sandboxed browser (
agents.defaults.sandbox.browser).
- The Gateway process itself.
- Elevated exec (
tools.elevated) — always runs on the host and bypasses sandboxing. - If sandboxing is off,
tools.elevatedis a no-op (exec already runs on host).
Sandbox mode
agents.defaults.sandbox.mode:
"off"— no sandboxing."non-main"— sandbox only non-main sessions. Group/channel sessions use their own keys, so they count as non-main and are sandboxed."all"— every session is sandboxed.
"non-main" is based on session.mainKey (default "main"), not agent id.
Scope
agents.defaults.sandbox.scope — how many containers are created:
"session"(default) — one container per session."agent"— one container per agent."shared"— one container shared by all sandboxed sessions.
scope: "shared", per-agent bind mounts are ignored (only global binds apply).
Workspace access
agents.defaults.sandbox.workspaceAccess:
"none"(default) — sandbox workspace under~/.openclaw/sandboxes. Eligible skills are mirrored into sandbox workspace."ro"— mounts the agent workspace read-only at/agent(disableswrite/edit/apply_patch)."rw"— mounts the agent workspace read/write at/workspace. Skills are readable from/workspace/skills.
media/inbound/*).
Workspace lane fencing
For multi-lane deployments,fenceToLane: true binds the sandbox filesystem to the lane’s effective workspace directory instead of the shared persona root.
workspaceAccess: "rw" is required for complete isolation. Without it, scope-keyed directory seeding can allow cross-session reads. A warning is logged at session setup when fenceToLane: true and workspaceAccess is not "rw".
fenceToLane only applies when workspace lanes are enabled, the lane is resolved, and the policy decision is "allowed". No effect in single-user setups. Restricts tool filesystem access only; bootstrap resolution remains lane-aware.
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 applies only to the sandboxed browser container:
- When set (including
[]), replacessandbox.docker.bindsfor the browser container. - When omitted, falls back to
sandbox.docker.binds.
- Binds pierce the sandbox filesystem: whatever you mount is visible with the mode you set.
- Default mode is read-write if omitted; prefer
:rofor source and secrets. - WednesdayAI blocks dangerous bind sources:
docker.sock,/etc,/proc,/sys,/dev, and mounts that would expose them. - Sensitive mounts (SSH keys, service credentials) should be
:rounless absolutely required.
Docker images and setup
Default image:openclaw-sandbox:bookworm-slim
Build once:
curl, jq, nodejs, python3, git:
agents.defaults.sandbox.docker.image: "openclaw-sandbox-common:bookworm-slim"
Sandboxed browser image:
agents.defaults.sandbox.docker.network.
Security defaults:
network: "host"is blocked.network: "container:<id>"is blocked by default (namespace join bypass risk). Break-glass:agents.defaults.sandbox.docker.dangerouslyAllowContainerNamespaceJoin: true.
docker-setup.sh can bootstrap sandbox config. Set OPENCLAW_SANDBOX=1 to enable that path.
setupCommand (one-time container setup)
setupCommand runs once after the sandbox container is created (not on every run). Executes inside the container via sh -lc.
- Global:
agents.defaults.sandbox.docker.setupCommand - Per-agent:
agents.list[].sandbox.docker.setupCommand
- Default
docker.networkis"none"— package installs will fail without network. readOnlyRoot: trueprevents writes — setreadOnlyRoot: falseor bake a custom image.usermust be root for package installs (omituseror setuser: "0:0").- Sandbox exec does not inherit host
process.env. Useagents.defaults.sandbox.docker.envor a custom image for skill API keys.
Sandboxed browser
Optional sandboxed browser:- By default, the sandbox browser auto-starts when needed. Configure via
agents.defaults.sandbox.browser.autoStartandbrowser.autoStartTimeoutMs. - Uses a dedicated Docker network (
openclaw-sandbox-browser) instead of the globalbridgenetwork. Configure withbrowser.network. browser.cdpSourceRangerestricts container-edge CDP ingress with a CIDR allowlist.- noVNC observer access is password-protected by default; WednesdayAI emits a short-lived token URL.
browser.allowHostControllets sandboxed sessions target the host browser explicitly.allowedControlUrls,allowedControlHosts,allowedControlPortsgatetarget: "custom".
Multi-agent configuration
Per-agent overrides let each agent have a different sandbox profile: Sandbox config precedence:agents.list[].sandbox.{docker,browser,prune}.* is ignored when sandbox scope is "shared".
Example — different profiles per agent:
Tool policy + sandbox interaction
Tool allow/deny policy applies before sandbox rules. If a tool is denied globally or per-agent, sandboxing does not restore it.tools.elevated is an explicit escape hatch that runs exec on the host. To hard-disable exec, use tool policy deny (tools.deny: ["exec"]).
Sandbox tool policy (only applied when sandboxed):
agents.list[].tools.sandbox.tools replaces tools.sandbox.tools for that agent.
Security posture recommendations
Disable elevated globally if you only want sandboxed execution:
tools.elevated.enabled: false.
Disable elevated per agent for sensitive profiles: agents.list[].tools.elevated.enabled: false.
Auth and credentials
Auth is per-agent. Each agent reads from its ownagentDir:
auth-profiles.json into the other agent’s agentDir.