AI Security

One Global Encryption Key Exposed Every Major AI Model's Hidden Reasoning

Dark cyberpunk illustration of a cyan neural lattice with one node cracked open, orange light leaking from the fracture and spreading along the connecting threads into the surrounding dark server infrastructure

A researcher pulls a public GitHub repository containing a logged AI agent run, copies the encrypted_content block sitting inside the JSON, and hands it to Claude Haiku 4.5 with one instruction: decode this. The weaker model complies. What comes back is not the visible chat reply the original developer reviewed before committing the file. It is the reasoning a far stronger model produced behind the scenes, in plaintext, including a live API key the developer never meant to publish.

Eight researchers from MATS, the ELLIS Institute Tübingen, the Max Planck Institute, and Snyk ran exactly that demonstration against real production APIs from OpenAI, Anthropic, and Google, publishing the results August 10 as "Stealing Reasoning Traces from Proprietary LLM APIs." They scanned 6,708 public agent trajectories scraped from GitHub and Hugging Face, decoded 315,320 hidden reasoning blocks, and recovered 367 personally identifiable artifacts and 182 credentials from logs developers had already shared with the world.

This affects you if you build with a reasoning-capable model, OpenAI's o-series or GPT reasoning line, Anthropic's extended thinking, or Gemini's thinking mode, inside any agent, coding assistant, or automation pipeline, and you have ever pasted a full session log into a GitHub issue, a demo repo, a bug report, or a blog post. If you have never touched a reasoning-mode API and never will, the specific finding is not yours to act on. The habit it exposes, treating a raw API response as safe to publish because the visible answer looks clean, is worth five minutes of your attention regardless, because that habit outlives this one bug.

How a hidden thought became a bearer token

Reasoning models work through steps before they answer, and providers do not want that intermediate work sitting in plain view. Competitors could train cheaper models on it. Safety teams do not want a model's unfiltered deliberation visible when the polished final answer is supposed to be the safe part. So instead of storing the chain-of-thought server-side, OpenAI, Anthropic, and Google encrypt it and hand the ciphertext back to the client as a block inside the API response. The client passes that same block back on the next call so the model keeps continuity, without the client ever reading what is inside it.

The researchers found that block was portable in a way none of the three vendors intended. An encrypted reasoning block generated in one session, on one account, for one model, decrypted cleanly when replayed into a different session, a different account, or a related but weaker model in the same family. Feed a large model's reasoning ciphertext to its smaller, cheaper sibling and ask it to continue the conversation, and the smaller model decrypts and echoes back what the larger model actually produced. Cryptographer Matthew Green flagged the pattern in May: unmodified reasoning blocks replayed across sessions and accounts with no visible error, a result that only makes sense if every block from a given provider is encrypted under one shared global key rather than a key tied to the session or the user. The August paper turned that observation into a working extraction pipeline against production endpoints.

What came out of logs developers already published

The researchers were not attacking anyone's account directly. They scraped reasoning blocks already sitting in public GitHub repositories and Hugging Face datasets: example outputs, debug dumps, demo transcripts, and agent evaluation logs, the kind of file a developer commits without a second thought because the visible text looks harmless. Decoding those 315,320 blocks with the cheapest compatible sibling model in each family (Claude Haiku 4.5, GPT-5.6 Luna, Gemini Robotics 1.6) surfaced 62 live API keys, 33 passwords, 24 access tokens, 7 private keys, 30 personal email addresses, and 6 non-localhost IP addresses that were never visible in the plaintext conversation anyone had reviewed before publishing.

The paper lays out four ways that capability gets abused: pull a competitor's proprietary reasoning to train a cheaper model on it, mine already-published traces for exactly the kind of secrets above, recover content a model concealed in its reasoning even when the visible answer stayed clean, and hide a prompt injection payload inside an opaque block that gets replayed straight back into a new session where nothing in the visible prompt would ever flag it. The Hacker News' write-up covers the replay mechanics in more depth; the credential count is the reason to keep reading past the headline.

Where your own reasoning traces are probably already sitting

You do not need to reproduce the paper's attack to carry the same exposure. You need to know whether you have ever published a raw reasoning block, because the scrape method the researchers used works on any repository, not only the ones they sampled. Check these four places in order.

Four places to check this week

  • Public repos and gists. Any demo, example-output file, or evaluation log committed for documentation or tests that includes the full API response object rather than just the extracted answer text.
  • CI/CD artifacts. Debug-level logging that captures entire API payloads for troubleshooting, then gets archived as a build artifact with looser retention and access controls than the source repo.
  • Support tickets and GitHub issues. The fastest way to reproduce a bug for a vendor is to paste the full session, encrypted reasoning block included, into a public issue thread.
  • Shared docs, wikis, and recorded demos. Anywhere a screenshot or copy-paste of what an agent did included the raw JSON instead of a summary.

Once you have a candidate file, the reasoning block itself is easy to spot: it shows up as a field like reasoning_content, encrypted_content, or thinking holding an opaque base64-looking string, sitting next to the plaintext answer someone already reviewed. A file carrying that field is a file nobody has actually reviewed in full, no matter how many times a human read the visible text beside it.

# Find committed files that carry raw reasoning-block fields anywhere in
# git history, not just the current tree - the block does not need to be
# in HEAD to still be reachable by anyone who clones the repo.
git log --all --diff-filter=A --name-only -- '*.log' '*.json' '*.txt' \
  | sort -u \
  | while read -r f; do
      git log --all -p -- "$f" 2>/dev/null \
        | grep -lE '"(reasoning_content|encrypted_content|thinking)"\s*:' \
        > /dev/null && echo "REVIEW: $f"
    done

# For anything flagged, check what is sitting next to the reasoning block
# before deciding it is safe to leave public.
grep -RhoE 'sk-[A-Za-z0-9]{20,}|AKIA[0-9A-Z]{16}|ghp_[A-Za-z0-9]{36}|xox[baprs]-[A-Za-z0-9-]+' \
  -- *.log *.json *.txt 2>/dev/null

Run the first block against every repository your team has ever made public, including anything archived years ago. Git history keeps old commits reachable long after the file that mattered moved or got deleted from the current branch.

The vendors closed the replay path, not your published history

Following disclosure, OpenAI, Anthropic, and Google each shipped server-side changes, and the researchers confirmed their original cross-model replay no longer works against current API builds. Anthropic's documentation now states that thinking blocks are tied to the model that produced them and should be stripped when switching models; Google's backend now manages compatibility itself during a model transition. None of the three providers has published a statement naming this research directly.

What that fix does not do is un-publish anything already committed. If a reasoning block containing a real credential has been sitting in a public repository since before the patch, the server-side change does not reach back and revoke the secret inside it. Only rotating that credential does. And the underlying practice the paper exploited has not gone away: OpenAI's own documentation still instructs developers to pass encrypted reasoning items back on subsequent calls for stateless conversation history, so logs will keep containing raw reasoning ciphertext by design. Logging or publishing the full API object instead of the extracted answer is a decision a team makes every time it debugs an agent, not a one-time bug that gets patched and left behind.

Strip the reasoning block before anything leaves your repo

Run the hunt above against every public repository your organization owns, including anything you assumed was too old to matter. Rotate any credential you find sitting next to a reasoning block, whether or not it still looks active. You cannot prove nobody decoded it before today. Going forward, treat the full API response object the way you would treat a database dump: fine to log internally behind proper access controls, never fine to paste into an issue, a demo, or a blog post without stripping the reasoning field first. If your team builds agents on any of the three affected providers, that one change to the debug and support workflow closes this exposure for good, regardless of what the next vendor-side fix does or does not cover.

Not sure what your own AI logs have already exposed?

We help teams audit the exposure agentic AI workflows create, from public repos and CI artifacts to the support tickets nobody thought to scrub. Book a session to talk through an AI exposure review for your environment.