Skip to content

[Bug] Default sandbox config breaks file tools for non-root gateway users (post-#4026) #20979

@LucasAIBuilder

Description

@LucasAIBuilder

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

  1. Install openclaw via git clone, running the gateway as a dedicated user (e.g., openclaw, UID 1003)
  2. Enable sandbox mode (default sandbox.mode: "all")
  3. Do not set agents.defaults.sandbox.docker.user — rely on defaults
  4. Send a message that triggers the agent to use Write or Edit on a workspace file
  5. 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:

  1. No default usersrc/agents/sandbox/config.ts:82 resolves user from agent or global config with no fallback. When unset, the container runs as root (UID 0).
  2. capDrop: ["ALL"]src/agents/sandbox/config.ts:83 defaults to dropping all capabilities, stripping DAC_OVERRIDE from root.
  3. --user conditionally omittedsrc/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:

  1. Auto-detect gateway UID at container creation — pass --user $(process.getuid()):$(process.getgid()) in buildSandboxCreateArgs(). Cleanest fix; preserves the --cap-drop ALL security posture.
  2. Selectively add DAC_OVERRIDE — re-add just the one capability root needs for file access. Simpler but weakens sandbox hardening.
  3. 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions