Codex Desktop Remote SSH: unbounded reconnect loop leaks pwsh.exe on Windows host until it hard-freezes (1299 processes, 95% commit, 2 forced reboots)
Summary
When a remote SSH connection ("Connections" / remote machine) added in Codex Desktop fails to bootstrap against a Windows OpenSSH host, Codex retries the connection roughly every 90 seconds, forever, with no retry cap and no backoff. Each attempt spawns a pwsh.exe (+ conhost.exe) on the Windows host that never exits. Over ~1.5 days this accumulated to:
- 1299 ×
pwsh.exeand 1302 ×conhost.exe - ~43.26 GB of private memory held by PowerShell processes
- System commit charge 104.2 / 109.6 GB (95%), ~0.6 GB free of 32 GB physical RAM
- A paging/disk-I/O storm (single system-disk writes taking 36–260 s), Windows services timing out at 30 s, then SSH, ping and the whole machine becoming unresponsive
The Windows host hard-froze twice (Jul 11 ~01:54 and ~14:03 local time) and had to be power-reset. After each reboot the leak immediately started accumulating again, because the Desktop app kept retrying. The only mitigation was deleting the connection from the Codex Desktop app.
The client side leaks too: on the macOS machine running Codex Desktop, each retry orphaned the ProxyJump tunnel process, leaving 34+ ssh -W [host]:22 <jumphost> processes with PPID 1 accumulated over ~30 hours.
This effectively turns a misconfigured/failed connection into a remote denial-of-service against the user's own machine.
Environment
- Client (machine A): macOS (Apple Silicon), ChatGPT desktop app 26.707.41301 (bundled
codex-cli 0.144.0-alpha.4); standalone app-server~/.codex/packages/standalone/currentis codex-cli 0.144.1 - Remote (machine B): Windows 11, 32 GB RAM, native Windows OpenSSH, default shell resolves to PowerShell 7 (
pwsh.exe) - SSH route: client → jump host (Linux) → Windows host, via
ProxyJumpin~/.ssh/config
Steps to reproduce
- On machine A (macOS), have Codex Desktop set up and working.
- Add machine B — a Windows host whose OpenSSH default shell is PowerShell — as a remote SSH connection in Codex Desktop.
- The bootstrap fails (expected, see #22757 / #22965 — the POSIX login-shell probe is sent to PowerShell).
- Leave the connection configured. Codex Desktop retries ~every 90 s indefinitely.
- On the Windows host, watch
pwsh.execount grow monotonically; each process's command line contains the bootstrap probe:
````
Codex remote SSH requires SHELL to point to an executable login shell
- Within ~24–36 h the host exhausts commit charge and freezes.
The exact probe command observed (client side)
ssh -T -v -o BatchMode=yes -o ServerAliveInterval=15 -o ServerAliveCountMax=12 <host> sh -c 'if [ -z "$SHELL" ] || [ ! -x "$SHELL" ]; then echo "Codex remote SSH requires SHELL to point to an executable login shell" >&2; exit 127; fi; ... exec /bin/sh -c "$CODEX_REMOTE_PAYLOAD" ...' sh '...; PATH="${CODEX_INSTALL_DIR:-$HOME/.local/bin}:$PATH"; export PATH; codex app-server proxy'
On Windows, OpenSSH hands this to pwsh.exe, which fails to parse it — but the spawned pwsh.exe/conhost.exe pair is never torn down when the SSH session ends, and Codex never stops retrying.
Expected behavior
- Retries should be capped and/or use exponential backoff, and stop (with a visible error) after repeated bootstrap failures of the same kind — a deterministic
exit 127/ parse failure will never succeed on retry. - Each attempt must clean up after itself: the remote
pwsh.exe/conhost.exeand the localProxyJumpssh -Wchild should be terminated when the attempt fails or times out.
Actual behavior
- Infinite ~90 s retry loop that survives for days.
- Every attempt leaks one
pwsh.exe+conhost.exeon the Windows host and (intermittently) one orphanedssh -Won the macOS client. - The Windows host is driven into commit exhaustion → paging storm → complete freeze requiring power reset, repeatedly, until the user manually deletes the connection.
Diagnostics collected on the Windows host (before mitigation)
- 1299
pwsh.exe, 1302conhost.exe, all with near-identical command lines containing the bootstrap probe string - PowerShell private memory total ≈ 43.26 GB; commit 104.2/109.6 GB (95%); free physical ≈ 0.6 GB / 32 GB
- Event log: mass 30 s service timeouts; system disk writes taking 36–260 s
- No bluescreen/bugcheck codes; SSD SMART healthy, 43 °C — consistent with resource exhaustion, not hardware failure
Cleanup that worked (after deleting the connection on the client):
Get-CimInstance Win32_Process -Filter "Name='pwsh.exe'" |
Where-Object { $_.CommandLine -like '*Codex remote SSH requires SHELL*' } |
ForEach-Object { Stop-Process -Id $_.ProcessId -Force }
Related issues
- #22757 — Remote SSH to Windows OpenSSH fails when default shell is PowerShell (the failure mode that triggers this loop)
- #22965 — Remote SSH to native Windows host bootstrap assumes POSIX shell
Those cover the connection failure; this issue is about the unbounded retry + process leak that turns that failure into a machine-killing resource exhaustion on both ends.
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗