Windows: sandboxed exec leaks 3–5 lsass handles per command execution, degrading the whole OS over long sessions

Open 💬 7 comments Opened Jul 15, 2026 by Tycos

What version of Codex CLI is running?

codex-cli 0.144.4

What subscription do you have?

Pro

Which model were you using?

gpt-5.6

What platform is your computer?

Microsoft Windows NT 10.0.26200.0 x64

What terminal emulator and version are you using (if applicable)?

No interactive terminal is involved. Codex is launched non-interactively by a Python automation harness as cmd.exe /c codex.CMD exec --cd <repo> --sandbox workspace-write --json --output-last-message <file> --model <model> -c model_reasoning_effort="..." -, with the prompt piped to stdin and stdout/stderr captured. No multiplexer (no tmux/screen/zellij). For manual use: Windows Terminal + PowerShell 7 on Windows 11 Pro 26200.

Codex doctor report

codexVersion: 0.144.4, overallStatus: ok

What issue are you seeing?

On Windows, sandboxed codex exec leaks handles in the OS security process lsass.exe — roughly 3–5 handles per command execution the agent runs. Over a long agentic session (hours to days, several parallel agents) lsass.exe climbs to 80,000+ handles (normal is 1,500–4,000). Because lsass is on the path of every security operation (process creation, token checks, ACL evaluation), the whole machine becomes progressively laggy.

Killing all codex/node/pipeline processes does not recover it, and Task Manager shows no CPU or RAM anomaly — the leaked handles live in lsass, which cannot be restarted, so only a reboot clears it. This makes it easy to misdiagnose as an app-level problem.

Reproduced identically on codex-cli 0.144.1 and 0.144.4. Not thread-specific — it scales with the number of executed commands across all sessions, so no single thread id is meaningful.

What steps can reproduce the bug?

On Windows 11 (26200), codex-cli 0.144.4, attach the standalone script below and run it twice:

pwsh -File repro-lsass-leak.ps1 -SandboxMode workspace-write
pwsh -File repro-lsass-leak.ps1 -SandboxMode danger-full-access
It launches one codex exec ... --json - session whose prompt makes the agent run ~50 trivial echo commands one per step, measuring the lsass.exe handle count (median of several samples) before and after and dividing by the number of command_execution events.

Measured on my machine:

workspace-write: +225 lsass handles over 100 command executions = +2.25/exec
danger-full-access: −51 over 151 executions (flat, no leak)
(Full script pasted below / attached.)

repro-lsass-leak.ps1.txt

What is the expected behavior?

Handles/tokens/logon-session references acquired to set up the per-command Windows sandbox (restricted token / AppContainer) should be released when each command finishes. lsass.exe handle count should stay flat across a long run regardless of how many commands the agent executes.

Additional information

<html>
<body>
<!--StartFragment--><p dir="ltr" style="box-sizing: border-box; border: 0px solid color(srgb 0.0431373 0.0431373 0.0431373 / 0.1); margin: 0px; padding: 0px; outline-color: rgb(37, 107, 193); scrollbar-width: thin; scrollbar-color: rgba(31, 31, 30, 0.35) rgba(0, 0, 0, 0); text-rendering: optimizelegibility; color: rgb(110, 108, 104); font-family: &quot;Anthropic Sans&quot;, system-ui, &quot;Segoe UI&quot;, Roboto, Helvetica, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; white-space: normal; background-color: rgb(253, 253, 252); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;">Controlled A/B on identical workload isolates it to the Windows sandbox setup path:</p><div dir="ltr" class="overflow-x-auto" style="box-sizing: border-box; border: 0px solid color(srgb 0.0431373 0.0431373 0.0431373 / 0.1); margin: 0px; padding: 0px; outline-color: rgb(37, 107, 193); scrollbar-width: thin; scrollbar-color: rgba(31, 31, 30, 0.35) rgba(0, 0, 0, 0); overflow-x: auto; text-rendering: optimizelegibility; color: rgb(110, 108, 104); font-family: &quot;Anthropic Sans&quot;, system-ui, &quot;Segoe UI&quot;, Roboto, Helvetica, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; white-space: normal; background-color: rgb(253, 253, 252); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;">
Condition | Command rate | lsass handles
-- | -- | --
--sandbox workspace-write | ~47/min | +155/min (+775 over 5 min)
--sandbox danger-full-access | ~39/min | flat (82,700 → 82,541 over 15 min / 584 executions)

</div><p dir="ltr" style="box-sizing: border-box; border: 0px solid color(srgb 0.0431373 0.0431373 0.0431373 / 0.1); margin: 0px; padding: 0px; outline-color: rgb(37, 107, 193); scrollbar-width: thin; scrollbar-color: rgba(31, 31, 30, 0.35) rgba(0, 0, 0, 0); text-rendering: optimizelegibility; color: rgb(110, 108, 104); font-family: &quot;Anthropic Sans&quot;, system-ui, &quot;Segoe UI&quot;, Roboto, Helvetica, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; white-space: normal; background-color: rgb(253, 253, 252); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;">Additional controls, same machine: 300 plain<span> </span><code data-epitaxy-inline-code="" style="box-sizing: border-box; border: 0px solid color(srgb 0.0431373 0.0431373 0.0431373 / 0.1); margin: 0px; padding: 0px; outline-color: rgb(37, 107, 193); scrollbar-width: thin; scrollbar-color: rgba(31, 31, 30, 0.35) rgba(0, 0, 0, 0); font-family: &quot;Anthropic Mono&quot;, ui-monospace, monospace; font-feature-settings: &quot;calt&quot; 0, &quot;liga&quot; 0; font-variation-settings: normal; font-size: 13px; font-variant-ligatures: none; text-rendering: optimizelegibility; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(10, 10, 10, 0.04); color: rgb(10, 10, 10); border-radius: 4px; padding-block: 1px; padding-inline: 2px; line-height: 1.4;">CreateProcess</code><span> </span>spawns → no lsass growth; 200 schannel TLS handshakes → no lsass growth. So it's neither generic process creation nor TLS — it's specific to the sandboxed exec path, and disabling the sandbox makes the leak vanish entirely.</p><p dir="ltr" style="box-sizing: border-box; border: 0px solid color(srgb 0.0431373 0.0431373 0.0431373 / 0.1); margin: 0px; padding: 0px; outline-color: rgb(37, 107, 193); scrollbar-width: thin; scrollbar-color: rgba(31, 31, 30, 0.35) rgba(0, 0, 0, 0); text-rendering: optimizelegibility; color: rgb(110, 108, 104); font-family: &quot;Anthropic Sans&quot;, system-ui, &quot;Segoe UI&quot;, Roboto, Helvetica, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; white-space: normal; background-color: rgb(253, 253, 252); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;">Suspected area: per-command restricted-token / AppContainer creation not releasing a token or logon-session handle.</p><p dir="ltr" style="box-sizing: border-box; border: 0px solid color(srgb 0.0431373 0.0431373 0.0431373 / 0.1); margin: 0px; padding: 0px; outline-color: rgb(37, 107, 193); scrollbar-width: thin; scrollbar-color: rgba(31, 31, 30, 0.35) rgba(0, 0, 0, 0); text-rendering: optimizelegibility; color: rgb(110, 108, 104); font-family: &quot;Anthropic Sans&quot;, system-ui, &quot;Segoe UI&quot;, Roboto, Helvetica, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; white-space: normal; background-color: rgb(253, 253, 252); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;">Workaround:<span> </span><code data-epitaxy-inline-code="" style="box-sizing: border-box; border: 0px solid color(srgb 0.0431373 0.0431373 0.0431373 / 0.1); margin: 0px; padding: 0px; outline-color: rgb(37, 107, 193); scrollbar-width: thin; scrollbar-color: rgba(31, 31, 30, 0.35) rgba(0, 0, 0, 0); font-family: &quot;Anthropic Mono&quot;, ui-monospace, monospace; font-feature-settings: &quot;calt&quot; 0, &quot;liga&quot; 0; font-variation-settings: normal; font-size: 13px; font-variant-ligatures: none; text-rendering: optimizelegibility; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(10, 10, 10, 0.04); color: rgb(10, 10, 10); border-radius: 4px; padding-block: 1px; padding-inline: 2px; line-height: 1.4;">--sandbox danger-full-access</code><span> </span>avoids the leak but removes filesystem isolation; otherwise reboot between long runs.</p><!--EndFragment-->
</body>
</html>

View original on GitHub ↗

7 Comments

jrf1001 · 19 days ago

Still happens, 65,220 handles leaked over 169 hours

Codex app: 26.803.5235.0
Sandbox CLI: 0.147.0-alpha.6.5

AI Report:

The failure chain is:

  1. Every sandboxed command starts a runner under CodexSandboxOnline or CodexSandboxOffline.
  2. Codex does this with CreateProcessWithLogonW, creating a fresh Windows logon/token instance for each invocation. The current source shows that directly.
  3. LSASS accumulates the resulting \\HOSTNAME\CodexSandboxOnline:<unique-id> impersonation-token handles.
  4. Those token/logon-session references are not reclaimed when the command runner exits.

I reproduced the accumulation with trivial sandbox launches; the test children were all gone while LSASS remained above its pre-test count.

Codex does close the process and thread handles returned by CreateProcessWithLogonW. Therefore, the strongest current conclusion is that the leak lives in the per-command CreateProcessWithLogonW/LSASS logon-session cleanup path—or in Codex’s choice to create a fresh logon every command—not an obvious forgotten CloseHandle(pi.hProcess). Microsoft documents that API as performing the user authentication and returning only process/thread handles. Microsoft API reference

d0j · 8 days ago

Current latest-build reproduction: 3,784 CodexSandboxOffline token handles in LSASS and 14.5 GiB of kernel pool (Windows 11 build 26200)

Executive summary

I have a fresh, independently measured instance of this failure on a high-memory Windows 11 workstation running a current Codex Desktop build. This is not ordinary user-mode memory growth and not simple CPU, disk, or RAM exhaustion.

After 29.2 hours of uptime:

  • lsass.exe had 20,794 handles.
  • Microsoft Sysinternals Handle enumerated 3,907 Token handles in LSASS, of which 3,784 (96.85%) were explicitly named <machine>\CodexSandboxOffline:<unique-id>.
  • WMI reported 3,794 total logon sessions, including 3,788 interactive sessions. Exactly 3,784 of those sessions belonged to CodexSandboxOffline; all 3,784 were interactive logon type 2 and none had an associated live process. The exact 1:1 match between orphaned CodexSandboxOffline sessions and named LSASS token handles is highly significant.
  • The Appinfo service host had 41,207 handles, including 40,804 Token handles; a follow-up sample found 40,831 tokens for the interactive user plus one SYSTEM token. I am reporting this as secondary evidence, not yet claiming that every Appinfo token was created by Codex.
  • Windows kernel pools had reached 9.369 GiB paged + 5.140 GiB nonpaged = 14.509 GiB.
  • The whole desktop was visibly degraded even though an 8-second performance sample averaged only 4.85% CPU, 1.27% disk time, a zero processor queue, and approximately 57.1 GiB of available RAM.

The impact is system-wide and persists after command runners exit. LSASS cannot be restarted safely, and the accumulated logon/token/kernel state is only reliably reclaimed by rebooting Windows.

Severity: Critical operational reliability defect for sustained native-Windows agent sessions. This is a reboot-required resource-exhaustion failure affecting the entire desktop. I am not classifying it as a security vulnerability or claiming data loss.

This appears to be the same underlying defect as #35940 and is related to #34575. #34062 describes an older/profile-loading stall variant, but current main passes dwLogonFlags = 0, so profile loading is not the direct current-code hypothesis. The separate Desktop Git/process-token amplification tracked in #30926 may worsen kernel pressure, but the LSASS evidence below is independently and explicitly attributable to CodexSandboxOffline.

Environment

| Item | Value |
|---|---|
| OS | Windows 11 Pro x64 |
| OS version | 10.0.26200 |
| Full build | 26200.9168 |
| Uptime at snapshot | 29.2 hours |
| CPU | AMD Ryzen AI MAX+ PRO 395, 16 cores / 32 logical processors |
| RAM | 95.78 GiB |
| GPU | AMD Radeon 8060S, driver 32.0.22050.4002 |
| Registered Codex Desktop MSIX | OpenAI.Codex_26.814.5167.0_x64 |
| Staged but not yet registered MSIX | OpenAI.Codex_26.814.5517.0_x64 |
| Embedded Codex version string in both MSIX packages | 0.148.0-alpha.15 |
| Latest stable CLI checked | rust-v0.148.0 (3ba0f711642a) |
| Latest prerelease checked | rust-v0.149.0-alpha.1 (c767040aebb8) |
| Current upstream main checked | d1d51f6315f8 |
| Defender engine/platform | 1.1.26070.7 / 4.18.26070.9 |
| Defender state at snapshot | AV registered; real-time and behavior monitoring disabled |

Loaded filesystem minifilters at the snapshot were bindflt, UCPD, WdFilter, Gemma, storqosflt, wcifs, gameflt, CldFlt, bfs, FileCrypt, UnionFS, npsvctrig, Wof, and FileInfo. This is included as a possible kernel-pool confounder; it does not explain the explicit CodexSandboxOffline token names retained by LSASS.

Relevant local configuration at the time of the forensic snapshot:

sandbox_mode = "danger-full-access"
approval_policy = "on-request"

[windows]
sandbox = "elevated"

This configuration detail matters: the accumulated sessions were created by tasks that used the native elevated Windows sandbox. The current reporting task was running with full access, so it did not invoke the elevated backend during the boundary measurement below.

The MSIX was updated during the same Windows boot, so the cumulative 3,784-session backlog may include sessions created by the immediately preceding Desktop build. I cannot assign every retained session exclusively to 26.814.5167.0 because Windows exposes no creation timestamp per retained token in this snapshot. However, CodexSandboxOffline last logged on at 15:44:41 while 26.814.5167.0 was the active registered package, so the current build demonstrably continued to exercise this logon path. The staged 26.814.5517.0 package has not yet been executed and is assessed below only by read-only package/source comparison.

Fresh forensic snapshot

Timestamp: 2026-08-19T15:56:57+03:00

| Counter | Value |
|---|---:|
| Processes | 444 |
| Total visible process handles | 254,888 |
| lsass.exe handles | 20,794 |
| lsass.exe private memory | 35.1 MiB |
| Appinfo service-host handles | 41,207 |
| System handles | 11,860 |
| Total logon sessions | 3,794 |
| Interactive logon sessions | 3,788 |
| CodexSandboxOffline logon sessions | 3,784 |
| CodexSandboxOffline sessions with an associated process | 0 |
| Paged pool | 9.369 GiB |
| Nonpaged pool | 5.140 GiB |
| Committed memory | 58.810 GiB |
| Available physical RAM | 57.45 GiB |

The small LSASS private working set is important: this is not a conventional LSASS heap leak. The abnormal state is handle/logon-session/token retention plus kernel-pool pressure.

LSASS handle classification

Collected with Microsoft Sysinternals Handle 5.0 downloaded from download.sysinternals.com:

  • Authenticode status: Valid
  • Signer: Microsoft Corporation
  • SHA-256 of handle64.exe: 24BAFCC570CC9BBB6B6E6652A57A519E0464E3996891AABA6F55299CCE20B04F
LSASS total handles enumerated:       20,794
LSASS Token handles:                   3,907
CodexSandboxOffline Token handles:     3,784
CodexSandboxOnline Token handles:          0

Sanitized examples:

Token  <machine>\CodexSandboxOffline:<unique-id-1>
Token  <machine>\CodexSandboxOffline:<unique-id-2>
Token  <machine>\CodexSandboxOffline:<unique-id-3>
Token  <machine>\CodexSandboxOffline:<unique-id-4>
Token  <machine>\CodexSandboxOffline:<unique-id-5>

Owner grouping for LSASS Token handles:

3,784  <machine>\CodexSandboxOffline
   70  <machine>\<interactive-user>
   38  NT AUTHORITY\SYSTEM
   11  NT AUTHORITY\LOCAL SERVICE
    3  NT AUTHORITY\NETWORK SERVICE
Logon-session/process association proof

I joined Win32_LoggedOnUser, Win32_LogonSession, and Win32_SessionProcess rather than inferring orphaning only from process counts:

Win32_LoggedOnUser associations:                 3,794
CodexSandboxOffline associations:                3,784
Unique CodexSandboxOffline logon IDs:            3,784
CodexSandboxOffline interactive logon IDs:       3,784
CodexSandboxOffline sessions with any process:       0
CodexSandboxOffline orphan sessions:             3,784
Total Win32_SessionProcess associations:            413

Therefore, all 3,784 CodexSandboxOffline sessions were orphaned at the time of measurement. Their count exactly matched the 3,784 named CodexSandboxOffline Token handles retained by LSASS. They represented 99.89% of all interactive logon sessions on the machine.

The local sandbox accounts and group were present and enabled:

CodexSandboxOffline  enabled, last logon 2026-08-19 15:44:41 local time
CodexSandboxOnline   enabled, last logon 2026-07-09 17:44:51 local time
CodexSandboxUsers    contains both accounts

No passwords, machine SID, personal paths, repository names, or user account names are included here.

Appinfo secondary-token pressure

PID 8912 was confirmed through Win32_Service to host only the running Appinfo (Application Information) service at this snapshot.

Appinfo service-host total handles: 41,207
Appinfo Token handles:              40,804
CodexSandboxOffline names:               0

A follow-up sample grouped 40,831 of those token handles under the interactive user and one under SYSTEM. This may be a downstream effect of extreme process-creation/elevation churn, but I do not have a per-token creator trace, so it should be investigated separately rather than assumed to be exclusively Codex-owned.

Boundary measurement: accumulated elevated state vs current full-access task

During a 16.2-second boundary sample while the current task was running in full-access mode:

LSASS handles:  20,814 -> 20,806  (delta -8)
Logon sessions:  3,794 -> 3,794   (delta  0)
Appinfo handles: 41,261 -> 41,263  (delta +2)

This is consistent with the existing controlled A/B in this issue: danger-full-access does not create new CodexSandboxOffline logon sessions. It does not repair or reclaim the thousands of sessions already accumulated by the elevated sandbox.

It also supports the state-dependent observation in #35940: a short test can appear flat while the machine still contains a large persistent backlog. A post-reboot soak test is required; a few invocations on a clean boot are not a sufficient regression test.

Latest-build and source audit

I checked whether a newer build already contains a fix.

  1. The registered Desktop package is 26.814.5167.0.
  2. Windows has already staged 26.814.5517.0, but it is not registered while the current app is open.
  3. Both packages contain the same embedded Codex version string: 0.148.0-alpha.15.
  4. The two Desktop bundles most relevant to Git/process discovery are byte-identical between the registered and staged builds:
.vite\build\worker.js
  size:   1,850,139 bytes
  SHA256: a85d5425b975d0f2ce050befa4194efc6a9a9d3f34e1a350b5fd8017a33de689

.vite\build\child-process-snapshot-worker.js
  size:     692,061 bytes
  SHA256: 2f696b523647878440101c35969c6fd3af7d378c017d2b085183c73114ea695a

The semantic string additions found in the staged main bundle concern Claude Cowork history import limits/errors, not Windows sandbox, LSASS, logon-session, Git-refresh, WMI, or process-lifecycle handling. This does not prove that every binary in the staged MSIX is identical; it narrows the inspected Desktop changes and avoids treating the staged update as evidence of a fix.

  1. More importantly for this issue, the upstream elevated runner source file is byte-identical across the last stable release, current stable release, latest prerelease, and current main:
codex-rs/windows-sandbox-rs/src/elevated/runner_client.rs
SHA256: 8d22e6acb74148bf2d8f2b81bbeccc2fd0bdaf89310e772119f9c2f2fd9e7b0c

rust-v0.147.0          be6e8eac029b  identical
rust-v0.148.0          3ba0f711642a  identical
rust-v0.149.0-alpha.1  c767040aebb8  identical
main                   d1d51f6315f8  identical

The CreateProcessWithLogonW path remains in that file. At current main lines 346-353, the code explicitly says sandbox users have no profile state to inherit and passes /*dwlogonflags*/ 0; this is not the LOGON_WITH_PROFILE path. Source: https://github.com/openai/codex/blob/d1d51f6315f8/codex-rs/windows-sandbox-rs/src/elevated/runner_client.rs#L346-L353. The current 0.148.0 release notes do not list a fix for this LSASS/logon-session leak. At the time of checking, #33356, #35940, and #30926 were all open, unassigned, had no milestone, and had no linked development branch or PR.

Therefore, I cannot find evidence that 0.148.0, 0.149.0-alpha.1, current main, or the locally staged Desktop 26.814.5517.0 contains a fix for this failure mode.

Failure chain supported by the evidence

The strongest current interpretation is:

  1. Native Windows elevated sandbox commands run through the dedicated CodexSandboxOffline/CodexSandboxOnline accounts.
  2. The elevated runner uses CreateProcessWithLogonW(..., dwLogonFlags = 0, ...) for command execution. Current source explicitly does not load the sandbox user's profile.
  3. Each affected invocation creates or references a distinct Windows logon/token instance, visible as <machine>\CodexSandboxOffline:<unique-id> inside LSASS.
  4. Child processes and command-runner process/thread handles exit and are closed, but some token/logon-session reference remains alive.
  5. LSASS therefore cannot retire the interactive logon sessions. The sessions and security-token structures accumulate for the lifetime of the boot.
  6. Once the machine enters the degraded regime, security operations, process creation, ACL evaluation, Appinfo, DWM, and the kernel security pool become increasingly expensive. The visible symptom is whole-desktop lag without corresponding user-mode RAM, CPU, disk, or queue saturation.
  7. Exiting Codex prevents additional workload but does not reclaim the orphaned LSASS/kernel state. Reboot is the only reliable recovery currently observed.

The existing code already closes the PROCESS_INFORMATION process/thread handles returned by CreateProcessWithLogonW, so the investigation should not stop at another check for CloseHandle(pi.hProcess). The missing reference may be in profile/logon-session lifecycle, a retained duplicated token, Secondary Logon (seclogo) state, Appinfo interaction, or the architectural decision to perform a fresh interactive logon per command.

Where I recommend looking

  1. Instrument the sandbox invocation with the logon LUID. Correlate command ID, runner PID, token authentication ID/LUID, Security event 4624, and the corresponding 4634/logoff event. Assert that each session disappears after the runner and descendants exit.
  2. Audit all token duplication and ownership paths, not just process/thread handles: primary token, impersonation tokens, duplicated tokens, profile handles, broker/helper IPC, async error paths, timeout paths, and cancellation/kill paths.
  3. Do not anchor the current investigation on profile loading. Current main passes dwLogonFlags = 0. Confirm the deployed binary follows that source and investigate why the no-profile CreateProcessWithLogonW path still strands interactive logon sessions. Treat #34062 as a possibly related older variant, not proof of the present mechanism.
  4. Inspect Secondary Logon and Appinfo interactions. In the failed state, LSASS holds thousands of named Codex sandbox tokens while Appinfo holds tens of thousands of user tokens.
  5. Avoid a fresh interactive logon for every command. Consider one long-lived authenticated sandbox runner/token per session or another design that reuses a bounded logon session while preserving the required security boundary. A CreateProcessAsUserW-style child launch from a safely retained primary token may be worth evaluating, subject to the threat model.
  6. Test every termination path: normal exit, nonzero exit, timeout, cancellation, parent disconnect, app restart, concurrent sessions, shell grandchildren, piped stdio, and setup/helper restart.
  7. Add a long-duration Windows regression soak. A fresh-boot test of 5-20 launches is insufficient because #35940 reports state-dependent behavior. Track at minimum:
  • Win32_LogonSession count by type,
  • LSASS handle count,
  • LSASS token handles named CodexSandboxOffline/Online,
  • Appinfo token handles,
  • Toke, SeAt, SeTd, and SeDt kernel pool tags,
  • command count and concurrent sandbox count.
  1. Set a hard regression budget: after N completed sandbox commands and all descendants have exited, logon-session and named-token counts must return to a small bounded baseline. They must not scale with command count.
  2. Expose a supported mitigation/diagnostic. Until fixed, the app should warn when LSASS/logon-session counts exceed a threshold and provide a supported way to select a non-leaking execution backend without silently weakening network isolation.

Separate Git/process-churn observation and evidentiary boundary

I also captured a 15-second Win32_ProcessStartTrace sample because #30926 can produce a similar kernel-token signature:

All process starts: 164
git.exe starts:      26
conhost.exe starts:  20

However, in this particular window the observed Git parent chains were mostly another desktop development client, bash.exe, and nested git.exe processes. No direct Codex parent was captured in that 15-second sample. I am therefore not presenting this local Git sample as proof of the Codex Git-refresh bug. It is included to prevent conflating two simultaneous sources of process churn.

The LSASS evidence does not depend on that Git attribution: 3,784 token handles are explicitly named CodexSandboxOffline. The Desktop Git/process-token issue in #30926 remains a plausible independent amplifier and should stay a separate but cross-linked engineering track.

Reproduction and diagnostics

The least invasive live checks are:

$lsass = Get-Process lsass
$lsass | Select-Object Id, HandleCount, PrivateMemorySize64

$sessions = Get-CimInstance Win32_LogonSession
$sessions.Count
($sessions | Where-Object LogonType -eq 2).Count

# Microsoft Sysinternals Handle 5.0, elevated shell:
handle64.exe -nobanner -p $lsass.Id -a |
  Select-String 'CodexSandboxOffline|CodexSandboxOnline'

The active reproduction from #35940 can intentionally add leaked sessions and should be run only on a disposable/test boot:

function N { (Get-CimInstance Win32_LogonSession).Count }
$before = N
1..100 | ForEach-Object {
  codex sandbox -P :workspace -c windows.sandbox="elevated" -- cmd /c exit 0
}
"delta: $((N) - $before)"

For a valid fix verification, repeat the test after hours of real workload and concurrent sessions, not only immediately after reboot. Compare against danger-full-access and unelevated, while separately verifying filesystem boundaries, network isolation, and piped-child behavior; #35940 documents that unelevated may avoid the logon leak while weakening/breaking other required behavior.

Expected behavior

  • Completed sandbox commands must not leave interactive logon sessions or named token handles behind in LSASS.
  • LSASS, Appinfo, and kernel security-pool usage must remain bounded independently of command count and session duration.
  • Exiting a command, task, or the Desktop app must release all task-owned token/logon/profile references.
  • Native Windows isolation must remain functional without requiring periodic reboots.

Actual behavior

  • Thousands of distinct CodexSandboxOffline token handles and interactive logon sessions accumulate in LSASS.
  • Kernel paged/nonpaged pool grows to multi-gigabyte levels not explained by visible processes.
  • The entire Windows desktop becomes progressively sluggish despite low CPU/disk utilization and abundant available RAM.
  • Closing task runners or the app does not reclaim the accumulated state.
  • Recovery requires rebooting Windows.

Current workarounds and their limitations

  • danger-full-access avoids this elevated-sandbox path, but removes filesystem isolation and is safe only for trusted local repositories/workloads.
  • unelevated avoids the dedicated sandbox-account logon path, but #35940 reports weaker network isolation and failures for child processes using piped stdio.
  • WSL avoids the native Windows elevated runner and is the safest current option for long isolated workloads, but it changes the development environment.
  • Reboot clears the accumulated LSASS/kernel state but is not an acceptable operational mitigation for long-running agents.

I can provide additional sanitized Handle summaries and bounded post-reboot time-series measurements if maintainers specify the exact counters or ETW providers needed. Raw session databases, repository paths, command histories, machine SID, and account names are intentionally not included.

CodingLikeAMadMonkey · 5 days ago

Independent reproduction in Codex Desktop on Windows; the defect remains present in a newer command-runner build.

Environment (sanitized):

  • Windows 11 25H2, build 26200.9168, x64
  • Codex command runner: 0.149.0-alpha.4
  • Codex Desktop using the default workspace-write sandbox

Observed behavior:

  • After approximately 22 hours of tool-heavy Codex use, the entire Windows UI develops intermittent multi-second interaction delays. The condition persists after closing ordinary applications and restarting DWM and the display drivers. Only a full Windows restart has restored performance.
  • Aggregate resource availability is misleading: total CPU was approximately 28%, processor queue length averaged 0.2, GPU execution was approximately 5%, RAM remained available, and disk-backed paging was negligible.
  • The immediate degraded-state paths were LSASS at approximately 114% of one logical processor and DWM at approximately 133% of one logical processor.
  • LSASS held approximately 111,000 handles after 22 hours.

Read-only classification of the LSASS handle table using SystemExtendedHandleInformation found:

  • Semaphore: 87,834
  • Token: 21,931
  • Event: 279
  • ALPC Port: 253
  • Process: 201
  • Thread: 43

The almost exact 4:1 semaphore-to-token ratio indicates a repeated fixed bundle of four semaphore handles plus one token handle. This strongly matches the sandbox/restricted-token leak described in this issue.

Additional comparison:

  • After a clean restart, the system remained responsive under substantial workload.
  • After overnight Codex activity, system handles, kernel pools, LSASS CPU, and the LSASS semaphore/token counts were substantially elevated.
  • Closing Codex can stop additional command activity but does not reclaim objects already retained by LSASS, explaining the reboot-only recovery.

Privacy statement:

  • No project names, source code, prompts, command lines, usernames, hostnames, file paths, documents, trace files, screenshots, or raw logs are included in this report.

This defect causes progressive, system-wide Windows degradation during the long-running workloads Codex is specifically designed to perform. Please escalate it as a high-severity Windows sandbox resource leak, add an automated handle-leak regression test, and provide a safe mitigation that does not require disabling sandbox isolation or restarting Windows.

d0j · 4 days ago

Fresh regression on a newer Codex Desktop build: 4,209 retained sandbox logon sessions, 16.82 GiB of kernel pool, and whole-desktop lag

This is a fresh follow-up from the same Windows 11 machine, collected on 2026-08-23 between 17:04 and 17:18 UTC+03:00. The system is currently in the degraded state. The data below was collected read-only; no intentional sandbox leak canary was run.

Executive summary

The defect is still operationally severe on a newer Codex Desktop build:

  • Windows currently retains 4,209 interactive CodexSandboxOffline logon sessions.
  • A WMI association join found 4,204 fully orphaned sessions and only 5 sessions with any live process association.
  • lsass.exe has approximately 23,000 handles.
  • the service host containing only Appinfo has approximately 30,300 handles.
  • aggregate Windows kernel pools are approximately 11.29 GiB paged + 5.53 GiB nonpaged = 16.82 GiB.
  • the entire desktop is visibly sluggish even though current aggregate CPU, disk, paging, processor queue, DPC, and interrupt pressure are low.
  • closing ordinary applications does not recover responsiveness because the retained LSA/kernel state survives their exit. A full Windows restart remains the only reliable recovery observed.

This is not a normal user-mode memory leak and it is not explained by a busy foreground application. It is a system-wide, reboot-required resource-retention failure in the recommended native Windows sandbox path.

Environment

| Item | Value |
|---|---|
| OS | Windows 11 Pro x64 |
| OS build | 10.0.26200.9168 (26200 branch reported by WMI) |
| Uptime | approximately 32.1 hours |
| Device | HP ZBook Ultra G1a 14-inch Mobile Workstation |
| CPU | AMD Ryzen AI MAX+ PRO 395, 16 cores / 32 logical processors |
| RAM | 95.78 GiB |
| GPU | AMD Radeon 8060S, OEM driver 32.0.22050.4002 |
| Registered Codex Desktop package | OpenAI.Codex_26.818.5229.0_x64 |
| Desktop package installation time | 2026-08-22 13:01 UTC+03:00 |
| Running packaged codex.exe start time | 2026-08-22 15:29 UTC+03:00 |
| Global CLI | codex-cli 0.149.0 |
| Latest stable upstream release checked | rust-v0.149.0, published 2026-08-20 |

The retained backlog may include commands executed earlier in the same Windows boot, so I am not assigning all 4,209 sessions exclusively to one binary. However, the currently registered 26.818.5229.0 package was installed and its packaged codex.exe was running well before the most recent CodexSandboxOffline logons. Security events show new sandbox logons through 2026-08-23 15:58:32, so this newer Desktop build demonstrably continued to exercise the affected logon path.

Logon-session and orphan proof

klist sessions reported:

All listed logon sessions:       4,229
CodexSandboxOffline sessions:    4,209

The sessions are shown by Windows as NTLM:Interactive under the dedicated sandbox account.

A fresh join of Win32_LoggedOnUser and Win32_SessionProcess reported:

All Win32_LoggedOnUser associations:       4,228
CodexSandboxOffline associations:          4,209
Unique CodexSandboxOffline logon IDs:       4,209
Codex sessions with any live process:           5
Fully orphaned Codex sessions:              4,204

The five non-orphan sessions contained 82 old test-server descendants (56 python.exe and 26 conhost.exe). They are a separate process-lifecycle problem worth investigating, but they are not the immediate load source: the 56 Python processes used 0 CPU seconds over an 8-second sample, only 0.604 GiB private memory, and approximately 5,201 handles. They cannot explain the 4,204 fully orphaned sessions or the global UI degradation.

The retained portion of the Windows Security log contains:

CodexSandboxOffline event 4624 logons:    3,257
CodexSandboxOffline event 4634 logoffs:   2,181
Explicit logoffs (4647):                      0
Retained event interval: 2026-08-23 13:38:55 through 15:58:32 UTC+03:00

Older Security events have already rolled out of the log, so this event balance is only a lower-bound time slice. klist and the WMI associations provide the current retained-session count.

LSASS, Appinfo, DWM, and pool state

Fresh process snapshot:

| Process | Handles | Private memory | Working set |
|---|---:|---:|---:|
| lsass.exe | approximately 22,962-23,014 | 38.9 MiB | 50.0 MiB |
| svchost.exe hosting only Appinfo | approximately 30,311-30,366 | 7.8 MiB | 25.8 MiB |
| dwm.exe | 3,331 | 927.1 MiB | 396.0 MiB |

Aggregate kernel counters:

Pool paged bytes:       approximately 11.29 GiB
Pool nonpaged bytes:    approximately  5.53 GiB
Total:                  approximately 16.82 GiB

I also queried SystemPoolTagInformation directly (the same native information class used by PoolMon). The largest current tag buckets included:

| Tag | Paged | Nonpaged | Total | Likely subsystem boundary |
|---|---:|---:|---:|---|
| FMfn | 2.77 GiB | 0 | 2.77 GiB | Filter Manager/file-name state |
| Ntff | 2.19 GiB | 0 | 2.19 GiB | NTFS file-information state |
| File | 0 | 1.09 GiB | 1.09 GiB | kernel file objects |
| FMsl | 0 | 0.64 GiB | 0.64 GiB | Filter Manager stream-list state |
| MmSt | 0.62 GiB | 0 | 0.62 GiB | memory manager |
| Toke | 222.68 MiB | 0 | 222.68 MiB | token state |
| SeAt | 89.65 MiB | 0 | 89.65 MiB | security/audit state |
| SeTd | 17.52 MiB | 0 | 17.52 MiB | security state |
| SeDt | 7.77 MiB | 2.44 MiB | 10.21 MiB | security state |

This is an important evidentiary boundary: the explicit CodexSandboxOffline session/token retention is proven, but not every byte of the 16.82 GiB aggregate pool should be attributed to the Toke/Se* tags. The dominant FMfn/NTFS/File/FMsl buckets point to an additional filesystem-object or process/file-churn retention path that should be investigated alongside the logon-session leak, not dismissed as ordinary memory use.

A clean 15-second post-trace slope was approximately flat (+0.86 MiB paged, -1.56 MiB nonpaged), and the CodexSandboxOffline count remained exactly 4,209 across repeated full-access observations. This means the machine is currently carrying a large persistent backlog rather than showing a fast new-session slope in the present full-access task. Flat short-term growth does not reclaim or make the existing state harmless.

Loaded filesystem minifilters at the snapshot included bindflt, UCPD, WdFilter, Gemma, storqosflt, wcifs, gameflt, CldFlt, bfs, FileCrypt, UnionFS, npsvctrig, Wof, and FileInfo. This is included as a confounder inventory; it is not an attribution claim.

Performance evidence: severe UI lag without ordinary saturation

Six-second live counter sample:

Total CPU:                    10.79% average
Processor queue length:       0.00 average
Disk time:                    0.87% average
Current disk queue:           0.00 average
Available physical memory:   51.8 GiB
Pages/sec:                     1.32 average
Processor performance:      129.5% of nominal
DPC time:                      0.06%
Interrupt time:                0.27%

An independent 8-second per-process CPU-delta sample in the same degraded boot found:

dwm.exe:      1.21 logical cores
lsass.exe:    0.32 logical cores
Appinfo host: 0.00 logical cores during this short window

The DWM process currently accounts for approximately 5.95 GiB of GPU-process "dedicated usage" on this UMA system plus 0.12 GiB shared usage. This may be a secondary compositor-pressure symptom and should be kept separate from the proven sandbox-session leak.

I captured an official WPR trace using GeneralProfile.light + GPU.light + DesktopComposition.light + Power.light + Thermal.light:

Trace duration: approximately 17 seconds
Events:         4,738,357
Lost events:    0

Exclusive sampled CPU time included approximately:

ntoskrnl:                   27.297 CPU seconds
dwmcore + udwm + dwmcorei: 17.779 CPU seconds
amdkmdag:                    0.258 CPU seconds
dxgmms2:                     0.073 CPU seconds
dxgkrnl:                     0.067 CPU seconds

There have been zero Display event 4101 resets and zero WHEA events during the current boot. The CPU is not thermally/power limited, the disk is not queued, paging is negligible, and GPU kernel-driver CPU time is small. The immediate visible UI path is DWM, but there is no current evidence that an AMD TDR or hardware fault is the root cause of this degraded state.

Current release and source audit

  • 0.149.0 is still the latest stable Codex CLI release checked: https://github.com/openai/codex/releases/tag/rust-v0.149.0
  • this machine has global codex-cli 0.149.0 installed.
  • issues #33356 and #35940 remain open and unassigned.
  • current upstream main still contains CreateProcessWithLogonW(..., /*dwlogonflags*/ 0, ...) in codex-rs/windows-sandbox-rs/src/elevated/runner_client.rs.
  • the current file SHA-256 is still 8D22E6ACB74148BF2D8F2B81BBECCC2FD0BDAF89310E772119F9C2F2FD9E7B0C, identical to the previously checked affected release path.

Current source: https://github.com/openai/codex/blob/main/codex-rs/windows-sandbox-rs/src/elevated/runner_client.rs#L345-L356

Why this needs urgent engineering action

The official Codex Windows documentation describes elevated as the preferred native Windows sandbox and explains that it uses dedicated lower-privilege sandbox users. That recommended mode must support the long-running, command-heavy workloads Codex is designed for without progressively degrading the host OS until reboot:

https://learn.chatgpt.com/docs/windows/windows-sandbox

Full access, unelevated, or WSL are useful diagnostic/workaround boundaries, but they are not equivalent fixes:

  • Full access removes the filesystem isolation boundary.
  • unelevated is documented as weaker and has different network/child-process behavior.
  • WSL changes the execution environment.
  • rebooting only clears the accumulated failure state; it does not correct the defect.

Please treat this as a critical Windows operational-reliability defect and assign an owner/milestone. At minimum, the fix should include:

  1. a bounded logon/token architecture rather than a fresh interactive logon per command;
  2. explicit cleanup assertions for normal exit, failure, timeout, cancellation, parent disconnect, app exit, and descendant processes;
  3. a long-duration Windows regression soak that tracks logon-session count, named LSASS token handles, Appinfo handles, Toke/Se* tags, Filter Manager/NTFS/file-object tags, and child-process count;
  4. a hard post-command budget requiring all completed-command state to return to a small bounded baseline;
  5. an in-product warning before the machine reaches thousands of sessions or multi-GiB kernel-pool pressure;
  6. a supported recovery/mitigation that does not require silently weakening isolation or rebooting Windows;
  7. investigation of the separate descendant-process cleanup and filesystem-object retention paths shown above.

The present behavior makes sustained native-Windows development unreliable: the machine can have abundant free RAM, low CPU and disk utilization, and no hardware errors while the entire desktop becomes increasingly unresponsive. That is exactly the kind of failure that aggregate Task Manager percentages conceal, and it needs a real product fix rather than a documentation-only workaround.

I can provide sanitized WPR/Pool trace slices or additional bounded post-reboot A/B measurements if maintainers specify the exact tables/providers required. Raw traces are not attached because they can contain private process paths and command data.

grtninja · 3 days ago

Independent Windows exhaustion corroboration: ~240k system-wide handles + Win32 1816

I have a separate long-running Windows Codex incident whose coarse system state is strikingly close to the latest evidence in this issue:

  • 498 total processes
  • 8,304 total threads
  • 239,618 total open handles
  • large duplicate populations of Codex/helper descendants (node, node_repl, Python bridge/MCP helpers) under separate ownership tracing
  • later process creation repeatedly failed with Win32 error 1816: Not enough quota is available to process this command

This is especially notable next to the Aug 19 report here at 254,888 total visible process handles plus thousands of orphaned CodexSandboxOffline sessions/tokens.

I am not yet claiming the 239,618-handle machine has the same LSASS attribution. That machine's current incident recovery is deliberately capturing per-process handle counts, PID/PPID/start-time ownership, listeners, and Codex task/lease provenance before cleanup. The duplicate helper-process leak is independently real and is being tracked against #38754/#39982/#35485; the sandbox/LSASS path may be a second compounding source of the same eventual host exhaustion.

The operational end state is the same and worth making part of the Windows acceptance criterion: after a long native-Windows sandboxed agent session, a fresh CreateProcess must continue to work and system/LSASS handle and logon-session counts must remain bounded. A test that only proves child command runners exit is insufficient if LSASS retains per-command logon/token state.

I will follow up with the sanitized LSASS/Appinfo/logon-session delta from the affected machine if the ownership census confirms the same named CodexSandboxOffline pattern.

CodingLikeAMadMonkey · 2 days ago

Second-boot recurrence on embedded runner 0.149.0-alpha.4.1

After a clean restart and approximately 24 hours of Codex workload, the same system-wide intermittent UI lag recurred.

Elevated read-only snapshot:

  • Logon sessions: 13,360 total; 13,348 CodexSandboxOffline (99.91%); 0 online.
  • LSASS: 69,630 handles; 54,638 Semaphore; 13,561 Token; 4.03:1 ratio.
  • System: 394,603 handles; 7.57 GB kernel pools.
  • DWM: 1.06 CPU cores.
  • LP11/LP12: 83.0% / 77.5%; total CPU: 21.6%; average processor queue: 2.
  • Available RAM: 68.7 GB; GPU and disk were not saturated.
  • Previous recurrence: embedded runner 0.149.0-alpha.4; current recurrence: 0.149.0-alpha.4.1.

No canary or intentional leak was run. These are sanitized aggregate values from a read-only snapshot. No usernames, hostnames, session IDs, project names, paths, commands, logs, or traces are included.

MajesticMug · 1 day ago

Bump

This is causing severe performance issues during long sessions and the only way to release those orphaned resources is through a PC restart.

This should be a higher priority!