Windows sandbox: CreateProcessAsUserW fails with error 5 when the resolved shell is the MSIX (Store) build of pwsh
Summary
On Windows, the sandbox fails with CreateProcessAsUserW failed: 5 (Access is denied.) whenever the resolved shell is the MSIX (Microsoft Store) build of PowerShell 7. Windows refuses to launch a packaged (MSIX) binary under the restricted token the sandbox creates.
This appears to be the underlying cause behind several open reports (openai/codex#26803, openai/codex#25436, openai/codex#26186, [#10090](<https://github.com/openai/codex/issues/10090>), openai/codex#9062, and likely openai/codex#30047 / openai/codex#26896 where accounts were also involved). None of them identify the packaged-shell condition, which is why the failure looks environment-specific and unreproducible: it depends solely on whether pwsh resolves to C:\Program Files\WindowsApps\....
Measurement
Same machine, same session, 20 trials per shell. Counted on the presence of CreateProcessAsUserW in the output, not on the exit code (cmd.exe legitimately returns non-zero, which is misleading).
<!-- linear:table-colwidths:400,400 -->
| shell launched by the sandbox | failures |
| -- | -- |
| pwsh.exe — Store/MSIX (C:\Program Files\WindowsApps\Microsoft.PowerShell_7.6.4.0_x64__8wekyb3d8bbwe\pwsh.exe) | 20 / 20 |
| powershell.exe 5.1 (C:\Windows\System32\WindowsPowerShell\v1.0\) | 0 / 20 |
| cmd.exe | 0 / 20 |
| git bash | 0 / 20 |
End-to-end confirmation: codex exec with the normal PATH resolves the MSIX pwsh and fails. The same codex exec with the WindowsApps entries removed from PATH falls back to PowerShell 5.1 and returns normally (exit 0, \~720 ms).
Error payload
windows sandbox: runner failed during SpawnChild: CreateProcessAsUserW failed: 5 (Access is denied.)
| cwd=C:\Users\<user>\<workspace>
| cmd="C:\Program Files\WindowsApps\Microsoft.PowerShell_7.6.4.0_x64__8wekyb3d8bbwe\pwsh.exe" -NoProfile -Command "..."
| env_u16_len=6928 | si_flags=256 | creation_flags=525312 (Windows error 5)
creation_flags=525312 = 0x80400 = CREATE_UNICODE_ENVIRONMENT | EXTENDED_STARTUPINFO_PRESENT.
Two red herrings we eliminated, in case they save someone time
- Environment block size.
env_u16_len=6928is constant across all 20 failures, and it is \~5× below the documented 32,767 limit. An oversized block would also raiseERROR_INVALID_PARAMETER(87), not 5. Not the cause. - "Intermittent" behaviour. It looks intermittent but is deterministic per command: in our environment
echo hellofailed 20/20 whileGet-Content <path>succeeded 20/20 — file reads evidently take a path that never reachesSpawnChild. Observers who tested different commands drew opposite conclusions from the same broken setup.
Also ruled out on this machine: the CodexSandboxOffline / CodexSandboxOnline accounts both exist and are enabled, so this is not the missing-account variant.
Environment
- Windows 11 Pro, 10.0.26200
codex-cli0.144.3~/.codex/config.toml:[windows] sandbox = "elevated"
Suggested fix
When resolving the shell, skip binaries under %ProgramFiles%\WindowsApps (or any MSIX-packaged executable) and fall back to System32\WindowsPowerShell\v1.0\powershell.exe. A packaged binary cannot be started under a restricted token, so it can never work on the sandbox path.
A clear error message would help too — Access is denied gives no hint that the shell is the problem.
Workarounds for anyone hitting this now
- Ensure a non-packaged
pwshprecedes the Store one inPATH, or removeWindowsAppsfrom thePATHhanded to codex. [windows] sandbox = "unelevated"in~/.codex/config.toml(documented fallback; not needed once the shell is non-packaged).
15 Comments
Potential duplicates detected. Please review them and close your issue if it is a duplicate.
Powered by Codex Action
Correction / refinement to the report above: there are two independent variables, not one. Further measurement shows the MSIX shell alone is not sufficient — the failure requires
elevatedmode AND an MSIX-packaged target. Changing either one fixes it.Same machine, same MSIX
pwshtarget, 20 trials each:| sandbox mode | failures |
|---|---|
|
windows.sandbox=elevated(our config) | 20 / 20 ||
windows.sandbox=unelevated| 0 / 20 |End-to-end with a real model turn:
So the accurate statement is: under
elevatedmode, the sandbox cannot launch an MSIX-packaged binary under its restricted token. Underunelevated, the same packaged shell launches fine.This is worth knowing for triage, because it means affected users have two independent escapes — avoid the packaged shell, or switch the mode — and it may explain why some reporters see the failure and others with Store PowerShell do not: their mode differs.
Also: the "which commands fail" boundary is now precise
The earlier note about apparent intermittency resolves cleanly. In our runtime, simple readable operations are served internally and never reach
SpawnChild; anything else attempts a real spawn and fails 100% of the time.| command | failures |
|---|---|
|
Get-Content <file>| 0 / 5 ||
Get-ChildItem| 0 / 5 ||
Get-Content <file> \| Measure-Object| 5 / 5 ||
$PSVersionTable.PSVersion| 5 / 5 |A pipe, or any non-read command, is enough to cross into the failing path. This is almost certainly why the same broken setup produces contradictory reports from different users depending on which command they happened to try first.
Important caveat on the
unelevatedworkaround I listed above — it is a degradation, not an equivalent fix. We measured what it costs before adopting it, and then rejected it. Posting the numbers so nobody takes it as a clean escape.Two measured costs of running
windows.sandbox=unelevated:Add-Type, or type cast fails inside an agent script.unelevatedsilently weakens them — a deny-read on a sensitive file becomes a no-op. OpenAI's own documentation also notes the non-admin mode "carries greater risk if prompt injected".There is also a footgun worth flagging on its own:
codex app-serversilently tolerates unknown-ckeys (measured). A configuration-based workaround therefore fails silently if the key is ever renamed upstream — the failure comes back with no signal at all.So the accurate framing is:
unelevatedis a workaround that degrades the security backend, acceptable only if you don't depend on the read-only tier or on full-language PowerShell.What we'd actually like from upstream: that the
elevatedbackend be able to launch an MSIX-packaged binary, or — failing that — that it refuse the packaged shell explicitly and fall back toSystem32\WindowsPowerShell\v1.0\powershell.exe, with an error message naming the shell as the cause.Access is deniedsends everyone hunting through account SIDs and permissions, which is where the seven existing reports went.For the record, the fix we shipped on our side keeps
elevatedand removes theWindowsAppsdirectories from the PATH of the child process we spawn — narrow, logged by name, and it leaves the sandbox backend intact.Independent confirmation from Codex Desktop on Windows (sanitized; user authorized sharing).
Environment:
26.721.4979.0Microsoft Windows NT 10.0.26200.00.146.0-alpha.3.1workspace-writesessionObserved on 2026-07-29 while running a read-only
rgverification:The command did not start. Retrying the same verification with the shell explicitly set to:
succeeded immediately (exit 0). This matches the packaged/WindowsApps PowerShell resolution condition described in this issue and provides a current Desktop-app reproduction. No credentials, customer data, or private workspace paths are included here.
Follow-up from the same sanitized Codex Desktop environment reported above (user authorized sharing).
During a longer implementation turn on 2026-07-29, the default command runner hit the same failure again on multiple independent calls, including:
rg ... | Select-Objectread-only inspection;Get-Date -Format ...call.Both failed before command execution with:
Immediately retrying through
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exesucceeded (exit 0) in each case. This confirms that the failure persists across repeated tool calls in the same Desktop session and is not specific to one repository command or pipeline. No credentials, customer data, or private workspace paths are included.Not a duplicate of #34872 — different failing mechanism.
#34872 is about Node canonicalizing absolute paths at startup and hitting
EPERMonlstatof workspace ancestors: a path-traversal / directory-access problem, where the fix is about which directories the sandbox grants.This issue is about process creation: under
windows.sandbox=elevated,CreateProcessAsUserWreturns error 5 when the target binary is MSIX-packaged, before any command runs. It reproduces on a target that lives inside the workspace, with no ancestor traversal involved, and it disappears by changing either the mode or the binary — neither of which is a path-permission change.Same platform and same subsystem, but the failing step and the fix differ. Keeping this one open.
---
@ffonsecabc — thank you for the independent confirmation, and for the second follow-up. Two details from your reports are worth pinning down for triage:
pwsh.exe(an MSIX execution alias), and the immediate retry through the inboxSystem32\WindowsPowerShell\v1.0\powershell.exesucceeds — which matches the packaged-vs-unpackaged boundary measured above;Get-Date), so it is not workload-dependent.That is a second environment, on a different Codex build, showing the same boundary.
Additional Codex Desktop reproduction on Windows.
Environment
26.721.41059C:\temp\codextest[windows] sandbox = "elevated"[windows] sandbox = "unelevated"Direct invocation failures
Direct PowerShell commands such as:
both fail with:
This reproduces under both
elevatedandunelevated; changing the sandbox setting did not alter the result.Control cases that succeed
returns:
and:
returns:
So on this machine:
cmd.exeworks.cmd.execan successfully launch PowerShell.CreateProcessAsUserWerror 5.This may be the same packaged-shell resolution defect described here, but the
unelevatedworkaround does not resolve it in Codex Desktop version26.721.41059. A practical current workaround is to retry commands throughcmd.exe /c, includingcmd.exe /c powershell -NoProfile -Command "...", rather than treating the direct PowerShell failure as complete shell unavailability.Follow-up from the same Codex Desktop reproduction:
returns:
while:
returns:
The Codex-injected PATH includes
C:\Users\antho\AppData\Local\Microsoft\WindowsApps, after the Windows PowerShell 5.1 directory. The direct runner nevertheless appears to resolvepwsh, which lands on the WindowsApps alias, while the explicit workaroundcmd.exe /c powershell -NoProfile -Command "Get-Location"succeeds through PowerShell 5.1.This strongly aligns the Desktop case with the packaged/MSIX
pwshresolution cause described in this issue. One nuance:[windows] sandbox = "unelevated"still did not fix direct invocation in Codex Desktop26.721.41059.I traced the default Windows shell-selection path on current
main.get_shell_path()accepts thewhich::which("pwsh")result before consulting the existing unpackaged PowerShell fallbacks. This means a WindowsApps/App Execution Alias can win even whenC:\Program Files\PowerShell\7\pwsh.exeor Windows PowerShell 5.1 is available.That appears consistent with the reproductions here. I would not assume the correct fix layer yet, though: shell detection is shared, whereas the incompatibility appears specific to the Windows sandbox spawn path. Would you prefer rejecting packaged candidates during default shell selection, or validating them at the elevated sandbox boundary so non-sandboxed Store PowerShell remains unaffected?
If you would like this addressed as an external contribution, please explicitly invite me to submit the focused fix and regression coverage.
Independent confirmation from Codex Desktop on Windows x64.
Environment
26.730.61639(MSIX package26.730.8199.0)0.147.0-alpha.1.210.0.26200[windows] sandbox = "elevated"7.6.4Reproduction
With the Microsoft Store/MSIX build of PowerShell 7 installed, the shell selected by Codex was the user-scoped app execution alias:
PowerShell itself resolved to the packaged binary:
Every sandboxed shell command failed before command execution:
The following were verified and did not resolve it:
CodexSandboxOfflineandCodexSandboxOnlineexisted and were enabled.codex-command-runnerlaunched.A/B confirmation
Installing the machine-wide MSI/WinGet build of the same PowerShell version changed resolution to:
After restarting Codex, the same command immediately succeeded inside the elevated sandbox:
This strongly confirms that Codex should detect and skip a user-scoped/MSIX
pwsh.exewhen using the Windows sandbox, fall back to a machine-wide shell, and surface an actionable error instead of generic Win32 error 5.Reproduced a matching failure in Codex Desktop on Windows (2026-08-06): spawned subagents consistently fail before any command executes with
CreateProcessAsUserW failed: 5 (Access is denied.), includingGet-Location,Get-Content, andrg. The root agent in the same workspace can run the same commands normally.The agent failure attempted the MSIX/WindowsApps
pwsh.exepath. This is therefore a strong duplicate/corroborating report for the restricted-token packaged-shell cause described here.I originally opened #37259 before finding this issue; closing it as duplicate.
I can reproduce this issue in Codex Desktop on Windows, and I have some additional diagnostics that may help.
Environment:
Failure:
Every agent shell command inside the workspace fails before the command itself starts with:
CreateProcessAsUserW failed: 5 (Access is denied.)
Minimal reproducer:
Get-Content .\package.json -TotalCount 1
The sandbox log shows that the actual launcher is:
C:\Users\<user>\AppData\Local\Microsoft\WindowsApps\pwsh.exe
This is the App Execution Alias / reparse point for the Store-installed PowerShell.
Additional findings:
I tested both:
[windows]
sandbox = "elevated"
and:
[windows]
sandbox = "unelevated"
Result in both cases:
0/8 basic read-only commands succeeded.
The agent runtime continued to launch:
C:\Users\<user>\AppData\Local\Microsoft\WindowsApps\pwsh.exe
and failed with the same CreateProcessAsUserW error 5.
I also changed the Codex Desktop integrated terminal shell from PowerShell to Command Prompt. This had no effect on the agent sandbox launcher; it continued to use the WindowsApps pwsh.exe alias.
The 8-command test included:
Because every sandboxed shell invocation fails, routine read-only work requires repeated escalation/approval. In one larger read-only audit this resulted in 41 approval requests.
This appears consistent with the packaged/MSIX PowerShell issue described here, but in Codex Desktop the agent appears to explicitly use:
%LOCALAPPDATA%\Microsoft\WindowsApps\pwsh.exe
I could not find a supported configuration option for changing the agent sandbox shell executable.
A possible fix would be for the agent shell resolver to avoid App Execution Alias / packaged PowerShell executables for sandboxed execution and fall back to a non-packaged shell such as:
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe
Full Access only bypasses the failing sandbox and does not fix the underlying issue.
Reproduced this on Codex Desktop on Windows and can confirm the PATH-based workaround works end-to-end, with one nuance worth flagging.
Environment:
C:\Program Files\PowerShell\7\pwsh.exe[windows] sandbox = "elevated"in config.tomlInitial datapoint (before the fix worked): with
where.exe pwshin my own interactive PowerShell session resolving the real MSIX binary (C:\Program Files\WindowsApps\Microsoft.PowerShell_7.6.4.0_x64__8wekyb3d8bbwe\pwsh.exe) ahead of the per-user alias, Codex Desktop's sandbox log still explicitly showed:followed by
CreateProcessAsUserW failed: 5 (Access is denied.). This looked like Codex was ignoring PATH order entirely and hard-resolving the per-user alias. Turned out that was an artifact of my own interactive shell (itself launched via the MSIX pwsh, which self-prepends its own directory to PATH) — not representative of the environment Codex's own process actually inherited.What actually fixed it: removing
C:\Users\chase\AppData\Local\Microsoft\WindowsAppsfrom PATH did work — but it had to be removed from both User and Machine scope (it was present, oddly, in both — Machine PATH had a duplicate of the per-user alias folder baked in alongside the expected systemprofile WindowsApps entry), and Codex Desktop had to be fully quit (allChatGPT.exe/codex.exeprocesses terminated, not just the window closed) before reopening, since PATH is only read at process start. A partial restart (window closed but background processes still alive) silently kept using the old, unfixed environment and still failed identically.After a genuinely clean restart with both WindowsApps PATH entries removed,
whoamisucceeded and returned the correct principal.Suggested addition to the fix: since this environment variable is process-inherited, any documentation or auto-detection logic should account for the fact that closing/reopening a chat window inside the Desktop app does not necessarily restart the underlying
codex.exe/ChatGPT.exeprocess tree — a full app quit is required for a PATH change to take effect.Separately (unrelated to this issue but hit along the way): also had to repair a corrupted
deny_read_acl_state.json(0-byte/NUL-filled) and grant a narrowly-scopedWriteAttributesACE onC:\Users\Defaultfor the sandbox's dedicatedCodexSandboxOffline/Onlineaccounts — those were separate, unrelated pre-existing issues on this machine, now resolved, mentioned here only in case anyone else hits multiple stacked sandbox issues at once and needs to rule them out independently.Independent reproduction from Codex Desktop on Windows, reported with user authorization.
Environment:
OpenAI.Codex_26.803.10989.0_x64__2p2nqsd0c76g00.144.1Windows 10 Pro, DisplayVersion25H2, build26200.9168, x64[windows] sandbox = "elevated"7.6.4Observed repeatedly during ordinary read-only repository work:
The requested Git/PowerShell command did not begin. Retrying through the approved escalated path completed the same read-only command, so this is below the repository or project harness layer.
Shell resolution evidence:
The failure appears intermittent only because some simple reads can complete without reaching the failing SpawnChild path; multiple independent child-start attempts failed before execution. Setting
login:falsedid not reliably change the outcome.The documented diagnostic path
%USERPROFILE%\.codex\.sandbox\sandbox.logis absent on this installation, and no othersandbox.logexists under%USERPROFILE%\.codex.This matches the packaged/MSIX PowerShell boundary described in this issue. The safest user-side remedy appears to be installing machine-wide PowerShell so
C:\Program Files\PowerShell\7\pwsh.exeis selected, then fully quitting and restarting Codex. Switching tounelevatedis not an equivalent fix because it weakens the sandbox and has not worked consistently for Desktop reports.Please make sandbox shell selection reject the WindowsApps/App Execution Alias target and fall back to a machine-wide PowerShell or the inbox Windows PowerShell, with an actionable error when only a packaged target is available.
Independent confirmation on current builds (user authorized public sharing; user/workspace paths omitted).
Environment
26.820.9563.0codex-cli 0.150.1workspace-writesandbox7.6.5installed side-by-side:Microsoft.PowerShell_7.6.5.0_x64__8wekyb3d8bbweC:\Program Files\PowerShell\7\pwsh.exeReproduction
The Codex process PATH resolves
pwshin this order:Direct/default PowerShell shell startup fails before command execution with:
The controls are deterministic in the same sandbox:
Additional finding: disabling the App Execution Alias is insufficient
I disabled the Store PowerShell
pwsh.exeentry under Windows App execution aliases, confirmed that the per-user alias file no longer exists, fully rebooted Windows, and restarted Codex. The failure persists because Codex's process PATH still contains the Store package's direct install directory ahead of the MSI directory.A process-local A/B test that removes only that direct Store package directory from PATH immediately succeeds:
This matches the
rust-v0.150.1resolver behavior:which("pwsh")wins before the hard-coded MSI fallback is considered. It would help if Windows sandbox shell resolution rejected an inaccessibleWindowsAppsresult and continued to the existing MSI fallback (C:\Program Files\PowerShell\7\pwsh.exe) before falling back to Windows PowerShell 5.1.