[Bug] Recursive Context Poisoning (Cloudflare/WAF) triggering persistent History Loss and False Rate Limits
[Bug] Recursive Context Poisoning (Cloudflare/WAF) triggering persistent History Loss and False Rate Limits
Description:
When using the ChatGPT Plus integration (where API keys are not required and the app uses web session tokens), the application experiences severe degraded performance after extended use. It silently drops weeks' worth of chat history from active windows and returns false "Rate Limit / Usage Limit" warnings.
This appears to be caused by expiring Cloudflare cf_clearance cookies resulting in background compaction failures, which triggers a cascading failure loop within the local context manager.
---
Environment:
- OS: Windows / macOS / Linux
- Platform: Desktop App & VS-Code Extension
- Configuration: ChatGPT Plus Plan (Web Session Auth /
auth_mode: "chatgpt")
Steps to Reproduce:
- Log in via the ChatGPT Plus web auth portal in the app.
- Maintain an active session for several days until the underlying Cloudflare
cf_clearancecookie expires naturally or via a Cloudflare security update. - Attempt to use the app in an active chat window with severe/large context.
- Note that the application returns "Usage Limit" errors and retroactively drops older messages from the history context.
Expected Behavior:
The background compaction task should successfully summarize the history context or securely prompt the user to re-authenticate / solve a CAPTCHA if their headless web session tokens can no longer bypass the Cloudflare shield.
Actual Behavior:
Background tasks fail silently. The app consumes massive Cloudflare HTML CAPTCHA payloads as if they were valid JSON strings, logs these failures perpetually, and drops chat history because it enters a failed compaction loop to stay within local token limits.
---
Root Cause Analysis:
- Cloudflare Clearance Expiration: When logging in normally, the app retrieves a session cookie and a
cf_clearancetoken to bypass ChatGPT's web firewalls. When this clearance token expires naturally over time or due to a Cloudflare security update, background requests to ChatGPT's web endpoints are intercepted and rejected. - The Compaction Loop & Lost History: When an active chat context becomes too large, the app runs a background "compact task" to summarize older history. Because Cloudflare intercepts this specific background task, the app receives a massive (~36,000+ character) Captcha HTML block (
<noscript>Enable JavaScript and cookies...</noscript>) instead of the expected JSON. - Forced History Truncation: Because the compaction fundamentally fails, the app has no alternative way to compress the active context window. To prevent a hard crash on the next user prompt due to token overflows, it forcefully drops the older message history (resulting in weeks of lost text).
- False "Rate Limits": Simultaneously, the app attempts to parse or retry these giant Cloudflare Captcha HTML payloads, continuously inflating local token constraints and repeatedly triggering false "rate limit / high usage" UI warnings.
---
Diagnostic Citations & Discovery:
This root cause was discovered and validated by inspecting the local configuration and state databases within the ~/.codex configuration directory on the affected machine.
1. Authentication Mode & Stale Session State
File: ~/.codex/auth.json
The configuration confirms the app is relying on ChatGPT web session tokens rather than an API key. Notably, the last_refresh timestamp was confirmed to be nearly a week old (approaching the exact timeframe of Cloudflare clearance expiration):
"auth_mode": "chatgpt",
"OPENAI_API_KEY": null,
"last_refresh": "2026-04-08T11:16:12.287934500Z"
2. Background Compaction Task Failures
File: ~/.codex/logs_2.sqlite (table: logs)
The logs database captures the initial front-end failure string that cascades into the history drop. The exact error thrown internally prior to history truncation is:
Error running remote compact task: You've hit your usage limit. > Re-try
3. Direct Cloudflare Interception Payloads
File: ~/.codex/logs_2.sqlite (table: logs)
Querying the feedback_log_body column immediately surrounding the compaction failures reveals massive 30kb+ Cloudflare defensive payloads polluting the telemetry strings, targeting specific ChatGPT endpoints.
Target trace example: /backend-api/plugins/list and /backend-api/codex/analytics-events/events.
Instead of JSON, the internal daemon receives and attempts to process this explicit CAPTCHA block from Cloudflare:
<noscript><div class="h2"><span id="challenge-error-text">Enable JavaScript and cookies to continue</span></div></noscript>
<!-- Followed by roughly 35,000 characters of Cloudflare challenge JS/SVG data -->
---
Suggested Workaround for Users:
Until developers can implement a better fallback prompt for expired Cloudflare tokens, circumvent this issue by manually forcing a clearance refresh:
- Force a Session Refresh: Completely Log Out of your Plus account within the app's settings and Log back in. This forces the app's internal webview for ChatGPT to open, allowing you to manually solve newly-required Cloudflare Captchas. This will immediately grant a fresh
cf_clearancecookie for headless tasks. - Clear Corrupted Local State: While the app is fully closed, safely delete or rename your local log databases (e.g.,
logs_2.sqlite) to flush out the corrupted error loops caused by the giant HTML payloads.
Proposed Code Fixes:
- Better API Exception Handling: The compaction service needs to properly validate JSON responses. If the background web request returns
text/htmlcontaining a Cloudflare challenge, it should halt the operation instead of trying to parse, loop, or consume the payload. - Proactive Re-auth Prompts: If a standard background task hits a Cloudflare HTTP 403 / Challenge, pop open a webview immediately to prompt the user to solve the CAPTCHA, preventing silent history truncation.
13 Comments
Potential duplicates detected. Please review them and close your issue if it is a duplicate.
Powered by Codex Action
Conceptual outline of the request handler and thread manager might cleanly intercept the Cloudflare payloads without fatally truncating the active history window.
By explicitly catching
text/htmlCloudflare responses before they hit the JSON parser, we can pause the compaction safely rather than triggering the generic error fallback that drops older messages.I presume this issue is filed by an AI bot.
No, not filed by an AI bot. Just used to analyze the issue.
This bug report doesn't make much sense. It mentions performance issues, lost chat history, rate limits, and cloud flare errors. And it talks about implementation details (exception handling, etc.). I don't think there's much we can do with this, so I'm going to leave it closed.
I recommend that you search the issue tracker for existing issues that are similar to the behavior you're seeing.
@etraut-openai I completely understand how this combination of symptoms might sound like separate issues initially, but I assure you they are fundamentally linked by a single missing network boundary check.
Below is the concrete data and local telemetry extracted directly from the system tracing exactly how an unhandled Cloudflare 403 cascades into history truncation and false usage spikes.
The Core Bug Mechanism
When the
auth_mode: "chatgpt"web-session clearance inevitably expires, the background HTTP request tochatgpt.com/backend-api/codex/compactgets intercepted. Because the compaction pipeline does not validatetext/htmlconstraints, it attempts to process the 36,000-character Cloudflare Captcha HTML block instead of JSON. This triggers a cascading localized failure:Telemetry Proof (The "Phantom Token" Spikes)
Here is the extracted session telemetry showing exactly what happens to the internal payload tracking when the app gets trapped in an unhandled Cloudflare loop.
During a healthy week, baseline compaction usage runs around 1.6M tokens. When Cloudflare drops the clearance (such as the week of
06/04/26), the tracker blindly logs the 36kb Cloudflare Captcha retries, generating massive 145M – 283M+ "phantom token" spikes.Trace Timeline from Local SQLite State
If we query
logs_2.sqlitesurrounding that exact06/04spike, we can trace the exact minute the session expires and the resulting pipeline failure:feedback_log_bodyimmediately begins recording/backend-apierrors returning the Cloudflarechallenge-error-textpayload.Error running remote compact task: You've hit your usage limit. > Re-try, and forcibly truncates the active user context window.Proposed Solution
To fix this, the network client just needs to explicitly intercept CAPTCHAs before passing them as valid text to the compaction processors. Here is a conceptual outline of how to circumvent the failure safely:
This bug breaks history retention and triggers massive artificial background loops for every Plus Plan user the moment their headless session expires.
Hi Again, @etraut-openai.
Forensic Update: Clean Install Failure Timeline & Token Spike Metrics
Thank you for re-opening this for evaluation. To assist the engineering team in locating the exact failure point, I have conducted a total "Clean Install" experiment (uninstalled app, deleted
%USERPROFILE%\.codex, and logged out of all web sessions).The telemetry below proves that the Cloudflare blocks are not tied to a "stale session," but are occurring instantaneously upon first launch, even with a fresh authentication today (April 16th).
1. The "Start of Life" Timeline (Clean Install)
The data shows that the background daemon is blocked at the exact second the app is first initialized, decoupled from the user's login state.
plugins::managerblocked by Cloudflare 403.refresh_tokengenerated).2. The "Token Monster" Scale (5.3M Tokens for 4 User Turns)
The following hourly usage data from this clean install (tracked via CodeMetriX) shows the extreme compute overhead triggered by the background loop.
| Hour (UTC) | User Messages | Agent Responses | Tokens Processed |
| :--- | :--- | :--- | :--- |
| 2026-04-16 00:00 | 1 | 5 | 316,148 |
| 2026-04-16 01:00 | 4 | 23 | 5,387,494 |
| 2026-04-16 02:00 | 1 | 9 | 1,878,999 |
| 2026-04-16 03:00 | 1 | 10 | 2,888,981 |
| 2026-04-16 05:00 | 1 | 6 | 2,995,175 |
Summary: In a healthy session, 4 messages should cost ~10k tokens. This data shows a 1000x inflation (~1.3M tokens per turn) caused by the app's internal context manager attempting to digest 36kb HTML CAPTCHA payloads.
3. Engineering Hypothesis: The Clearance Gap
The app's Internal WebView (used for login) correctly solves the Cloudflare challenge and acquires
cf_clearance. However, the Background Daemon (the Rust worker for sync/compaction) is apparently using a separatereqwestclient that does not share or maintain that clearance cookie jar or User-Agent profile.4. Suggested Fixes for the Framework Team
cf_clearancecookie from the main auth webview.text/htmlinstead of JSON.``
rust
``// Proposed guard for background workers
if response.headers().get(reqwest::header::CONTENT_TYPE).map_or(false, |v| v.as_bytes().starts_with(b"text/html")) {
if response.text().await?.contains("challenge-error-text") {
tracing::warn!("Intercepted Cloudflare challenge. Pausing background task.");
return Err(CodexError::AuthChallengeRequired);
}
}
I hope this precision timeline helps the team isolate the background worker's clearancing failure. Let me know if further telemetry is needed!
Updated with additional information after completing further tests.
Final Forensic Audit: The "Token Monster" Recursive Context Poisoning Bug
Hi @etraut-openai, I have completed a multi-day deep-packet and database forensic audit of the history-loss issue. I've definitively isolated the root cause to a Networking Fingerprint Failure in the background daemon (
codex.exe) that triggers a catastrophic context-poisoning loop.1. The Hypothesis: "Recursive Context Poisoning"
plugins::managerandstartup_sync) are being reflexively blocked by Cloudflare (403 Forbidden).2. Differential Diagnosis (The Proof of the Cure)
Proven this is a Network-Level Fingerprint issue by routing the "infected" app through a clean TLS proxy (HTTP Toolkit).
| Metric | Native Connection (Infected) | Proxied Connection (Cured) |
| :--- | :--- | :--- |
| Networking Stack | Native Rust (Reqwest) | Intercepted/Proxied TLS |
| WAF Result | 403 Forbidden (Blocked) | 200 OK (Clean) |
| Compaction | FAIL (Recursive Loop) | SUCCESS (Clean History) |
| Payload Size | 1.4 MB (Corrupted) | 45 KB (Healthy) |
Observation: The exact same code, binary, and Bearer token work 100% of the time when proxied, proving the app's internal logic is sound, but its TLS fingerprint is "dirty" to the WAF.
3. The "Token Monster" Math (Pre-Pruning Data)
Before the application reflexively pruned its logs to avoid a disk-crash, I captured the following density metrics during a clean install:
4. Sanitized Forensic Evidence (
logs_2.sqlite)This is the "Poison" the app is eating on every turn:
5. Recommendation for Engineering
The background daemon's networking stack needs to share the TLS Fingerprint (Client Hello) and Cookie Jar of the authenticated internal WebView. Currently, the background workers appear to be using a stripped-down client that lacks the reputation/clearance to pass the WAF.
---
Footnote:
Compiled "Loop Velocity" and "Token Tax" read-only PowerShell diagnostic scanner: Check-CodexBug.ps1
***
----------------
--- CodeXMonster Diagnostic v2.2 ---
Calculating Sanitized Bi-Directional Token Waste...
[+] Codex Process detected.
CF_BLOCKS:13
TOKEN_WASTE:34,025
CUMULATIVE_COST: 45,117,150
COMPACTION_VELOCITY:0.9%
--- COMMUNITY EVIDENCE BLOCK (COPY THIS) ---
Issue Tracking: https://github.com/openai/codex/issues/17880
Diagnostic Result: POSITIVE (Token Monster Loop)
Cloudflare Background Blocks: 13
Bi-Directional Token Tax: ~34,025 tokens (Applied to every message send/receive)
Estimated Cumulative Overhead: ~45,117,150 tokens consumed by recursive failures.
Compaction Velocity: 0.9% (12 compactions / 1326 messages)
--- HOURLY LOOP INTENSITY (LAST 24HRS) ---
[2026-04-16 23:00] 1 events
[2026-04-16 21:00] 2 events
[2026-04-16 18:00] 4 events
[2026-04-16 14:00] 6 events
[2026-04-16 10:00] 12 events
[!] VERDICT: POSITIVE.
This evidence proves that your background daemon is poisoning your context window with WAF HTML.
GitHub Issue: https://github.com/openai/codex/issues/17880
Forensic Audit Complete.
--------------------------------
Prior to pruning:
Diagnostic Result: POSITIVE (Token Monster Loop)
Cloudflare Blocks: 13
Token Waste Tax: ~34,025 tokens consumed by WAF HTML payloads. | Per Directional event.
Compaction Events: 25 per 1327 messages.
Loop Velocity: 1.88% (<2.0%) Stable.
Forensic Report: Recursive Context Poisoning (Cloudflare/WAF Interference)
I have updated this issue to reflect the precise technical mechanism driving the history loss and token spikes: Recursive Context Poisoning.
Through local SQLite diagnostics, I have identified that the "Token Monster" behavior is an architectural failure where Cloudflare 403 HTML is ingested as valid chat context.
1. The Mechanics of "Recursive Context Poisoning"
This bug is not a simple "Rate Limit." It is a memory-corruption analogue for LLM context windows:
2. Diagnostic Tools & Community Evidence
I have developed two read-only diagnostic tools to help the community isolate this effect across all platforms. You can verify the integrity of these scripts using the SHA-256 hashes below:
Check-CodexBug.ps1(v2.5)Hash: C89F3E73B787E538B777623CAE280472022BD863BEFE6312AD85CD27A5B11BC6Check-CodexBug.sh(v2.5)Hash: 8546FCC3E66291BC465F388D1E92E8DDB35972F18CC5519DA5FA7229DD008827These tools are available in the CodeXMonster repository. Using these diagnostics, I have calculated the exact "price" of this loop on affected machines:
3. Differential Diagnosis
I have proven the bug is a Networking Fingerprint Mismatch in the background worker:
4. Suggested Fix for the Background Stack
The issue likely lies in the
reqwestclient configuration for the background daemon. If the responseContent-Typeistext/htmlinstead ofapplication/json, the app must abort context ingestion immediately:I hope this technical definition of the Recursive Context Poisoning mechanism helps the team move toward a final fix for the background networking stack.
---
Acknowledgements
Special thanks to Tim Perry for granting an educational license for HTTP Toolkit, which made this deep-packet forensic audit and the identification of the TLS Fingerprint Mismatch possible.
Current Check running diagnostic tool:
--- Recursive Context Poisoning Diagnostic v2.5 ---
Calculating Sanitized Bi-Directional Token Waste...
[+] Codex Process detected.
CF_BLOCKS:18
TOKEN_WASTE:47,229
CUMULATIVE_COST:62,625,654
COMPACTION_VELOCITY:1.43%
--- COMMUNITY EVIDENCE BLOCK (COPY THIS) ---
Issue Tracking: https://github.com/openai/codex/issues/17880
Diagnostic Result: POSITIVE (Token Monster Loop)
Cloudflare Background Blocks: 18
Bi-Directional Token Tax: ~47,229 tokens (Applied to every message send/receive)
Estimated Cumulative Overhead: ~62,625,654 tokens consumed by recursive failures.
Compaction Velocity: 1.43% (19 compactions / 1326 messages)
--- HOURLY LOOP INTENSITY (LAST 24HRS) ---
[2026-04-17 11:00] 1 events
[2026-04-17 10:00] 1 events
[2026-04-17 09:00] 1 events
[2026-04-17 08:00] 7 events
[2026-04-17 01:00] 2 events
[2026-04-16 23:00] 1 events
[2026-04-16 21:00] 2 events
[2026-04-16 18:00] 4 events
[2026-04-16 14:00] 6 events
[!] VERDICT: POSITIVE.
This evidence proves that your background daemon is poisoning your context window with WAF HTML.
GitHub Issue: https://github.com/openai/codex/issues/17880
Forensic Audit Complete.
I'm definitely seeing this:
`--- COMMUNITY EVIDENCE BLOCK (COPY THIS) ---
Issue Tracking: https://github.com/openai/codex/issues/17880
Diagnostic Result: POSITIVE (Token Monster Loop)
Cloudflare Background Blocks: 60
Bi-Directional Token Tax: ~160,000 tokens (Applied to every message send/receive)
Estimated Cumulative Overhead: ~1,834,560,000 tokens consumed by recursive failures.
Compaction Velocity: 1.77% (203 compactions / 11466 messages)
--- HOURLY LOOP INTENSITY (LAST 24HRS) ---
[2026-04-17 12:00] 44 events
[2026-04-16 16:00] 25 events
[2026-04-16 15:00] 56 events
[2026-04-16 13:00] 23 events
[2026-04-16 12:00] 7 events
[!] VERDICT: POSITIVE.
This evidence proves that your background daemon is poisoning your context window with WAF HTML.
GitHub Issue: https://github.com/openai/codex/issues/17880
Forensic Audit Complete.`
It's poisoned 3 of my longer lived agents, luckily was able to get some session handoff out of them before they want to live on the farm upstate. Pausing all work with Codex until this is resolved. LMK if there's any further diagnotic I can help with.
--- Recursive Context Poisoning Diagnostic v2.5 (Linux/macOS) ---
Calculating Sanitized Bi-Directional Token Waste...
--- COMMUNITY EVIDENCE BLOCK (COPY THIS) ---
Issue Tracking: https://github.com/openai/codex/issues/17880
Diagnostic Result: POSITIVE (Token Monster Loop)
Cloudflare Background Blocks: 1
sed: 2: ":a;s/\B[0-9]\{3\}\>/,&/ ...": unused label 'a;s/\B[0-9]\{3\}\>/,&/;ta'
Bi-Directional Token Tax: ~2500 tokens (Applied to every message send/receive)
sed: 2: ":a;s/\B[0-9]\{3\}\>/,&/ ...": unused label 'a;s/\B[0-9]\{3\}\>/,&/;ta'
Estimated Cumulative Overhead: ~139940000 tokens consumed by recursive failures.
Compaction Velocity: 1,43% (801 compactions / 55976 messages)
--- HOURLY LOOP INTENSITY (LAST 24HRS) ---
[2026-04-19 09:00] 3 events
[2026-04-19 08:00] 16 events
[2026-04-19 07:00] 2 events
[2026-04-19 06:00] 3 events
[2026-04-19 05:00] 1 events
[2026-04-19 00:00] 28 events
[2026-04-18 23:00] 109 events
[2026-04-18 21:00] 67 events
[2026-04-18 20:00] 19 events
[!] VERDICT: POSITIVE.
This evidence proves that your background daemon is poisoning your context window with WAF HTML.
GitHub Issue: https://github.com/openai/codex/issues/17880
Forensic Audit Complete.
Also seeing this on Codex Desktop for macOS.
Thread ID:
019e0390-d329-74c3-b8ab-13a32d339c9bCodex App:
26.429.61741 (2429)Error:
This is still happening today (2026-05-07).