#20991: fix(sandbox): fall back to gateway UID:GID when no user is configured (#20979)
agents
size: M
Cluster:
Sandbox Enhancements and Fixes
## Summary
Fixes #20979
When `agents.defaults.sandbox.docker.user` is not set, the container runs as root (UID 0) with `--cap-drop ALL` which strips `DAC_OVERRIDE`. Without `DAC_OVERRIDE`, root inside the container cannot write to workspace directories owned by the non-root gateway user — the recommended git-based install pattern. This silently breaks the Read, Write, Edit, and `apply_patch` file tools for all sandboxed sessions.
## Root Cause
Three default values combine to create a UID mismatch (as detailed in #20979):
1. **No default `user`** — `resolveSandboxDockerConfig()` resolves `user` from agent or global config with no fallback, so container runs as root (UID 0) when unset.
2. **`capDrop: ["ALL"]`** — strips `DAC_OVERRIDE` from root.
3. **`--user` conditionally omitted** — `buildSandboxCreateArgs()` only passes `--user` when `cfg.user` is truthy.
## Fix
In `buildSandboxCreateArgs()` in `src/agents/sandbox/docker.ts`, when `cfg.user` is not explicitly set, fall back to `process.getuid():process.getgid()` on POSIX platforms so the container's effective user matches the gateway's file ownership:
```typescript
const effectiveUser =
params.cfg.user ||
(typeof process.getuid === "function"
? `${process.getuid()}:${typeof process.getgid === "function" ? process.getgid() : process.getuid()}`
: null);
if (effectiveUser) {
args.push("--user", effectiveUser);
}
```
**Behavior:**
- ✅ Explicit `user` config: unchanged (always takes precedence)
- ✅ Non-root gateway (UID 1003): container gets `--user 1003:1003`
- ✅ Root gateway (UID 0): container gets `--user 0:0` (same as before — no regression)
- ✅ Windows (no `process.getuid`): no `--user` flag passed (same as before)
## Tests
Added `src/agents/sandbox/docker.sandbox-create-args.test.ts` covering:
- Explicit user config takes precedence
- Non-root gateway falls back to UID:GID
- Root gateway falls back to 0:0
## Workaround (no longer needed)
Users on affected setups can still manually configure:
```bash
openclaw config set agents.defaults.sandbox.docker.user "$(id -u):$(id -g)"
openclaw sandbox recreate --all
```
<!-- greptile_comment -->
<h3>Greptile Summary</h3>
Fixes file tool access issues for non-root gateway users by falling back to the gateway process UID:GID when `agents.defaults.sandbox.docker.user` is not configured. The root cause was that containers ran as root with `--cap-drop ALL`, which stripped `DAC_OVERRIDE` capability, preventing write access to workspace directories owned by non-root gateway users.
- Implemented automatic fallback to `process.getuid():process.getgid()` on POSIX platforms in `buildSandboxCreateArgs()`
- Added comprehensive tests covering explicit config, non-root fallback, and root fallback scenarios
- Updated CHANGELOG.md with fix details
- Test coverage is thorough but missing Windows/non-POSIX platform test case
<h3>Confidence Score: 4/5</h3>
- This PR is safe to merge with minimal risk - it fixes a legitimate bug without introducing breaking changes
- The fix is well-designed and follows existing codebase patterns for POSIX detection. Tests cover the main scenarios. Score of 4 (not 5) due to missing Windows test coverage, though the implementation itself handles Windows correctly by design.
- No files require special attention - the implementation is straightforward and safe
<sub>Last reviewed commit: 2451865</sub>
<!-- greptile_other_comments_section -->
<sub>(3/5) Reply to the agent's comments like "Can you suggest a fix for this @greptileai?" or ask follow-up questions!</sub>
<!-- /greptile_comment -->
Most Similar PRs
#23112: fix(sandbox): propagate docker.user to all exec commands
by dashed · 2026-02-22
88.1%
#4226: Fix/sandbox containerworkdir rw access
by ozgur-polat · 2026-01-29
83.1%
#16922: fix: remove incorrect sandbox file tool guidance
by carrotRakko · 2026-02-15
81.5%
#16509: Fix sandbox path validation rejecting Docker bind mount paths
by Clawborn · 2026-02-14
81.4%
#7851: feat: secure sandbox defaults for new installs
by ichbinlucaskim · 2026-02-03
81.1%
#19344: fix(sandbox): allow writes when workspaceAccess is 'none'
by mingming099 · 2026-02-17
80.6%
#20477: fix(cron): prevent sandbox config clobbering in hook/cron agent path
by olyashok · 2026-02-19
79.8%
#11820: fix(sandbox): remap container paths in sandboxed file tools
by steflsd · 2026-02-08
79.6%
#17402: fix:sandbox path issue
by luckylhb90 · 2026-02-15
79.3%
#3907: fix(sandbox): use absolute /bin/sh path + add allowedReadPaths config
by pvoo · 2026-01-29
78.7%