[Windows] Background shell child can exhaust system memory without visible lifecycle or resource safeguards

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

Summary

During a local Codex Desktop task on Windows, a background PowerShell child associated with a Codex shell tool call consumed tens of gigabytes of private memory and drove the machine into severe memory pressure. Terminating that exact process released the pressure immediately.

A subsequent evidence review strongly correlated the process with a background task launched through Codex. The review could not determine the process's object-level allocation source because no live memory dump or allocation trace had been captured before recovery.

The product-level concern is that a background child could consume enough resources to destabilize Windows without a visible resource ceiling, durable lifecycle record, or clear user-facing indication that the process remained active.

This report does not claim that PowerShell itself, Codex's internal PowerShell components, filesystem recursion, or the project script is a proven allocation root cause.

Environment

  • Product: Codex Desktop using the native Windows agent
  • Platform: Windows x64
  • Incident period: July 2026
  • Exact incident build: not captured
  • Workspace: local Git repository

The Windows username, repository identity, absolute paths, session identifiers, exact host fingerprint, prompts, source code, and raw Codex records are intentionally omitted.

Observed behavior

  • A PowerShell child associated with a Codex-launched background task reached tens of gigabytes of private memory.
  • Physical-memory pressure became severe and Windows page-file activity increased.
  • The task did not produce its expected final diagnostic artifact.
  • Terminating the exact high-memory process released the memory immediately.
  • The Codex transcript did not retain a complete child-process lifecycle record sufficient to prove the parent/child edge, final process state, or cleanup result from one durable record.

The process association is strongly supported by the relative timing of the Codex launch record, Windows PowerShell operational events, and task artifacts. It is not classified as fully proven because the child PID output and OS-level parent/command-line record were not durably available after the incident.

Scope and evidence boundaries

The local review established the following at a public-safe level:

  • Codex initiated a background local task through a shell tool.
  • A PowerShell process initialized immediately afterward and was associated with the expected task artifacts.
  • The shell tool returned while the background work continued.
  • The expected aggregate result was not produced.
  • The abnormal process later held tens of gigabytes of private memory.
  • Killing that exact process restored memory availability.

The review did not establish:

  • the exact managed or unmanaged object type holding the memory;
  • that the process was intentionally or accidentally detached by Codex;
  • that the process survived a specific task-completion event, because a timestamped live-PID readback was not captured at that boundary;
  • whether Codex Desktop/app-server applied an undocumented Windows process-containment mechanism;
  • whether producer-side output was fully buffered before transcript truncation;
  • whether the incident shares an allocation root cause with other Windows PowerShell reports.

The project task was also found to contain its own defensive-programming gaps. Those mechanics are deliberately omitted from this public report because they are not required to demonstrate the Codex-side lifecycle and resource-boundary concern. They can be shared privately with maintainers.

Reproduction status

The high-memory condition has not been deliberately reproduced because doing so could make the Windows host unusable.

No public reproduction recipe is included. A bounded lifecycle test and the original evidence can be provided privately to OpenAI maintainers. Any such test should use a harmless child process and strict external resource limits.

Expected behavior

For local tasks that create background descendants, Codex Desktop/app-server should:

  1. Keep a durable ownership record linking the tool call to the background process and its descendants.
  2. Make intentionally persistent background work visible and explicitly stoppable by the user.
  3. Apply bounded time and resource policies so one child cannot destabilize the operating system.
  4. On timeout, cancellation, task completion, client disconnection, or app shutdown, either clean up the owned process tree or clearly report that registered background work remains active.
  5. Verify and record the cleanup result instead of inferring completion only from the conversation or parent shell.
  6. Preserve bounded diagnostic tails and lifecycle metadata so failures remain attributable without publishing private task content.

Questions for maintainers

  1. What is the intended lifecycle contract for descendants created by a Windows shell tool call?
  2. Does current Codex Desktop apply Windows-native process-tree containment and resource limits to those descendants?
  3. Is there a supported way for a tool call to register background work so it appears in Codex's background-process controls?
  4. Which lifecycle fields should be present in a support bundle to prove launch, ownership, exit, cancellation, and cleanup?
  5. Can maintainers provide a private channel for the precise process timeline, source-derived task details, and retained local evidence?

Related reports

This incident may overlap with the following reports at the process-lifecycle or resource-boundary level, but it does not claim the same underlying allocation cause:

  • #29317 — extreme memory growth in a Windows PowerShell helper
  • #33913 — descendant-process and inherited-stream lifecycle hang on Windows
  • #34050 — repeated PowerShell activity followed by system-wide resource exhaustion
  • #34264 — a recursive shell task left a PowerShell process chain active
  • #34577 — completed shell calls left elevated PowerShell wrappers active

Evidence available privately

The following can be provided privately to OpenAI maintainers after confirming an appropriate disclosure channel:

  • exact process ID, sub-second timestamps, Windows build, and Codex package details;
  • the precise shell launch record and task-completion record;
  • PowerShell Operational event record identifiers and correlation metadata;
  • complete parent/child correlation reasoning and its remaining gaps;
  • source hash and bounded excerpts from the project-owned harness;
  • receive-loop implementation details, buffer behavior, cancellation behavior, and missing defensive bounds;
  • artifact timestamps and child-host metadata;
  • persisted-output size statistics;
  • the full local RCA with explicit evidence classifications;
  • a safe, externally bounded lifecycle reproduction plan.

No raw private repository files, complete session transcripts, SQLite databases, username-bearing paths, or exploit-oriented reproduction steps will be posted publicly.

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.

  • #34264
  • #35393
  • #35193

Powered by Codex Action

SwordFourteen · 27 days ago

Follow-up: second incident with sub-second Python lifecycle evidence (2026-07-31)

This follow-up materially strengthens the original report. In this incident, the retained Codex tool record and Windows Resource Exhaustion Detector events correlate an explicit python - launch with the surviving high-memory process at sub-second resolution.

Environment

  • Surface: Codex Desktop, native Windows execution through PowerShell
  • Incident app log reports release=26.727.40816
  • Currently installed package after later restart/update: OpenAI.Codex 26.727.6591.0
  • Bundled/local CLI: codex-cli 0.145.0
  • OS: Windows 11 Pro x64, 10.0.26200
  • RAM: 31.82 GiB
  • Windows PowerShell: 5.1.26100.8972
  • Python: 3.12.6

Local usernames, repository names, absolute paths, thread/turn identifiers, prompts, and complete transcripts are intentionally omitted.

Triggering command shape

The tool call launched PowerShell with timeout_ms: 600000; PowerShell piped an inline script to Python:

@'
import sympy as s
# Build exact rational-function matrix entries
# Repeated cancel(), exact symbolic determinant(), fraction(), substitution, and expand()
det = s.cancel(s.det(s.Matrix(rows)))
num, den = s.fraction(det)
num = s.Poly(s.expand(num.subs(q, 1 + u)), u)
'@ | python -

The SymPy workload was capable of severe symbolic expression growth. That explains why the process wanted large amounts of memory. The Codex defect reported here is narrower: after Codex explicitly reported the tracked script as terminated, the child Python process survived silently for almost four more hours.

Correlated timeline (UTC)

| Time | Retained evidence |
|---|---|
| 15:37:15.527 | Codex shell tool record launches the command containing python -. |
| 15:37:15.710 | Windows later records creation of python.exe, PID 100896, Python version 3.12.6150.1013—about 183 ms after the tool call. |
| 15:40:00.030 | Codex calls the yielded-cell wait operation with terminate: true. |
| 15:40:00.031 | Tool result: Script terminated (no cleanup warning and no surviving-child status). |
| 18:02 | Windows Event 2004 records the same PID and creation time still alive with 92,081,598,464 committed bytes (85.76 GiB). System commit is 116.83/116.94 GiB, 99.90%. |
| 18:11:02.535 | Codex Desktop log reports its in-app browser renderer gone with reason=memory-eviction. |
| 19:30:56 | The same Python PID reaches 110,102,011,904 committed bytes (102.54 GiB). System commit reaches 116.94/116.94 GiB, 99.99%. |

Windows emitted 19 Resource Exhaustion Detector Event 2004 records during the incident. The XML ProcessInfo/Process_1 entries consistently identify the same python.exe PID and the same CreationTime; this is committed memory (CommitCharge), not merely a large reserved address range.

Actual behavior

  1. Codex returned a successful-looking Script terminated result.
  2. The explicit Python descendant remained alive and continued allocating committed memory.
  3. There was no user-visible indication that cleanup had failed or that a descendant still existed.
  4. The surviving child drove total Windows commit to effectively 100%, causing page-file thrashing, application failures, and renderer eviction.
  5. Reinstalling/restarting the app cleared symptoms but does not address the lifecycle gap.

This differs slightly from #33913 and #35193: in those reports, a surviving descendant can keep the tool call blocked. Here, the tool call returned immediately, but the descendant survived silently. Both behaviors point to incomplete Windows process-tree ownership/cleanup.

Expected behavior

When a yielded shell execution is terminated, times out, is cancelled, or its session/app exits, Codex should:

  1. terminate the complete process tree owned by that tool call;
  2. verify that no owned descendants remain before returning Script terminated;
  3. if cleanup fails, return a distinct error containing the target PID(s) and cleanup status rather than a success-like message;
  4. retain bounded lifecycle metadata: root PID, descendant PIDs, creation time, termination reason, cleanup result, and peak committed bytes;
  5. provide a configurable per-command or per-job committed-memory ceiling, or at minimum warn and surface the process before it can destabilize the host.

Suggested Windows implementation direction

  • Run each shell execution in a Windows Job Object owned by the command runtime.
  • Assign the initial process before it can spawn descendants; prevent breakaway where compatible.
  • Use JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE and call TerminateJobObject for timeout/cancellation.
  • Consider configurable JOB_OBJECT_LIMIT_JOB_MEMORY / JOB_OBJECT_LIMIT_PROCESS_MEMORY limits or notification thresholds.
  • Bound cleanup time independently from stdout/stderr draining and report partial cleanup explicitly.

Safe regression test

A safe test does not need to recreate the 102.54 GiB condition. A parent process can spawn a harmless child that allocates a bounded amount (for example 128–256 MiB) and then sleeps. Terminate the tracked shell cell and assert that:

  • the child PID no longer exists;
  • the job has no active processes;
  • the tool result distinguishes successful tree cleanup from cleanup failure;
  • the test remains bounded by an external watchdog.

I can provide the sanitized Event 2004 XML fields and bounded excerpts of the Codex/app logs privately if maintainers identify an appropriate channel. I will not post the raw transcript because it contains local paths and private project content.