Windows elevated sandbox can stall for minutes loading a user profile per command

Open 💬 1 comment Opened Jul 18, 2026 by MarvinDontPanic

Environment

  • Codex CLI: 0.144.5 (current npm latest when reproduced on 2026-07-18)
  • OS: Windows 11 Core, 10.0.26200, x64
  • Sandbox: native Windows elevated sandbox
  • Model: independent; the delay occurs before the requested command starts
  • Terminal: PowerShell-based launcher; also reproduces with standalone codex sandbox
  • codex doctor --json: not attached because a host invocation did not return within 120 seconds

Problem

Every elevated-sandbox command launches codex-command-runner with CreateProcessWithLogonW(..., LOGON_WITH_PROFILE, ...). This synchronously loads the sandbox account's registry profile even though the runner does not consume that account's HKCU state.

On a healthy machine this adds only a fraction of a second. After sustained multi-session activity, the same call can block for minutes. During an observed stall:

  • the parent was blocked inside CreateProcessWithLogonW before Codex reached its 15-second runner pipe timeouts;
  • Windows Wait Chain Traversal showed a wait through \\RPC Control\\SECLOGON;
  • User Profile Service logged repeated loads of the sandbox account's ntuser.dat and UsrClass.dat hives;
  • ordinary host commands remained fast;
  • rebooting temporarily restored sub-second launches, but stock Codex continued loading a profile for every command.

This affects shell commands and native filesystem/apply-patch operations because they share the runner-launch path. Concurrent Codex sessions multiply the unnecessary profile loads; when Secondary Logon/User Profile Service becomes contended, a trivial command can wait for minutes even though the command and workspace drive are healthy.

The call is visible on current main here:

https://github.com/openai/codex/blob/35eaf3ffb0bf2001486c68c47a3d946b34d16634/codex-rs/windows-sandbox-rs/src/elevated/runner_client.rs

Microsoft documents that LOGON_WITH_PROFILE loads the user's profile and that profile loading is time-consuming:

https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-createprocesswithlogonw

Reproduction

  1. Provision the native elevated sandbox:

``toml
[windows]
sandbox = "elevated"
``

  1. Enable Microsoft-Windows-User Profile Service/Operational and record its latest event ID.
  2. From a trusted workspace, run:

``powershell
codex sandbox -c 'windows.sandbox="elevated"' -P :workspace -C $PWD -- cmd.exe /d /c "echo CODEX_SANDBOX_PROFILE_REPRO"
``

  1. Query new events containing CodexSandboxOffline.
  2. Repeat the command.

On stock 0.144.5, each command deterministically produces two event ID 5 hive-load events plus one event ID 67 profile event. The minutes-long contention is intermittent, but the unnecessary profile load occurs on every invocation.

Controlled evidence

I ran the same harmless echo command sequentially through stock 0.144.5 and a side-by-side patched build from current main, using the already-provisioned offline sandbox account to isolate events from other sessions.

| Runner | Successful runs | Exact output | Offline profile events |
| --- | ---: | --- | ---: |
| Stock 0.144.5 | 5/5 | CODEX_SANDBOX_OFFLINE_AB_OK | 15: exactly 3 per run |
| Patched current main | 5/5 | CODEX_SANDBOX_OFFLINE_AB_OK | 0 |

Stock latency was 240–277 ms and patched latency was 243–313 ms on the healthy post-reboot system. This is not presented as a healthy-state microbenchmark improvement: the material result is eliminating the operation captured blocking for minutes under contention.

Both builds also returned identical exit codes and child environment values, including an explicit IPC-propagated variable and USERPROFILE.

An otherwise equivalent direct Win32 call using the existing sandbox credential in memory with dwLogonFlags = 0 launched cmd.exe /c exit 0 in 57.81 ms, returned 0, and generated zero profile events. No credential was printed, persisted, or changed.

Proposed fix

Stop requesting the sandbox user's profile for the runner:

-use windows_sys::Win32::System::Threading::LOGON_WITH_PROFILE;
+const RUNNER_LOGON_FLAGS: u32 = 0;

-    LOGON_WITH_PROFILE,
+    RUNNER_LOGON_FLAGS,

Why this appears safe:

  • the runner's environment pointer is already null, so it inherits the caller environment;
  • the requested child environment is carried in SpawnRequest.env and explicitly passed to child creation;
  • the runner has no HKCU access; its only USERPROFILE use treats the inherited value as a filesystem location for the CWD junction;
  • patched online/offline and multi-root sandbox commands preserved output, exit status, environment propagation, credentials, and restrictions.

Validation

  • Full side-by-side Codex CLI and both Windows helpers built successfully from current main.
  • just fix -p codex-windows-sandbox and just fmt passed.
  • Focused crate tests: 131 passed. One legacy test failed and one timed out; both reproduced identically on untouched 35eaf3ffb0bf2001486c68c47a3d946b34d16634, so they predate and do not exercise this elevated-runner change.
  • Five isolated stock and five patched integration runs produced identical command behavior; profile events changed from 3 per stock run to 0 per patched run.

This is distinct from #18620, which concerns logon error codes, and #14585, which concerns ACL/path behavior.

Is loading the sandbox account's HKCU profile intentional for a dependency not visible in the current runner? If not, I have an atomic one-file implementation ready. Please explicitly invite a PR if this approach aligns with the intended architecture and you would like the patch submitted.

View original on GitHub ↗

This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗