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

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

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 ↗

2 Comments

github-actions[bot] contributor · 1 month ago

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

  • #33010

Powered by Codex Action

enos9991-a11y · 1 month ago

I can confirm this independently on an affected Codex Windows desktop installation.

Environment

  • Codex Windows app: 26.707.3748.0
  • Native Windows sandbox
  • The delay occurs before the requested process does any work
  • No hostname, Windows username, or other identifying information is included

Minimal benchmark

Exact command:

cmd.exe /d /c exit 0

Observed end-to-end tool latency:

| Windows sandbox setting | Run 1 | Run 2 |
| --- | ---: | ---: |
| [windows] sandbox = "elevated" | 31.9 s | 35.9 s |
| [windows] sandbox = "unelevated" | 0.3 s | — |

All runs returned exit code 0. Changing only the Windows sandbox implementation removed more than 99% of the latency. This makes the elevated implementation unusable for normal agent work because the cost is paid on every small command.

Windows event correlation

On the affected elevated path, the end of the blank interval correlates with Security Event 4624 containing:

  • LogonType = 2
  • AuthenticationPackageName = Negotiate
  • LogonProcessName = seclogo
  • TargetUserName = CodexSandboxOffline
  • ProcessName = C:\Windows\System32\svchost.exe

The process sequence observed locally is consistent with Codex starting codex-command-runner.exe as CodexSandboxOffline through CreateProcessWithLogonW, with the command not beginning until the Secondary Logon path completes.

This event correlation does not, by itself, prove that the entire 30–50 second interval is specifically a Kerberos-to-NTLM fallback. That would require DNS/Kerberos ETW or a network trace. Profile loading, Secondary Logon/User Profile Service contention, or another operation inside the same logon path remain possible contributors. It does, however, strongly support the central finding in this issue: the delay is in the elevated cross-user runner launch, not in the requested command or workspace I/O.

Impact and requested behavior

A security boundary that adds 30–50 seconds to every command is effectively unavailable to users, so they are forced onto the weaker unelevated fallback.

In addition to removing unnecessary LOGON_WITH_PROFILE use if it is not required, please consider:

  1. timing and surfacing the runner-launch stages in diagnostics;
  2. a health check for pathological CreateProcessWithLogonW / Secondary Logon latency;
  3. a clear warning and optional automatic fallback to unelevated when elevated startup exceeds a reasonable threshold;
  4. a regression test/benchmark for cmd.exe /d /c exit 0 startup latency.

The unelevated workaround is effective here, but the current default preference for elevated makes this performance failure especially damaging.