🧰 Tooling Guide

OpenClaw Sandbox Setup: Why setupCommand Fails on the Defaults

•7 min read

Sandboxing in OpenClaw is off until you turn it on. Most people turn it on, paste a setupCommand from somewhere, and end up with a container that has no git in it.

The sandbox moves tool execution into a Docker container. The gateway itself stays on the host, so your channels, config and memory keep working exactly as before, and only the things the agent runs (exec, file reads and writes, the browser if you enable it) happen inside the box. The official page and its mirrors cover every key, and the longer third-party guides add SSH and OpenShell backends on top. All of them list the defaults. None of them point out that two of those defaults make the install step they recommend impossible, which is the first thing you hit on a real machine and the reason this page exists.

Three Dials

mode decides which sessions get a container: off, non-main or all. scope decides how many containers exist: one per agent (the default), one per session, or one shared by everything sandboxed. workspaceAccess decides what the container can see of your agent's workspace.

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

"Main" refers to a session key. It comes from session.mainKey, which defaults to main, and that is your direct chat. Group and channel sessions get their own keys, so under non-main the Discord server and the family Telegram group run sandboxed while your one-on-one chat runs on the host. That is the split I want. Strangers and pasted links go in the box; I do not.

Per-agent overrides live at agents.list[].sandbox (some releases call the list agents.entries), so a research agent that reads the open web can be all while everything else stays on non-main.

workspaceAccess, Read Literally

  • none: the container gets its own scratch workspace under ~/.openclaw/sandboxes. Your real workspace files are invisible.
  • ro: scratch space at /workspace, your agent workspace mounted read-only at /agent.
  • rw: your agent workspace mounted read-write at /workspace.

ro is the one people underrate. The agent can read MEMORY.md and the skill files it needs, and a prompt injection in a group chat cannot rewrite them. If you have read the workspace files guide, you know how much of an agent's behavior lives in those files. Handing rw on them to a public channel is handing over the agent.

The setupCommand Trap

The documented Docker defaults are tight: network: "none", readOnlyRoot: true, user: "1000:1000", capDrop: ["ALL"]. Good defaults. The image is openclaw-sandbox:bookworm-slim, which does not include Node, and the docs suggest two fixes for missing runtimes. One of them is setupCommand, which runs once after the container is created, via sh -lc, and which the same docs say needs network egress, a writable root and the root user.

Every one of those is switched off by default.

So the example everyone copies, apt-get update && apt-get install -y git curl jq, has nowhere to download from, nowhere to write and no permission to install even if it did. The agent then discovers the gap mid-task, usually by trying git status in a group chat and reporting that git is not installed, which most people blame on the model. You can make setupCommand work by opening the network, dropping readOnlyRoot and running as root. Do not. That trades three protections for the convenience of not writing a Dockerfile, and the network one in particular is the protection that stops an injected curl from posting your files somewhere.

Bake the Image Instead

Build the stock image once from a source checkout with scripts/sandbox-setup.sh, then layer what your skills need on top of it:

FROM openclaw-sandbox:bookworm-slim
USER root
RUN apt-get update \
 && apt-get install -y --no-install-recommends git jq ripgrep nodejs \
 && rm -rf /var/lib/apt/lists/*
USER 1000:1000
docker build -t openclaw-sandbox:mine .

Point agents.defaults.sandbox.docker.image at openclaw-sandbox:mine and leave network, root filesystem and user exactly where the defaults put them. The install happens at build time on your machine, with your network, where you can read the output. The container the agent gets is already finished.

To decide what goes in the RUN line, do not guess. The allow and deny list guide has a sessions_history prompt for a week of tool calls. Ask for every exec command line instead and take the binaries from that list. Anything a skill shells out to (check the skill folders too) belongs in the image, and anything that needs the network to do its job, a package manager or gh, needs a deliberate decision about whether that agent should be sandboxed at all.

Rebuild Means Recreate

With scope: "agent" the container lives a long time, and pruning only removes it after it sits idle or gets old. A new image tag in config does nothing for a container that already exists; recreate is the command that rebuilds containers against current config. After any image or sandbox change, run:

openclaw sandbox recreate --all
openclaw sandbox list

list shows whether each container's image matches the config. Check that column. With the default prune settings (24 idle hours, 7 days of age) an agent that runs daily can keep a stale container for a week, happily reporting that jq is missing from an image that has it.

Where It Leaks

The docs call this "not a perfect security boundary," and they are right. The first item below matters far more than the others:

  1. tools.elevated. It runs outside the sandbox, on the gateway by default. If a sandboxed agent has it, the box is decoration. Deny it in the tool policy for every agent that sits in a group chat, and pair that with the allowlist in the exec approvals guide, because the gateway default for exec security is full.
  2. Custom binds. A docker.binds entry that mounts your home directory read-write undoes workspaceAccess: "none" in one line.
  3. GitHub identity. It is excluded by default. Setting tools.github.allowInSandbox mounts the agent's credentials read-only, which stops edits and does not stop reads.

Tool policy runs before the sandbox, so a denied tool stays denied either way. Use both.

The Canary

Run openclaw sandbox explain --agent <id> first. It prints the effective mode, the mounts and the workspace the container really uses (look at effectiveHostWorkspaceRoot, not the configured root). Then, from a group chat, ask the agent to run cat ~/.openclaw/openclaw.json and curl -s https://example.com. Pass is a missing file and a network error. Then ask for git --version. Pass there is a version string, which proves the baked image is the one running. Add the three to the checklist in the upgrade guide and rerun them after every release.

Common Failure Modes

The agent says git (or node, or jq) is not installed

Your setupCommand never ran successfully under the default network and read-only root. Bake the tools into an image.

You changed the image and nothing changed

The old container is still alive. openclaw sandbox recreate --all, then confirm the image column in sandbox list.

Your direct chat is sandboxed and cannot see your files

Mode is all, or the session is not on the main key. Check session.mainKey and sandbox explain --session.

A group-chat agent edited MEMORY.md

workspaceAccess is rw, or a bind mount exposes the workspace. Drop it to ro.

Final Verdict

Turn it on with non-main, scope: "agent" and workspaceAccess: "ro", keep every Docker default the docs ship with, and put the tools your skills need into a baked image rather than a setupCommand that cannot run. Deny tools.elevated to anything that talks to people you have not met. The security best practices guide says external agents belong in isolated sandboxes. This is the version of that sentence that survives contact with a missing git.

⚡

Ready to build?

Get the OpenClaw Starter Kit — config templates, 5 production-ready skills, deployment checklist. Go from zero to running in under an hour.

$14 $6.99

Get the Starter Kit →

Also in the OpenClaw store

🗂️
Executive Assistant Config
Buy
Calendar, email, daily briefings on autopilot.
$6.99
🔍
Business Research Pack
Buy
Competitor tracking and market intelligence.
$5.99
⚡
Content Factory Workflow
Buy
Turn 1 post into 30 pieces of content.
$6.99
📬
Sales Outreach Skills
Buy
Automated lead research and personalized outreach.
$5.99

Get the free OpenClaw quickstart guide

Step-by-step setup. Plain English. No jargon.