Linux sandbox: node child_process.spawnSync/execFileSync returns EPERM after the child exits successfully (status 0, stdout captured)
Summary
Inside the Linux sandbox (codex sandbox -- …, and equally inside an agent turn under sandbox_mode = "workspace-write"), Node's child_process.spawnSync / execFileSync fails with EPERM after the child has already run successfully. The child executes and its stdout is captured (status: 0), but Node reports error: spawnSync <cmd> EPERM (errno -1), so execFileSync throws. Any build/tooling script that shells out from Node (e.g. git rev-parse HEAD) breaks. The same command outside the sandbox works.
Environment
- codex-cli 0.150.1 (native Linux binary), WSL2 Ubuntu 26.04 LTS, kernel per WSL2, system bubblewrap 0.11.1 at
/usr/bin/bwrap - Node 24.20.0 / 22.23.2 / 20.20.2 (all reproduce identically)
- macOS (seatbelt) does not reproduce
Repro
$ codex sandbox -- git rev-parse --short HEAD
16ce57d # plain git is fine
$ codex sandbox -- node -e 'const r=require("child_process").spawnSync("git",["rev-parse","--short","HEAD"]);console.log("status",r.status,"err",r.error?r.error.code:"none","out",String(r.stdout).trim())'
status 0 err EPERM out 16ce57d # child ran, output captured, but error=EPERM
execFileSync('git', ['rev-parse','HEAD']) therefore throws spawnSync git EPERM even though git returned 0 and printed the sha.
What we ruled out
- Node version: 24 / 22 / 20 identical.
features.use_legacy_landlock = true(via--enable,-c, and inCODEX_HOME/config.toml): still EPERM.use_linux_sandbox_bwraptrue/false in config.toml: still EPERM.- Running the same node one-liner directly under
bwrap(including--unshare-pid --as-pid-1) does not reproduce, so it does not look like the pid namespace alone; it looks like the syscall filter the sandbox runner applies aroundexec(the child's post-exit reap path in libuv —waitid/pidfd_*/kill(pid,0)class — gets EPERM).
Expected
spawnSync/execFileSync of an allowed command inside the sandbox should return without error when the child exits 0, as it does on macOS.
Impact
Any Node-based build step that spawns processes (git, npm run scripts calling git, etc.) fails inside the Linux sandbox, forcing users to either move work off Linux or use danger-full-access, which we'd rather not.