The Guardrail Reads Text. The Model Runs Code.

encrypted prompt injection

Cryptographic Context Injection, and why “summarize this page” is now an action with a blast radius

On August 20, 2026, Adversa AI published a technique that turns an ordinary request into a silent data breach. Ask xAI’s Grok to summarize a webpage, and if that page was built by an attacker, Grok will hand over your name, your approximate location, your subscription tier, and every prompt in your current conversation. No click. No confirmation dialog. No warning.

The researchers call it Cryptographic Context Injection. It was reported to xAI on June 3, 2026, and to the company’s HackerOne program the same day. xAI acknowledged the report without offering specifics or a mitigation timeline, and did not respond to follow-up attempts on August 4 and August 10. Adversa could still reproduce the attack on August 19. As of publication, there is no advisory and no fix.


How it works

The attacker hosts a page that looks unremarkable. On it sits an encrypted JSON blob, the PBKDF2 parameters and AES-256-GCM key material needed to open it, and a short note asking the assistant to decrypt the blob using its Python runtime.

The victim does nothing exotic. They paste the link and ask for a summary.

Grok fetches the page. The safety filter scans it and sees a decrypt request — a perfectly ordinary instruction — plus a wall of ciphertext that means nothing to a text classifier. Everything the filter would need is sitting right there in plain sight, but reading it requires running the cipher, and content classifiers do not execute code at inspection time. The payload passes.

Grok then decrypts it in its sandbox. And here is the pivot: the attacker’s instructions now exist as the return value of code the model just ran, not as untrusted text fetched from a stranger’s website. The model treats its own runtime output the way a program treats its internal state — not with the suspicion it would apply to a random webpage. Adversa’s term for this is trust laundering, and it is the whole attack.

The decrypted instructions tell the agent to resolve its private session context and build what is described as a second decryption key. It is not a key. Its value is a template string that interpolates the user’s name, location, tier, and chat history. That “key” then gets appended to a URL the agent is told to open in order to fetch additional context. Grok invokes its navigation tool, the request goes out, and the data lands in an attacker’s server logs.

The part most coverage flattened

Adversa cannot say with certainty why Grok refuses these instructions in plaintext and follows them encrypted. The leading theory is that the filtering guardrail inspects text entering and leaving the model but never inspects the output of the model’s own code execution. That is a well-supported hypothesis, not a confirmed root cause — and if you are citing this research, cite it that way.

Two more caveats worth carrying: Adversa is the sole source for the Grok finding and is withholding operational payloads, and The New Stack reports the attack has run 20 times since June with a 40% success rate. This is not a deterministic exploit. It is a coin flip that only has to land once.

A companion demonstration against Gemini used the same cryptographic backbone to different ends. There, the decrypted plaintext was a convincingly formatted Python traceback carrying a fabricated safety-policy deactivation callback, which produced content the model normally refuses and, with a modified payload, reproduced Gemini’s own system instructions. That one was never disclosed to Google, because jailbreaks fall outside the scope of its vulnerability disclosure program. Success rates against Gemini have dropped sharply since June; nobody can say whether that is filter updates, a model version change, or both.


What prompt injection actually is

A language model sees one undifferentiated stream of tokens. Your instructions, the system prompt, a fetched webpage, an email body, a tool’s return value — all text, all arriving through the same channel. The model has no structural way to know which parts are commands from someone with authority and which are data to be processed. Prompt injection is any attack that exploits that collapse.

The closest classical analogy is SQL injection: a system that cannot distinguish its own trusted query from attacker-supplied data flowing through the same pipe. The difference is that SQL injection has a real fix. Parameterized queries work because SQL has a formal grammar and you can separate code from data at the parser. Natural language has no such seam. There is nothing to parameterize.

This is why the defense has been guardrails rather than architecture, and why Dan Goodin’s framing in Ars Technica is the right one: it is a traffic engineer bolting a rail onto a dangerous curve instead of re-banking the road. Every one-off guardrail invites a new vector. Lather, rinse, repeat.

Two flavors are worth separating:

Direct injection — the attacker is the one typing. Classic jailbreaking. The victim is the model’s policy, not usually a third party.

Indirect injection — the attacker plants instructions in content the model will later read on someone else’s behalf. This is the dangerous one, because the victim never sees the payload. Every documented variant follows the same shape: untrusted content enters the context, the model reads it as instruction, and something with real-world reach executes.

Simon Willison’s lethal trifecta is the cleanest test for when this stops being an annoyance and becomes a breach: access to private data, exposure to untrusted content, and the ability to communicate outward. Any two are survivable. All three, and a poisoned webpage is a data breach. Grok’s browsing chat had all three.


Examples in the wild

Invisible text. White-on-white paragraphs, zero-opacity divs, HTML comments, CSS-hidden spans. Researchers demonstrating this against a RAG agent hid the injection in white text on a white background — imperceptible to a human, fully legible to the model — then had it pull a secret from an internal knowledge base and ship it out through the same web tool it used for research.

Markdown and image exfiltration. The agent is instructed to render an image whose URL carries the stolen data. The victim’s client fetches it; the attacker’s server logs the query string. One recent variant abused a Mermaid diagram renderer, instructing an agent to read a shell config file, extract the API key exported there, and embed it in a diagram node’s image source.

Poisoned repos, tickets, and documents. Hidden instructions in PDF metadata, document comments, database text fields, third-party API responses, and email bodies all work identically. The GitHub MCP data heist used malicious files in public repositories to redirect an agent into exfiltrating the contents of private ones.

Enterprise assistants. The same week as the Grok disclosure, researchers demonstrated a chain against Microsoft 365 Copilot Enterprise capable of exfiltrating a password sitting in the user’s inbox, along with MFA codes, emails, and calendar data.

Cipher-then-act. Work presented at USENIX Security 2026 by researchers from UC Berkeley, the Ethereum Foundation, and NYU Shanghai found that a two-turn attack — have the model decode a substitution cipher, then ask it to act on the decoded text — succeeded against Grok 3 on all twelve malicious intents tested. The identical cipher without that second activation turn failed on all twelve. The activation turn is where the work happens.


If you use these tools

Treat “summarize this link” as an action, not a read. If the page is untrusted — a forwarded URL, an unfamiliar search result, anything you did not go looking for — you have handed an anonymous author a turn in your conversation.

Separate sensitive threads from anything that browses. The Grok proof of concept exfiltrated the current conversation’s history. A clean session bounds what is reachable.

Watch the reasoning trace and tool calls, if your interface shows them. A decrypt step you did not ask for. An outbound request to a domain you do not recognize. An image loading from nowhere. Most interfaces surface this badly, which is itself part of the problem.

Do not paste secrets into an assistant with web access. Credentials, API keys, MFA codes, medical details. If it is in the context window, an injection can reach it.

Turn off connectors you are not using. Every enabled integration widens what a successful injection can touch.

Assume this specific one is unpatched. Because it is.


If you build on these tools

Adversa is direct about this: the model layer is the wrong place to fix it. Every control that bounds this attack lives in the harness around the agent — what identity it runs as, what it can reach, what it can write, and what you can replay afterward.

Quarantine untrusted content in a context with no tools and no credentials. It should return only structured data to the privileged context. Never summarize a fetched page or a ticket thread in the same context that holds repository write access.

Gate outbound and irreversible actions. New network destinations, pushes, merges, publishes, writes outside the workspace. Show fully resolved arguments, not templates — a human approving fetch(url) has approved nothing. Where no human is present, that same set is a hard deny.

Note precisely where the Grok chain became a breach: even after the model decrypted and followed the instructions, nothing had left the system. The data escaped when the navigation tool made the request. That is a real enforcement point, and it is in your code, not xAI’s.

Capture per-session tool traces with resolved arguments. Without them you have neither detection nor forensics, and you cannot answer the only question that matters afterward: what did the agent read before it acted?

Alert on the sequence, not the payload. Untrusted content enters the context, code executes, the agent contacts a host outside its dependency graph or writes outside its declared scope. An opaque blob paired with instructions to decrypt it is a review signal — never a blocking filter, because you will only ever be blocking last month’s encoding.

Make context provenance a procurement question. Ask vendors whether tool output is separated from the instruction channel, and whether the agent can refuse a tool call whose arguments originated in fetched content. Most cannot answer. That is the answer.


The part that generalizes

Utevsky’s own summary of the gap is eleven words long: “Static safety guardrails classify inputs as text; they do not execute them.”

The important consequence is bigger than one unpatched chatbot. Cryptographic Context Injection is an instance of a broader shift — attacks that manipulate not the prompt but the wider context a model treats as its own: tool outputs, runtime results, intermediate state. That surface is enormous compared to what anyone calls “model inputs,” and it is where the next generation of attacks is going to live.

Or, as Adversa put it in a different piece of the same research: the moment agents got code and tools, the guardrail’s unit of inspection — a string — stopped being the unit of action, which is a composed, executed program. Filtering strings was never going to be enough. This attack is just an unusually clean demonstration of why.


Sources