Confirmed root cause on Codex 0.147.0: missing inherited Window Station/Desktop access in a Windows OpenSSH Session 0
Nobody has claimed this yet.
Assessment
- Difficulty
- 5/5
- Estimated time
- Over a week
- Newbie friendliness
- 35/100
- Issue type
- Bug
- Clarity
- Mostly clear
- Activity status
- Active
- Tech stack
- rust
- Domain
- operating-systems, security
Research direction
Start with codex-rs/windows-sandbox-rs/src/elevated/runner_client.rs, then read the related command_runner/win.rs and desktop.rs launch flow. Reproduce the Session 0 failure and inspect the CreateProcessWithLogonW path and its inherited Window Station/Desktop context. Done means the runner bootstraps reliably, launch-specific access is cleaned up safely during concurrent launches, and the private desktop isolation remains intact.
Written by the indexing model from the issue text.
Description
Confirmed root cause on Codex 0.147.0: missing inherited Window Station/Desktop access in a Windows OpenSSH Session 0
I can reproduce the failure deterministically on Codex CLI 0.147.0 and have completed an A-B-A causal test.
The evidence indicates that the elevated sandbox bootstrap runner is launched with CreateProcessWithLogonW from a non-interactive OpenSSH Session 0, but the selected sandbox account is not granted access to the inherited service Window Station and Desktop.
This causes codex-command-runner-0.147.0.exe to fail during process initialization with 0xC0000142. Codex then waits 15 seconds for the runner pipe and reports a timeout.
All machine-specific names, full SIDs, usernames, and workspace paths below have been redacted.
Environment
- Codex CLI: official standalone stable
0.147.0 - Windows: Windows 11 x64, build
26200(10.0.26200.8457) - Remote transport: Windows OpenSSH
- Client: Codex desktop application launching the remote Codex app-server through SSH
- Host process session: Session 0
- Sandbox configuration:
windows.sandbox = "elevated"windows.sandbox_private_desktop = true
- Sandbox provisioning command completed successfully from an elevated PowerShell:
codex sandbox setup --elevated --current-user- exit code
0
- The same official Codex binary and sandbox configuration work from an interactive Session 1.
Original failure
The native elevated sandbox consistently fails over the SSH Session 0 path with:
windows sandbox failed: timed out after 15000ms connecting runner pipe-in
A representative reproduction command is:
$codex = "$env:USERPROFILE\.codex\packages\standalone\current\bin\codex.exe"
& $codex sandbox `
-P :workspace `
-c windows.sandbox=elevated `
-c windows.sandbox_private_desktop=true `
-C $PWD `
"$env:SystemRoot\System32\cmd.exe" `
/d /c "echo SESSION0_BASELINE_OK"
Baseline result:
BASELINE_EXIT=1
windows sandbox failed: timed out after 15000ms connecting runner pipe-in
The timeout is a downstream symptom. Windows records the earlier bootstrap failure in the System event log:
Application Popup
Event ID: 26
Process: codex-command-runner-0.147.0.exe
The application was unable to start correctly (0xc0000142).
0xC0000142 is the process/DLL initialization failure status.
Event timeline
The relevant events occurred in this order:
01:59:24.357 Elevated sandbox launch started
01:59:24.489 Sandbox setup/account refresh started
01:59:24.532 Setup completed, errors=[]
01:59:24.546 Filesystem ACL inspection/refresh started
01:59:24.553 Filesystem ACL step completed
01:59:24.562 command-runner helper cache/path resolved
01:59:24.566 Security event 4624: sandbox account successfully logged on
01:59:24.609 System event 26: command runner failed with 0xC0000142
01:59:39.575 Sandbox logon session ended after the 15-second pipe wait
The active sandbox log was the dated file:
%USERPROFILE%\.codex\.sandbox\sandbox.2026-08-09.log
This shows that provisioning, account lookup, credential logon, filesystem ACL handling, and runner path resolution all completed before the runner initialization failure.
Session 0 Window Station/Desktop state
The SSH-hosted Codex process was running on:
Session ID: 0
Window Station: Service-0x0-<LUID>$
Desktop: Default
Before the causal test, the Window Station and Desktop DACLs contained access entries for:
<interactive-user>
BUILTIN\Administrators
They contained no access entry for either native Codex sandbox account:
CodexSandboxOffline
CodexSandboxOnline
Both sandbox accounts existed and were enabled.
Their direct local group membership was limited to:
CodexSandboxUsers
BUILTIN\Users
The CodexSandboxUsers group contained exactly the two native sandbox accounts.
Account and logon-policy checks
The sandbox accounts effectively received:
SeInteractiveLogonRight
SeNetworkLogonRight
No applicable deny-logon right applied to either account.
The Windows Security log recorded:
Event 4648: explicit credentials used
Event 4624: successful logon
Logon Type: 2
Account: CodexSandboxOffline
There was no corresponding event 4625 authentication failure.
Therefore, this was not caused by an invalid password, a disabled account, missing interactive logon rights, or an explicit deny-logon policy.
A-B-A causal test
I performed a reversible A-B-A experiment against the exact same SSH Session 0 and the exact same official Codex 0.147.0 binary.
A1 — Original DACL
No sandbox-account ACE was present on the current Session 0 Window Station or Desktop.
Result:
BASELINE_EXIT=1
windows sandbox failed: timed out after 15000ms connecting runner pipe-in
B — Add only the missing sandbox-account access
I temporarily added an ACE for the CodexSandboxOffline account SID to the current inherited objects.
No group, user, service, Codex configuration, executable, or filesystem permission was changed.
The masks used were the standard non-interactive Window Station/Desktop masks:
Window Station: 0x000F006E
Desktop: 0x000F00CF
The exact same official sandbox command was then run with a different output marker.
Result:
PROBE_EXIT=0
SESSION0_DACL_CAUSAL_OK
There was:
no runner pipe timeout
no 0xC0000142 event for this launch
no stderr output
The native elevated sandbox therefore completed successfully inside the same SSH Session 0 after only the missing object access was supplied.
Restore
The original binary security descriptors were restored in a finally path.
Before/after SHA-256 checks were identical:
Window Station:
C22FE903AFC19D63F06DB090379CD5C98816F5CC45DCD86A530471BED2BF9365
Desktop:
F78C04E3B3BFC5F6322100CE288EB5678BC45E5576261724843C38E8A33446E1
Verification:
STATION_RESTORED_EXACT=True
DESKTOP_RESTORED_EXACT=True
A2 — Original DACL restored
After exact restoration, the same official command was executed again.
Result:
POST_RESTORE_EXIT=1
windows sandbox failed: timed out after 15000ms connecting runner pipe-in
The observed sequence was therefore:
missing ACE -> failure
temporary minimal ACE -> success
exact DACL restoration -> same failure returns
This demonstrates direct causality rather than correlation.
Interactive Session 1 control test
The same official Codex 0.147.0 executable, sandbox accounts, configuration, and machine succeeded when launched from an interactive Session 1:
SESSION1_NATIVE_OK
exit code 0
The firmware, virtualization state, installed Windows components, sandbox accounts, and Codex files were unchanged. The material difference was the inherited Windows session and GUI-object security context.
Source-code match
In Codex 0.147.0, the elevated runner bootstrap code creates a zeroed STARTUPINFOW, sets only cb, leaves lpDesktop null, and calls CreateProcessWithLogonW directly:
The corresponding current main implementation still follows the same launch sequence:
https://github.com/openai/codex/blob/main/codex-rs/windows-sandbox-rs/src/elevated/runner_client.rs
The private desktop is created later by the already-running command runner:
Therefore, changing windows.sandbox_private_desktop cannot fix this bootstrap failure. The runner must start successfully before it can create or use the final private desktop.
Windows API contract
Microsoft documents the relevant responsibility for CreateProcessWithLogonW:
By default,
CreateProcessWithLogonWcreates the new process on a noninteractive window station with a desktop that is not visible and cannot receive user input. To enable user interaction with the new process, you must specify the name of the default interactive window station and desktop,winsta0\default, in thelpDesktopmember of theSTARTUPINFOstructure. In addition, before callingCreateProcessWithLogonW, the application must add permission for the specified user account to the specified window station and desktop.
API documentation:
https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-createprocesswithlogonw
Microsoft also documents the dynamically created non-interactive service Window Station naming and default access model:
https://learn.microsoft.com/en-us/windows/win32/winstation/window-station-and-desktop-creation
Process-to-Window-Station association is documented here:
https://learn.microsoft.com/en-us/windows/win32/winstation/process-connection-to-a-window-station
In this case, lpDesktop is null, so the runner inherits the caller's Session 0 service Window Station/Desktop context. The selected sandbox account has not been granted access to those inherited GUI objects.
Other causes ruled out
The following were checked and did not explain the failure:
- Sandbox provisioning failure
- Missing or disabled sandbox accounts
- Incorrect sandbox account password
- Missing interactive logon right
- An applicable deny-logon policy
- Runner executable missing from cache
- Filesystem read/traverse ACL failure
- AppLocker
- effective policy contained no rule collections
- no AppLocker event matched Codex
- WDAC/Code Integrity
- no Code Integrity event matched
codex.exe,codex-command-runner, or.codex
- no Code Integrity event matched
- Firmware virtualization
- Hyper-V
- Windows Sandbox optional component
- WSL/WSL2
- The final Codex private desktop option
Firmware virtualization, Hyper-V, Windows Sandbox, and WSL2 are separate virtualization features. The failing native Codex path had already reached CreateProcessWithLogonW and the Windows GUI-object access boundary.
Why reboot appeared to change the behavior
The Service-0x...$ Window Station is a dynamic object associated with the non-interactive service logon session.
A temporary ACE applied directly to one instance is not a persistent Codex configuration. After reboot or service/session recreation, Windows creates a new service-session Window Station/Desktop using its normal DACL construction.
This explains why a previous temporary repair could work before reboot and disappear afterward.
Suggested upstream fix
The durable fix appears to belong in:
codex-rs/windows-sandbox-rs/src/elevated/runner_client.rs
Before calling CreateProcessWithLogonW, the runner launcher should:
- Resolve the account SID for the selected
sandbox_credsaccount, either Offline or Online. - Open the current inherited Window Station and Desktop.
- Add only the minimal required ACEs for that sandbox account.
- Keep those ACEs valid until the runner has connected its pipe and completed the bootstrap/
SpawnReadyphase. - Remove only the ACEs inserted by that launch.
- Handle concurrent Offline/Online launches with serialization or reference counting so one launch cannot remove another launch's ACE.
- Avoid replacing or restoring the entire DACL in a way that could overwrite unrelated concurrent ACL changes.
The final private desktop should remain enabled by default. These are two separate security layers:
Layer 1: bootstrap runner access to the inherited Session 0 objects
Layer 2: final sandbox command isolation on Codex's private desktop
Fixing Layer 1 should not weaken Layer 2.
Current machine state after testing
The diagnostic ACEs were removed and both original binary security descriptors were restored exactly.
No persistent workaround remains:
no scheduled task
no helper service
no sshd DefaultShell wrapper
no login script
no sandbox-account group change
no Codex executable modification
no persistent Window Station/Desktop ACE
As expected after restoration, the official native elevated sandbox still fails over the SSH Session 0 path and still succeeds in interactive Session 1.
This evidence strongly suggests that issue #27265 is a reproducible caller-side bootstrap ACL defect rather than an unsupported Windows configuration, virtualization problem, or machine-specific policy failure.
- Dominant language
- Rust
- Stars
- 125k
- Forks
- 19.5k
- Avg merge
- 1m
- Merged PRs (30d)
- 1k
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from openai/codex
-
enhancement remote
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
-
bug CLI windows-os
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
-
macOS sandbox blocks hw.optional.arm64 sysctl, causing Flutter to misdetect Apple Silicon as x64 Openbug CLI sandbox
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
-
bug CLI TUI
Difficulty 2/5 1-3 hours Newbie friendliness 90/100
-
CLI config enhancement skills
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 86/100
kwakseongjae/auto-hwp#319 ·
-
area:cli bug filter-quality good first issue priority:medium
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
-
Difficulty 1/5 Under an hour Newbie friendliness 72/100
bevyengine/bevy#25861 ·
-
comp-datalake
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
ClickHouse/ClickHouse#121222 ·
-
A-linter
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
oxc-project/oxc#26863 ·