ChatGPT Chrome Extension Causes a Controlled Renderer to Grow by ~0.65 GiB/min Until It Reaches 10+ GiB
What version of the Codex App are you using (From “About Codex” dialog)?
26.721.41059
What subscription do you have?
Plus
What platform is your computer?
_No response_
What issue are you seeing?
Summary
The official ChatGPT Chrome extension causes a controlled webpage renderer to consume memory at a sustained rate of approximately 0.65 GiB per minute during a Codex browser-control operation.
The affected renderer grew from 7.8 GiB to approximately 13.0 GiB in about eight minutes. It also consumed more than 80% CPU and forced approximately 12.4 GiB of memory into swap.
Terminating only the affected renderer immediately stopped the growth and reduced total Chrome child-process RSS from approximately 4–5 GiB to approximately 2.1 GiB. System-wide free memory recovered from approximately 32% to 56%.
This appears to be a renderer-side retention issue triggered by the extension's browser-control pipeline, rather than ordinary Chrome cache growth or a leak in the extension service worker alone.
Environment
- Date observed: July 29, 2026
- Operating system: macOS 26.5.2 (25F84)
- Architecture: Apple Silicon / ARM64
- Google Chrome: 150.0.7871.187
- ChatGPT Chrome extension ID:
hehggadaopoacecdllhhajmbjkdcmajg - ChatGPT Chrome extension version:
1.2.27221.15725 - Extension description:
Control Chrome with ChatGPT. - Extension background implementation: Manifest V3 service worker
- Chrome parent process PID during the reproduction:
37204 - Affected renderer PID:
77035 - Codex/ChatGPT desktop version: 26.721.41059
Impact
- Severe memory pressure and swap growth within minutes.
- Sustained high CPU usage.
- Potential system-wide UI stalls or hangs.
- Risk of out-of-memory termination or forced reboot.
- The problem can continue after a browser-control operation stalls or times out.
- Recovery currently requires terminating the affected renderer or restarting the extension/browser-control session.
What steps can reproduce the bug?
Steps to Reproduce
The precise prompt and target webpage can be added if needed, but the observed sequence was:
- Install and enable the official ChatGPT Chrome extension.
- Connect Codex/ChatGPT to the existing Chrome profile through the extension.
- Start a browser-control task that operates on an existing webpage.
- Allow Codex to inspect or manipulate the page using DOM, JavaScript evaluation, screenshot, page-context, or related browser-control operations.
- Observe Chrome processes in Activity Monitor or with
psandvmmap. - A newly created
Google Chrome Helper (Renderer)process begins using high CPU and grows by hundreds of MiB per minute. - The growth continues after the browser operation stalls or times out.
What is the expected behavior?
Expected Behavior
- Browser-control operations should use bounded memory.
- CDP commands and page-context operations should release temporary values when they complete, fail, time out, or are canceled.
- The extension should stop high-volume event producers and detach its debugger session when a turn or browser-control session ends.
- A failed DOM/evaluation operation should not leave the controlled renderer allocating memory indefinitely.
Actual Behavior
The controlled renderer continued allocating memory while using high CPU.
Additional information
Follow-up measurement
At approximately 2026-07-29 04:22 UTC+00:00:
Physical footprint: 12.9G–13.0G
Physical footprint (peak): 13.1G
Writable regions: 13.7G total, 12.9G written
Swapped out: approximately 12.4G
CPU: approximately 80% or higher
This is an increase of approximately 5.2 GiB in eight minutes, or about 0.65 GiB/min.
Memory Breakdown
vmmap -summary 77035 reported:
Memory Tag 253: approximately 5.8G swapped
Memory Tag 255: approximately 6.6G swapped
Chromium defines these tags as:
kPartitionAlloc = 253;
kChromium = 254;
kV8 = 255;
This indicates that the growth consisted primarily of:
- V8 heap pages;
- Chromium
PartitionAllocallocations; - likely JavaScript objects, strings,
ArrayBufferbacking stores, serialized CDP results, page-context data, or related temporary values that remained strongly referenced.
This memory profile does not look like ordinary disk cache or a purely GPU/image-cache problem.
Process Identification
The runaway process command line included:
--type=renderer
--renderer-client-id=4063
It did not include:
--extension-process
Therefore, the 13 GiB allocation was not located in the extension service worker itself. It was located in a normal webpage renderer being controlled by the extension.
The Chrome parent process remained much smaller, with an observed physical footprint of approximately 0.8–1.1 GiB. Activity Monitor may visually associate the renderer's usage with the parent Chrome application, but the actual runaway allocation was owned by renderer PID 77035.
CPU Sample Observations
The attached macOS sample report shows:
- sustained work on the renderer main thread;
- repeated execution through addresses outside static binary images, consistent with V8 JIT-generated code;
- continued renderer activity rather than an idle process waiting to be reclaimed;
- no evidence that the majority of the footprint was an
IOSurfaceor GPU allocation.
The sample report is useful for proving the process identity, CPU activity, launch time, and 7.8 GiB footprint. Because the Chrome framework is stripped, it does not identify the exact JavaScript function responsible for the allocation.
Extension Code Paths That May Be Relevant
The following findings are based on a read-only inspection of extension version 1.2.27221.15725. They are hypotheses for investigation, not a claim that one specific path has already been proven as the sole root cause.
1. Unbounded CDP event forwarding
The extension registers a global chrome.debugger.onEvent listener and forwards every event to the native host without an apparent method filter, byte limit, bounded queue, sampling policy, or transport backpressure.
The effective data path is:
chrome.debugger.onEvent
-> onCDPEvent JSON-RPC notification
-> chrome.runtime.Port.postMessage
-> native messaging transport
-> com.openai.codexextension
The dynamic CDP command path ultimately calls:
chrome.debugger.sendCommand(target, request.method, request.commandParams)
This means the native host can dynamically enable high-volume domains or methods such as:
Page.startScreencast;Page.captureScreenshot;Runtime.evaluate;DOMSnapshot.captureSnapshot;Network.enable;Network.getResponseBody;- WebSocket frame events.
If event production is faster than the native host or app server can consume it, multiple layers may retain serialized event payloads.
2. Runtime or DOM objects may survive timeout/cancellation
The renderer-side V8 allocation suggests that CDP or injected-page values may remain alive after a failed operation.
Please verify that all completion, timeout, cancellation, disconnect, and turn-finalization paths perform the equivalent of:
Page.stopScreencast
Network.disable
Runtime.releaseObject / Runtime.releaseObjectGroup
Target.setAutoAttach(autoAttach=false)
chrome.debugger.detach
In particular, Runtime.evaluate calls should use a bounded lifetime for remote objects and release their objectGroup in a finally block.
3. Large getTabContext values and base64 duplication
The extension's page-context code can read content from the controlled tab and transform it through a pipeline resembling:
ReadableStream chunks
-> Uint8Array[]
-> Blob
-> data URL
-> full base64 string
-> structured clone
-> native messaging chunks
The binary path allows up to 100 MiB of raw content, which becomes approximately 133 MiB after base64 encoding before accounting for duplicate representations and structured-clone/IPC copies.
The text path does not appear to have the same 100 MiB total-size limit.
The full dataBase64 value can remain captured by an asynchronous upload closure until all native-host chunks finish. Some native-host asset requests do not appear to have a default timeout. Multiple concurrent requests could therefore retain multiple complete payloads.
4. High-volume screenshot or screencast traffic
A screencast frame is a base64-encoded compressed image. For example:
500 KiB/frame * 4/3 base64 expansion * 30 fps * 60 seconds
~= 1.17 GiB/min of payload
This makes screencast/event backpressure worth investigating. However, the large V8 portion in the affected webpage renderer means a pure image-buffer leak does not fully explain this reproduction. Screencast or screenshot traffic may be a trigger or amplifier rather than the only retained object type.
Cleanup Result
After collecting the process sample and vmmap evidence, renderer PID 77035 was terminated with SIGTERM.
Observed result:
Affected renderer: exited
Chrome child-process RSS before: approximately 4–5 GiB
Chrome child-process RSS after: approximately 2.1 GiB
System-wide free memory before: approximately 32%
System-wide free memory after: approximately 56%
Chrome itself remained running. The associated controlled tab was expected to crash or reload.
This confirms that the majority of the active memory pressure belonged to the single runaway renderer.