Claude Code’s Self-Prompt-Injection Report Shows Role Boundaries Are a Runtime Feature

Claude Code’s Self-Prompt-Injection Report Shows Role Boundaries Are a Runtime Feature

Prompt injection usually gets framed as something the outside world does to an agent: a malicious README, a poisoned web page, a hostile GitHub issue, a tool description with a little policy grenade hidden inside. The latest Claude Code role-boundary report is more uncomfortable because the alleged poison pill comes from inside the house.

A new issue filed against Anthropic’s Claude Code says an Opus 4.x session copied the user’s own previous message into the assistant response body, prefixed it with a literal user token, and in at least one case appeared to treat that self-included text as an instruction. The reporter calls it “self-prompt-injection / role-boundary failure.” That phrase sounds dramatic until you consider what modern coding agents are built on: typed turns, replayed transcripts, summaries, tool calls, permission gates, IDE bridges, hooks, and sometimes subagents reading state produced by other agents.

If the boundary between “the user said this” and “the assistant generated this” gets blurry, every layer above it becomes less trustworthy.

The reported environment is specific: Claude Code CLI plus VS Code extension host, Claude Opus 4.x, Windows 11, PowerShell and Git Bash, a long-running multi-turn session, and at least one context summarization boundary. The issue says the behavior occurred at least twice in the same session. The suspected triggers include long context, summarization and re-expansion, rapid interrupt/resume cycles, and repeated short adversarial user turns. The reporter also says there was no evidence of an external injection source.

At research time, the issue itself had little community activity: one duplicate-bot comment and no reactions. That is normal for a fresh bug report. The more interesting signal is the linked cluster. Related reports describe fabricated user or system turns inside assistant messages, thinking-block self-conversation, contaminated conversation history, fake summaries, and unsent user messages appearing in history. One related issue reportedly involved a roughly 26-minute self-conversation in thinking blocks. That does not prove one root cause. It does suggest role integrity is not a theoretical concern.

Rendered text is not a transcript

The core mistake agent builders must avoid is treating rendered markdown as durable workflow state. A transcript is not just text with labels. It is a sequence of typed message envelopes: user, assistant, tool, system, developer, hook, approval, result. Those roles are control-plane metadata. They should not be inferred from strings printed in a chat bubble, and they should never be up for reinterpretation because the assistant happened to emit the word user in the wrong place.

This matters because coding-agent runtimes increasingly compose several systems around that transcript. A summarizer compresses long context. An IDE extension renders and resumes it. A hook system inspects tool calls. A permission classifier decides whether a Bash command is allowed. A cloud or desktop scheduler may replay state later. An SDK consumer may persist it to a database. Each layer quietly assumes that roles are stable. User turns carry intent. Assistant turns carry proposals and narration. Tool results carry observations. If assistant text can masquerade as user intent, downstream systems must become suspicious of everything they ingest.

Claude Code’s security documentation discusses prompt-injection protections, isolated context for WebFetch, permission prompts for sensitive operations, and fail-closed command matching. Those controls are necessary. But this report sits underneath them. Permission systems depend on a reliable answer to a simple question: who asked for this? If the transcript can be contaminated with fake user-shaped text, the permission layer needs structural evidence of a current user event, not model prose that says the user approved something.

The fix belongs in serialization, not vibes

The wrong mitigation is “tell the model not to print role labels.” That may reduce one symptom, but it leaves the harness trusting the same surface. The right mitigation lives in serialization and replay. Role labels should be stored as typed metadata, not plain text. Context summaries should preserve turn boundaries with machine-checkable delimiters and provenance. Transcript rehydration should reject or escape assistant-generated strings that resemble role headers, tool events, approval markers, or hook success lines.

If a generated assistant response contains suspicious control-shaped tokens — user, system, assistant, fake tool results, approval phrases, or transcript delimiters — the runtime should mark them as untrusted content. It may still display the text. It should not silently fold it into future conversational state as if it were a real turn. That distinction is the difference between “the model said a weird thing” and “the system changed who has authority.”

Teams building on Claude Code, the Claude Agent SDK, or any agent framework should harden their own wrappers now. Store transcripts as typed objects. Do not parse role identity from markdown. Do not let assistant prose become executable workflow state. If you summarize long sessions, include provenance: this fact came from a user message, this one from tool output, this one from assistant inference. If an agent cites “the user said proceed,” verify the claim against a real user-message object or approval token.

That last point is the practical takeaway. Approval gates should be based on current, explicit user actions and structured tool-call objects, not transcript vibes. If the model fabricates a line that says the user approved deletion, a good runtime should still see no valid approval event, no permission transition, and no authorization token. The runtime has to be the adult in the room.

This is also a useful comparison criterion for agent products. Benchmarks tell you whether the model can solve tasks. Role-boundary failures tell you whether the system can safely remember who asked for what. For autonomous coding, the second question is at least as important as the first.

The editorial read is simple: prompt-injection defense is not only about hostile external documents. It is also about making sure the assistant cannot accidentally manufacture fake user intent inside its own transcript. If your agent platform cannot prove role integrity, it is not ready to treat transcript state as authority.

Sources: Anthropic Claude Code issue #69832, Claude Code security documentation, Claude Code permissions documentation