Windows: sandboxed exec leaks 3–5 lsass handles per command execution, degrading the whole OS over long sessions
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.)
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: "Anthropic Sans", system-ui, "Segoe UI", 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: "Anthropic Sans", system-ui, "Segoe UI", 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: "Anthropic Sans", system-ui, "Segoe UI", 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: "Anthropic Mono", ui-monospace, monospace; font-feature-settings: "calt" 0, "liga" 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: "Anthropic Sans", system-ui, "Segoe UI", 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: "Anthropic Sans", system-ui, "Segoe UI", 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: "Anthropic Mono", ui-monospace, monospace; font-feature-settings: "calt" 0, "liga" 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>