Summary
Since v2026.2.13 (PR #4026), the default sandbox configuration makes Read, Write, Edit, and apply_patch file tools non-functional for git-based installs running the gateway as a dedicated non-root user — the recommended setup pattern.
The root cause is a three-way default mismatch: the container runs as root (no user configured), capDrop: ["ALL"] strips DAC_OVERRIDE, and the workspace is owned by the non-root gateway user. Without DAC_OVERRIDE, root inside the container falls into "other" with read-execute only, and all write operations fail silently.
Related: #17941 (media-file subset of the same underlying problem)
Reproduction Steps
- Install openclaw via git clone, running the gateway as a dedicated user (e.g.,
openclaw, UID 1003)
- Enable sandbox mode (default
sandbox.mode: "all")
- Do not set
agents.defaults.sandbox.docker.user — rely on defaults
- Send a message that triggers the agent to use Write or Edit on a workspace file
- Observe:
moltbot-sandbox-fs: 1: cannot create /workspace/<path>: Permission denied
Also reproducible with:
- Reading inbound media attachments (saved as 0600 by the gateway process)
- apply_patch tool (uses the same
SandboxFsBridge)
Root Cause
PR #4026 (29d783958) moved file tool operations from host-side node:fs to docker exec inside the container via SandboxFsBridge. Three default configuration values combine to create a UID mismatch:
- No default
user — src/agents/sandbox/config.ts:82 resolves user from agent or global config with no fallback. When unset, the container runs as root (UID 0).
capDrop: ["ALL"] — src/agents/sandbox/config.ts:83 defaults to dropping all capabilities, stripping DAC_OVERRIDE from root.
--user conditionally omitted — src/agents/sandbox/docker.ts:270 only passes --user when user is truthy. With no default, the flag is never passed.
The result: root (UID 0) without DAC_OVERRIDE must obey standard Unix permission checks. The workspace directory is owned by the gateway user (e.g., UID 1003) with mode rwx------. Root falls into "other" — read-execute at best, no write access.
Confirmed diagnostics from inside the container:
$ id
uid=0(root) gid=0(root)
$ cat /proc/1/status | grep Cap
CapInh: 0000000000000000
CapPrm: 0000000000000000
CapEff: 0000000000000000
$ touch /workspace/test
touch: cannot touch '/workspace/test': Permission denied
Impact
- All sandboxed file operations broken by default for the recommended git-based install setup (dedicated non-root gateway user)
- Silent failures — the agent sees "Permission denied" but the end user may not realize file tools are non-functional
- Inbound media (images, PDFs, audio) unreadable from sandbox (0600 files)
- No migration guidance in the v2026.2.13 changelog
- Workaround exists but requires knowing to set
agents.defaults.sandbox.docker.user
Possible Fixes
These are suggestions — happy to defer to maintainer judgment on approach:
- Auto-detect gateway UID at container creation — pass
--user $(process.getuid()):$(process.getgid()) in buildSandboxCreateArgs(). Cleanest fix; preserves the --cap-drop ALL security posture.
- Selectively add
DAC_OVERRIDE — re-add just the one capability root needs for file access. Simpler but weakens sandbox hardening.
- Document the workaround — add
agents.defaults.sandbox.docker.user guidance to sandbox docs. Minimum viable but doesn't fix the default.
Workaround
openclaw config set agents.defaults.sandbox.docker.user "$(id -u):$(id -g)"
openclaw sandbox recreate --all
Agent Prompt
When the gateway runs as a dedicated non-root user (the recommended git-based install pattern), the default sandbox configuration makes all file tools (Read, Write, Edit, apply_patch) non-functional. The container runs as root (UID 0) with all capabilities dropped, which strips DAC_OVERRIDE. Without that capability, root inside the container cannot write to workspace directories owned by the gateway user, or read 0600 inbound media files. The defaults that combine to cause this are: no user set in resolveSandboxDockerConfig(), capDrop: ["ALL"], and workspace owned by a non-root UID. The container's effective user needs to match the gateway's file ownership for sandboxed file operations to work.
Summary
Since v2026.2.13 (PR #4026), the default sandbox configuration makes Read, Write, Edit, and apply_patch file tools non-functional for git-based installs running the gateway as a dedicated non-root user — the recommended setup pattern.
The root cause is a three-way default mismatch: the container runs as root (no
userconfigured),capDrop: ["ALL"]stripsDAC_OVERRIDE, and the workspace is owned by the non-root gateway user. WithoutDAC_OVERRIDE, root inside the container falls into "other" with read-execute only, and all write operations fail silently.Related: #17941 (media-file subset of the same underlying problem)
Reproduction Steps
openclaw, UID 1003)sandbox.mode: "all")agents.defaults.sandbox.docker.user— rely on defaultsmoltbot-sandbox-fs: 1: cannot create /workspace/<path>: Permission deniedAlso reproducible with:
SandboxFsBridge)Root Cause
PR #4026 (
29d783958) moved file tool operations from host-sidenode:fstodocker execinside the container viaSandboxFsBridge. Three default configuration values combine to create a UID mismatch:user—src/agents/sandbox/config.ts:82resolvesuserfrom agent or global config with no fallback. When unset, the container runs as root (UID 0).capDrop: ["ALL"]—src/agents/sandbox/config.ts:83defaults to dropping all capabilities, strippingDAC_OVERRIDEfrom root.--userconditionally omitted —src/agents/sandbox/docker.ts:270only passes--userwhenuseris truthy. With no default, the flag is never passed.The result: root (UID 0) without
DAC_OVERRIDEmust obey standard Unix permission checks. The workspace directory is owned by the gateway user (e.g., UID 1003) with moderwx------. Root falls into "other" — read-execute at best, no write access.Confirmed diagnostics from inside the container:
Impact
agents.defaults.sandbox.docker.userPossible Fixes
These are suggestions — happy to defer to maintainer judgment on approach:
--user $(process.getuid()):$(process.getgid())inbuildSandboxCreateArgs(). Cleanest fix; preserves the--cap-drop ALLsecurity posture.DAC_OVERRIDE— re-add just the one capability root needs for file access. Simpler but weakens sandbox hardening.agents.defaults.sandbox.docker.userguidance to sandbox docs. Minimum viable but doesn't fix the default.Workaround
Agent Prompt
When the gateway runs as a dedicated non-root user (the recommended git-based install pattern), the default sandbox configuration makes all file tools (Read, Write, Edit, apply_patch) non-functional. The container runs as root (UID 0) with all capabilities dropped, which strips
DAC_OVERRIDE. Without that capability, root inside the container cannot write to workspace directories owned by the gateway user, or read 0600 inbound media files. The defaults that combine to cause this are: nouserset inresolveSandboxDockerConfig(),capDrop: ["ALL"], and workspace owned by a non-root UID. The container's effective user needs to match the gateway's file ownership for sandboxed file operations to work.