Linux sandbox: unreadable-glob ripgrep scan is fatal on WSL2 drvfs workspace roots that contain OS-restricted directories
On WSL2, when the session/workspace root is a Windows drvfs mount such as/mnt/c/Users/<user>, sandbox construction fails for every shell command, because the
unreadable-glob expansion scan cannot complete on directories Windows itself makes
unreadable.
Environment
- codex-cli 0.147.0 (also reproduced byte-identically on 0.146.0)
- WSL2 (kernel 6.18.x), ripgrep 14.1.0 at /usr/bin/rg
- Permission profile containing workspace-root deny globs, e.g.
[permissions.<name>.filesystem.":workspace_roots"] with "**/.env*" = "deny",
"**/*.pem" = "deny", etc.
Behavior
With the session/workspace root at /mnt/c/Users/<user>, EVERY shell command fails
before execution:
error building bubblewrap command: Fatal error: ripgrep unreadable glob scan failed
for /mnt/c/Users/<user>:
rg: /mnt/c/Users/<user>/AppData/Local/ElevatedDiagnostics: Permission denied (os error 13)
rg: Input/output error (os error 5)
Changing the per-command workdir does not help (the scan anchors at the workspace
root). sandbox_permissions=require_escalated does not help either.
Token-free repro:
codex sandbox -P <profile-with-ws-root-deny-globs> -C /mnt/c/Users/<user> echo ok
Cause
codex-rs/linux-sandbox/src/bwrap.rs ripgrep_files() treats every rg outcome other
than success, or exit 1 with empty stderr, as fatal. A standard Windows user profile
structurally contains entries the WSL user can never enumerate:
AppData/Local/ElevatedDiagnostics—d--x--x--x(listing denied by Windows ACL)- legacy junctions (
Local Settings, ...) that resolve into the same denied dirs - cloud-placeholder directories (Dropbox / OneDrive online-only files) that return
EIO (os error 5) through drvfs
ripgrep exits 2 while still producing complete results for the readable portion, so
the scan can never succeed on such roots, and the sandbox cannot be built at all.
The internal glob_files() fallback walker propagates fs::read_dir errors the same
way, and literal deny entries do not prune these subtrees from the walk.
Why fatal seems over-conservative here
The scan runs as the same uid as the future sandboxed process. A subtree the scanner
cannot read cannot be read by the sandboxed command either, so path-attributed
EACCES/EPERM entries are self-protecting: skipping them cannot weaken deny-read.
(The transient-error caution behind "other ripgrep failures stay fatal" can be kept
by limiting tolerance to path-attributed permission errors, optionally re-verified
with a direct stat.)
Suggestions (any one of)
- Accept rg exit 2 when stderr consists only of path-attributed
permission/unreadable entries (optionally stat-verify each), and keep other
failures fatal.
- Prune the walk under subtrees already covered by literal deny/unreadable roots so
admins can mask known-unscannable dirs explicitly.
- A config knob, e.g.
glob_scan_unreadable_policy = "skip-inaccessible", with the
current fatal behavior as the default.
Workaround we use today
Root the session in a scannable subdirectory of the Windows home; per-command workdir
on the parent still works. The home root itself remains unusable as a workspace root.