Linux sandbox: unreadable-glob ripgrep scan is fatal on WSL2 drvfs workspace roots that contain OS-restricted directories

Open 💬 0 comments Opened Aug 7, 2026 by k40481396-dr

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/ElevatedDiagnosticsd--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)

  1. Accept rg exit 2 when stderr consists only of path-attributed

permission/unreadable entries (optionally stat-verify each), and keep other
failures fatal.

  1. Prune the walk under subtrees already covered by literal deny/unreadable roots so

admins can mask known-unscannable dirs explicitly.

  1. 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.

View original on GitHub ↗