Windows sandbox: restricted token cannot enumerate or execute under the user profile, so pwsh/python/gh silently "do not exist"

Open 💬 2 comments Opened Aug 12, 2026 by jrgoralski
💡 Likely answer: A maintainer (github-actions[bot], contributor) responded on this thread — see the highlighted reply below.

What version of Codex CLI is running? codex-cli 0.146.1 (@openai/codex 0.146.1, codex-win32-x64)

What subscription do you have? ChatGPT (auth_mode = chatgpt)

Which model were you using? gpt-5.6-sol

What platform is your computer? Microsoft Windows NT 10.0.26200.9168 x64

What terminal emulator? Reproduced from Git Bash (MSYS2) and cmd.exe; not terminal-specific.

Codex doctor report: 17 ok · 1 idle · 1 notes · 0 warn · 0 fail — auth, connectivity and model access are all healthy. The failure is entirely in the sandbox command runner.

---

What issue are you seeing?

On this machine the Windows sandbox's restricted token can stat paths under C:\Users\<user>\ but cannot enumerate directories or execute binaries there. Sandboxed codex exec is consequently unable to run any tool installed under the user profile — which on a normal Windows dev box is most of them.

It surfaces as two unrelated-looking symptoms with one cause.

Symptom 1 — total CreateProcessAsUserW failed: 5 when pwsh is an MSIX App Execution Alias

windows sandbox: runner failed during SpawnChild: CreateProcessAsUserW failed: 5 (Access is denied.)
| cwd=C:\Users\<user>\dev\<repo>
| cmd=C:\Users\<user>\AppData\Local\Microsoft\WindowsApps\pwsh.exe -NoProfile -Command "..."
| env_u16_len=5450 | si_flags=256 | creation_flags=525312 (Windows error 5)

The cmd= path is under the user profile. …\AppData\Local\Microsoft\WindowsApps\pwsh.exe is an App Execution Alias — a reparse point into C:\Program Files\WindowsApps\Microsoft.PowerShell_7.6.4.0_x64__8wekyb3d8bbwe\pwsh.exe — and the sandbox token cannot execute it. Every command fails before it runs, under both -s read-only and -s workspace-write.

This is a common configuration rather than an exotic one: winget install --id Microsoft.PowerShell installs the msix variant, and that is the only installer in the manifest.

> winget show --id Microsoft.PowerShell --exact
Version: 7.6.4.0
  Installer Type: msix
  Installer Url: .../PowerShell-7.6.4.msixbundle

So anyone who installed PowerShell 7 via winget and never separately ran the MSI has pwsh on PATH as an alias only, with C:\Program Files\PowerShell\7\pwsh.exe absent. winget install --installer-type msi --force cannot help — it returns No applicable installer found, because the manifest has no MSI.

Workaround for this half: remove WindowsApps from the PATH the codex process itself sees. Shell discovery then falls through its candidate list (pwshpwsh.exepowershellpowershell.exe) to Windows PowerShell 5.1 at C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe, which is machine-wide, and commands spawn correctly.

Symptom 2 — with a machine-wide shell, every user-profile tool reports "not recognized"

After that workaround the sandbox runs commands, but only machine-wide ones. git (at C:\Program Files\Git) works; python and gh do not:

gh : The term 'gh' is not recognized as the name of a cmdlet, function, script file, or operable program.
python : The term 'python' is not recognized as the name of a cmdlet, function, script file, or operable program.

This is not a PATH problem. I initially assumed it was and was wrong. Dumping $env:PATH from inside the sandbox shows the inherited PATH arrives intact, including both directories:

C:\Users\<user>\.codex\tmp\arg0\codex-arg0CGD0Ky
C:\Users\<user>\AppData\Roaming\npm\...\codex-win32-x64\vendor\...\codex-path
C:\Program Files\Git\mingw64\bin
...
C:\Users\<user>\AppData\Local\Programs\Python\Python312     <-- present
...
C:\Users\<user>\AppData\Local\Microsoft\WinGet\Links        <-- present

shell_environment_policy also works correctly — arbitrary variables set via -c shell_environment_policy.set.FOO=bar arrive in the child exactly as configured. Neither mechanism is at fault.

The actual cause, probed directly

Run inside the sandbox (-s workspace-write, machine-wide PowerShell):

$p = "C:\Users\<user>\AppData\Local\Programs\Python\Python312\python.exe"
$g = "C:\Program Files\Git\cmd\git.exe"
Test-Path -LiteralPath $p                       # -> True
Test-Path -LiteralPath $g                       # -> True
Get-ChildItem -LiteralPath (Split-Path $p)      # -> UnauthorizedAccessException
& $p -c "print(42)"                             # -> ApplicationFailedException

The token can stat the user-profile executable, but cannot enumerate its directory and cannot execute it. The machine-wide binary is fine. That single fact produces both symptoms: pwsh fails to spawn because the alias is in the profile, and python/gh are "not found" because PowerShell's command discovery cannot enumerate the PATH directories holding them.

Writes to the workspace itself succeed under -s workspace-write even though the workspace is also under C:\Users\<user>\, so this is not a blanket profile denial — execute and enumerate are denied where write is allowed.

-s danger-full-access is unaffected, since it does not use the sandbox runner:

> codex exec -s danger-full-access 'run: git rev-parse --short HEAD; gh --version; python -c "print(1+1)"'
90756b1
gh version 2.95.0 (2026-06-17)
2

What steps can reproduce the bug?

  1. Windows 11. Install PowerShell 7 with winget install --id Microsoft.PowerShell (yields msix). Confirm C:\Program Files\PowerShell\7\pwsh.exe does not exist and where pwsh returns the WindowsApps path.
  2. Install any tool into the user profile — e.g. winget install GitHub.cli, or python.org's per-user Python.
  3. codex exec -s read-only 'run: git rev-parse --short HEAD' → every command fails with CreateProcessAsUserW failed: 5, cmd= pointing at the WindowsApps alias.
  4. Re-run with WindowsApps removed from the PATH the codex process sees → commands now spawn via powershell.exe, and git works.
  5. codex exec -s workspace-write 'run: gh --version'not recognized, despite WinGet\Links being present in the sandbox's $env:PATH.
  6. Run the Test-Path / Get-ChildItem / full-path-execute probe above → True, UnauthorizedAccessException, ApplicationFailedException.

What is the expected behavior?

  1. The sandbox should be able to execute the user's toolchain. Per-user installs are the norm on Windows — winget package links, python.org per-user installs, npm globals, pipx, rustup, Store apps. If the token cannot execute anything under C:\Users\<user>\, sandboxed mode cannot run most real projects, and -s danger-full-access becomes the only usable setting, which defeats the point of having a sandbox.
  2. If this denial is deliberate isolation, it needs to say so. Right now a denied execute is reported as CommandNotFoundException — "the term 'python' is not recognized" — which sends you looking for a PATH bug. I spent a long time ruling out PATH, shell_environment_policy.inherit, set.PATH, and profile files before probing the ACL. An explicit "sandbox denied execute on <path>" would have made it a one-minute diagnosis, and the docs should state that user-profile executables are unavailable in sandboxed mode.
  3. Shell discovery should not select an executable the sandbox's own token cannot start. Skipping WindowsApps alias stubs, or probing the machine-wide C:\Program Files\PowerShell\7\pwsh.exe (already referenced in the binary) before the PATH lookup, would fix symptom 1 outright.

Relationship to existing issues

#26186, #37592, #30024, #35958 and #36614 all report CreateProcessAsUserW failures, the first two with error 5. I am not claiming those share this cause. #37592's follow-up describes an intermittent failure where some commands succeed, correlated with SetFileAttributesW on C:\Users\Default; this one is total, deterministic, and fully explained by the token's inability to execute under the user profile. Filing separately rather than assuming — if a maintainer confirms a shared root cause, please close this as a duplicate.

Found while trying to run a code review with codex exec on an ordinary developer machine; nothing here is specific to the project under review. Paths redacted per the template.

View original on GitHub ↗

2 Comments

github-actions[bot] contributor · 15 days ago

Potential duplicates detected. Please review them and close your issue if it is a duplicate.

  • #37592

Powered by Codex Action

jdcodes1 · 9 days ago

Your probe results pin the policy shape precisely, and it's worth framing as a design gap rather than an ACL accident: the sandbox setup (the SetupPayload read/write/deny roots applied as ACLs by codex-windows-sandbox-setup — see the payload structure discussed in #38985) leaves user-profile directories stat-able but denies FILE_LIST_DIRECTORY and FILE_EXECUTE outside the workspace. On Windows that's fatal to tooling generally, because per-user installs are the norm: WindowsApps execution aliases (winget's only PowerShell variant, as you note), AppData\Local\Programs, WinGet\Links, npm global bins. Attributes-only visibility breaks both spawn (symptom 1) and PATH discovery (symptom 2) in one stroke — enumeration denial means PowerShell can't even see what's on PATH.

Fix shapes:

  1. Grant traverse + execute (not data read) on profile-rooted directories that appear on the inherited PATH, plus the WindowsApps alias directory and its Program Files\WindowsApps MSIX targets (the reparse target needs execute too, or aliases keep failing with error 5).
  2. Or an explicit executable_roots policy knob so users can whitelist tool directories without opening profile data reads.
  3. Either way, codex doctor could probe exactly your three checks (stat / enumerate / execute a PATH entry under the profile) and report the asymmetry — this class of "everything says not recognized" report becomes self-diagnosing.

Option 1's PATH-derived variant fixes the default experience for the common winget/npm/python.org setups without widening reads on user documents.