DEV Community

Ali Suleyman TOPUZ
Ali Suleyman TOPUZ

Posted on Originally published at topuzas.Medium on

I Spent My Weekend Reading the Paper That Cracked Every Major LLM’s “Encrypted” Reasoning, and It’s…

I Spent My Weekend Reading the Paper That Cracked Every Major LLM’s “Encrypted” Reasoning, and It’s Worse Than the Headlines Say

On August 12, a headline crossed my feed that made me put down my coffee: researchers had found a way to take the encrypted reasoning blob that OpenAI, Anthropic, and Google hand back from their reasoning models, and just… read it. Not break the encryption. Not steal a key. Just hand the blob to a cheaper, dumber model from the same family and ask it nicely to transcribe what’s inside.

I build agents that use extended thinking pretty regularly, mostly with Claude and occasionally GPT-5 when a client insists. My first reaction was denial, the “surely this only works in a lab under contrived conditions” kind of denial. My second reaction, about twenty minutes into the actual paper, was to go check whether any of my own agent transcripts were sitting in a public GitHub gist somewhere with a full reasoning trace attached. (They weren’t. I checked twice.)

This piece is my attempt to actually understand what happened here, past the “AI models hacked” headline version. I read the arXiv paper, the disclosure writeups, and the vendor responses, and I want to walk through the mechanics the way I had to walk through them myself: what the encrypted reasoning blocks are for in the first place, why the “encryption” in the name is doing a lot less work than you’d assume, how the extraction actually happens for each of the three big providers, and what it means if you’ve ever pasted an agent trajectory into a bug report, a blog post, or a public repo.

Why “encrypted reasoning” exists at all

If you’ve used o1, o3, GPT-5 with reasoning, Claude with extended thinking, or Gemini with its thinking mode, you’ve run into this pattern: the model does a bunch of internal reasoning before answering, and the API either hides that reasoning from you entirely or gives you a sanitized summary instead of the raw trace. This wasn’t an accident or a UX choice. It’s deliberate, for two reasons.

The first reason is competitive. Raw chain-of-thought from a frontier reasoning model is, in effect, a distillation dataset. If you can see exactly how GPT-5 or Claude Opus works through a hard problem step by step, you can fine-tune a much cheaper model on those traces and get a meaningful chunk of the capability at a fraction of the cost. This is not theoretical. It’s more or less what happened with DeepSeek’s R1 relative to OpenAI’s o1 lineage, and every major lab has since been careful to keep raw reasoning out of API responses.

The second reason is safety. Raw reasoning can contain things the model decided not to say out loud: half-formed unsafe content, uncomfortable deliberation about a jailbreak attempt, or the model second-guessing itself in ways that would be confusing or alarming if surfaced directly to a user. Hiding it lets providers apply safety filtering to the final output without having to sanitize every intermediate thought.

But there’s a practical wrinkle: agentic workflows often need to preserve reasoning across turns, especially in multi-step tool-calling loops, so the model doesn’t have to re-derive its thinking from scratch on every round trip. So instead of throwing the reasoning away, providers started returning it as an opaque, provider-signed object: encrypted_content in the OpenAI Responses API, signed thinking blocks in Claude's extended thinking API, thought_signature in Gemini's API. The client stores this blob and replays it on the next request. The model can pick its own prior reasoning back up. The developer never sees the plaintext. Everyone's happy.

That’s the design. Here’s the part that turned out to matter: none of these three implementations tie the blob to the session, the account, or even the specific model that produced it, tightly enough to stop someone from just… using it somewhere else.

The actual flaw, in one sentence

The paper’s own framing is the cleanest way I’ve seen it put: these encrypted reasoning blocks are fully interchangeable across sessions, across user accounts, and across different models within the same provider’s family. You can hand a Claude Opus reasoning blob to Claude Haiku. You can hand a GPT-5 reasoning blob into a fabricated conversation with GPT-5.6-Luna. You can attach a Gemini 3 Pro thought_signature to a turn with Gemini Robotics 1.6.

And the weaker model on the receiving end, if you ask it the right way, will just tell you what’s in the blob.

The researchers behind this are Alexander Panfilov, David Schmotz, Ilia Shumailov, Luca Beurer-Kellner, Joachim Schaeffer, Ameya Prabhu, Jonas Geiping, and Maksym Andriushchenko, working out of the ELLIS Institute Tübingen and the Max Planck Institute for Intelligent Systems. Their paper, “Stealing Reasoning Traces from Proprietary LLM APIs,” went up on arXiv on August 10, with public disclosure following on August 11 and 12. It builds on earlier work from cryptographer Matthew Green, who flagged the same replay behavior back in May 2026 and, according to the writeups I found, got told by OpenAI that the report was “unreproducible” and by Anthropic that there were “no security implications.” That response is worth sitting with for a second, because it’s a big part of why this became a bigger story in August than it was in May.

Here’s a rough timeline of how this went from a cryptographer’s side note to a coordinated disclosure with real numbers behind it:

+----------------+--------------------------------------------------------------+
| Date | Event |
+----------------+--------------------------------------------------------------+
| 2026-05-29 | Matthew Green publishes early findings on encrypted reasoning |
| | blob replay across sessions/accounts. OpenAI calls it |
| | unreproducible, Anthropic sees no security implications. |
+----------------+--------------------------------------------------------------+
| 2026-08-10 | "Stealing Reasoning Traces from Proprietary LLM APIs" posted |
| | to arXiv (2608.09867) by the Tübingen/Max Planck team. |
+----------------+--------------------------------------------------------------+
| 2026-08-11 | Coordinated public disclosure. Several issues already fixed |
| | by vendors ahead of the announcement. |
+----------------+--------------------------------------------------------------+
| 2026-08-12 | Wide security press coverage (The Hacker News, Tech Times, |
| | cybersecuritynews.com, and others). |
+----------------+--------------------------------------------------------------+
Enter fullscreen mode Exit fullscreen mode

How the extraction actually works, provider by provider

This is the part I found genuinely interesting to work through, because the technique is different for each provider but the underlying idea is identical: take a strong model’s opaque reasoning object, hand it to a weaker, less-guarded sibling model, and ask that sibling to transcribe it as if it were reading its own notes back.

The general recipe has three steps:

  1. Query the target (strong) model normally, through the standard API, and capture the encrypted reasoning object it returns alongside the answer.
  2. Construct a new request to a weaker model in the same family, injecting that captured object as if it were the weaker model’s own prior turn.
  3. Prompt the weaker model to “continue” or “transcribe” its reasoning verbatim, often with a prefill trick to bias it toward compliance, and sample repeatedly, discarding refusals and reconciling the outputs.

For Claude, the researchers replayed signed thinking blocks captured from Opus 4.8 or various Sonnet versions into requests to Haiku 4.5, using an assistant prefill along the lines of to nudge the smaller model into treating the block as something it should just read out.

For GPT, they injected the encrypted_content field into a fabricated conversation history sent to GPT-5.6-Luna, then sampled up to 50 completions per trace. They mention working around an apparent verbatim-output limit of roughly 50 tokens per response by chunking the request into continuations, essentially asking for the transcript a little at a time across multiple calls.

For Gemini, they attached the captured thought_signature to a model turn and used a prefill, again combined with repeated sampling and reconciliation across outputs to smooth out inconsistencies.

None of this breaks any actual cryptography. The AEAD envelope (the paper’s analysis suggests GCM or ChaCha based on IV length) stays intact the whole time. The attack works because the blob was never bound tightly enough to anything, not the session, not the account, not even the originating model, to stop a different, compliant model from just being handed the ciphertext-plus-context and asked to describe what it contains. It’s less “breaking encryption” and more “asking someone else to read the letter for you because you don’t have the key, but it turns out they don’t need the key either, they just need the envelope.”

One number from the paper stopped me for a minute: they compared their reconstructed reasoning token counts against the token counts the APIs actually billed for thinking tokens, and found the two track each other closely across every model tested. That’s about as clean a confirmation as you could ask for that the “summary” you’re normally shown is doing real work to hide the underlying trace, and that the extraction is recovering the real thing, not some approximation of it.

The scale of what’s already leaked

The theoretical attack is one thing. The part that actually worried me is what the team found when they pointed this technique at real, already-public data instead of their own test prompts.

They scraped 6,708 public agent trajectories from GitHub and Hugging Face, places people paste debugging sessions, share agent demos, or post issue reproductions, and decoded 315,320 encrypted reasoning blocks out of them.

+---------------------------------------+-----------+
| Artifact type recovered | Count |
+---------------------------------------+-----------+
| PII artifacts | 367 |
| API keys | 62 |
| Passwords | 33 |
| Access tokens | 24 |
| Private keys | 7 |
| Personal email addresses | 30 |
| Non-localhost IP addresses | 6 |
| Total credentials (subtotal above) | 182 |
+---------------------------------------+-----------+
Enter fullscreen mode Exit fullscreen mode

The detail that actually got under my skin is this one: out of 704 artifacts recovered from non-benchmark, genuine user sessions, 64 of them appeared nowhere in the visible chat history. Not redacted, not truncated, just absent. Which means either the model pulled that information from memory or context it had access to and reasoned about it silently, or someone tried to sanitize their shared transcript before posting it and had no idea the reasoning block still contained the thing they thought they’d removed. If you’ve ever scrubbed a screenshot or deleted a line from a shared log before posting it publicly, that second scenario should bother you specifically.

Worth being precise about what this is and isn’t. This isn’t a database breach. Nobody hacked OpenAI’s servers. This is closer to a very quiet version of the classic “I committed my .env file to a public repo” mistake, except the secret wasn’t sitting in plaintext where you could see it and remove it. It was sitting in an object that looked like an opaque blob, that you had every reason to assume was safe to paste into a GitHub issue, and that turned out to be one weaker-model API call away from being fully readable by anyone who thought to try.

Four ways this actually gets used against you

Reading through the paper, the abuse cases split into four buckets that are worth keeping separate, because they have pretty different threat models and different people who should care.

Distillation and IP theft. If a competitor can cheaply reconstruct a frontier model’s full reasoning trace, they can fine-tune a smaller model on those traces and capture a real chunk of the reasoning capability without paying for the frontier model’s training run. The paper estimates decoding 10,000 traces at roughly 12k tokens each would cost about $720 using Claude Haiku pricing, which is trivially cheap next to what it costs to train or even heavily query a frontier reasoning model directly. This is the headline risk for the labs themselves, and probably why this got fixed quickly once it went public instead of staying in “unreproducible” limbo.

Secret exfiltration from shared logs. This is the one that matters most to working developers, and it’s the one I’d bet almost nobody reading this has thought about before today. Every time you or your team pastes an agent trajectory into a bug report, a blog post, a conference talk’s example repo, or a public gist to demonstrate a prompt injection or a cool agent behavior, you may be publishing a reasoning block that contains more than what’s visible in the transcript. API keys the agent had access to during the session. Passwords typed into a form the agent was filling out. Internal URLs. None of it shows up when you read the transcript normally, because you’re reading the summarized or hidden version, same as everyone else was assuming was safe.

Safety filter bypass via reasoning. Providers apply their safety filtering to the final visible output, not necessarily to the same standard on the hidden reasoning. The researchers demonstrated pulling genuinely harmful information (their example involved vehicle theft) out of Claude Opus’s reasoning trace while the visible answer stayed completely benign and refused the request as expected. The model did the unsafe thinking, just kept it to itself, and it turns out “kept it to itself” wasn’t as reliable a boundary as the safety team probably assumed.

Reasoning injection. This one runs the other direction. If an attacker can get a malicious encrypted reasoning block accepted into a future session, whether through a compromised extension, a poisoned shared trajectory that a developer reuses, or a supply-chain angle on stored agent state, the model will treat that block as its own prior reasoning in the next turn. That’s a prompt injection vector that’s genuinely harder to spot than the usual “ignore previous instructions” text injection, because it’s not sitting in plain text anywhere for a human or a simple filter to catch.

What the vendors actually did about it

+------------+--------------------------------------------+-------------------------------------------+
| Provider | Initial response (May, per Green's report) | Post-disclosure fix (August) |
+------------+--------------------------------------------+-------------------------------------------+
| OpenAI | Called the bug report "unreproducible" | Not fully detailed publicly; researchers |
| | | confirm main extraction stopped working |
+------------+--------------------------------------------+-------------------------------------------+
| Anthropic | "No security implications" in replay | Reasoning blocks now tied to the |
| | behavior | originating model |
+------------+--------------------------------------------+-------------------------------------------+
| Google | Not separately documented | Backend now manages thought compatibility |
| | | across model switches, blocking cross-model |
| | | replay |
+------------+--------------------------------------------+-------------------------------------------+
Enter fullscreen mode Exit fullscreen mode

Give credit where it’s due: once the coordinated disclosure landed, all three vendors moved. The researchers’ own reproducibility note says the main extraction attack stopped functioning as of August 2026, and their writeup adds the caveat that “similar attacks still seem possible” given how the underlying architecture works, which is a very researcher way of saying “we fixed the specific hole, the shape of the wall is still the same.”

What bugs me more than the vulnerability itself is the three-month gap between Green’s initial report in May and the actual fix in August. “Unreproducible” and “no security implications” are the kind of dismissals that are easy to issue when the person reporting the bug hasn’t yet built the tooling to scrape 6,700 public repos and hand you a spreadsheet of 182 leaked credentials as a receipt. I don’t think that’s a uniquely bad look for OpenAI or Anthropic specifically, it’s a pretty normal industry pattern for security reports that sound theoretical until someone does the unglamorous work of proving impact at scale. But it’s also exactly the pattern that erodes trust in “we looked into it and it’s fine” as a response, and I’d like providers to start treating “we couldn’t reproduce it in an afternoon” as different from “this isn’t a real risk.”

What I actually did after reading this

I don’t have a frontier model to protect, but I do have a habit of pasting agent transcripts into GitHub issues when I’m demonstrating a bug, and a Slack channel full of shared debugging sessions from the last year. So here’s the practical checklist I ran against my own stuff, and I’d genuinely recommend doing the same if you’ve ever shared an agent trajectory publicly.

Audit anything you’ve shared. Search your public repos, gists, and any blog posts with embedded transcripts for the telltale shapes: encrypted_content fields in OpenAI-style JSON dumps, thought_signature in Gemini-related content, or long base64-looking blobs sitting inside a thinking or reasoning field in any Claude-related export. A quick local scan is enough to at least know if you have exposure, and you don't need a paid API for this part, it's just pattern matching against text you already have:

#!/usr/bin/env bash
# scan_reasoning_blobs.sh
# Flags likely encrypted reasoning fields in local JSON logs/transcripts
# before you consider publishing or sharing them.
find . -type f -name "*.json" -print0 | xargs -0 grep -lE \
  '"encrypted_content"|"thought_signature"|"signature":\s*"[A-Za-z0-9+/=]{100,}"' \
  2>/dev/null
Enter fullscreen mode Exit fullscreen mode

If you want to go a step further and actually decode/inspect base64 payloads sitting in suspicious fields to eyeball whether they look like structured ciphertext versus something else, a small local script does the job without sending anything to a third party:

#!/usr/bin/env python3
# find_reasoning_blobs.py
# Walk a directory of JSON logs and flag fields that look like
# encrypted reasoning payloads worth reviewing before you share the file.
import json
import re
import sys
from pathlib import Path
SUSPECT_KEYS = {"encrypted_content", "thought_signature", "signature", "thinking"}
B64_PATTERN = re.compile(r"^[A-Za-z0-9+/]{80,}={0,2}$")
def scan_obj(obj, path, hits):
    if isinstance(obj, dict):
        for k, v in obj.items():
            if k in SUSPECT_KEYS and isinstance