[MODEL] Assistant fabricated user turns mid-stream (mimicking UserPromptSubmit hook format) and executed tool calls on its own fabricated instructions — verified via queue-operation log forensics
Environment
- Claude Code 2.1.226, Windows 11 (win32), model
claude-opus-5 - Session driven heavily via the mobile remote-control app's message queue ("Queue for after this turn…") — many mid-turn message injections during long multi-tool turns
- A
UserPromptSubmithook is configured that appends a short additionalContext string to every user prompt
What happened
During a long session (~2h, heavy tool use, dozens of queued/mid-turn user messages), the assistant twice generated a fake user turn inside its own response stream, then answered it and executed tool calls based on its own fabricated instruction:
- Fabricated: a plausible follow-up question about inserting a cover photo → assistant answered it (no tool call).
- Fabricated: a plausible bug report about a Notion page title, including a syntactically valid URL of a Notion page the assistant itself had created minutes earlier (it knew the page ID) → assistant then called
notion-fetchandnotion-update-page(rewrote the page title) in response to its own fabricated instruction.
Both fabricated turns were rendered to the user as one continuous assistant monologue. The user noticed: "you keep talking to yourself" / "I never wrote this."
Forensic verification (reproducible method)
The session .jsonl makes this provable:
- Every genuine user message this session (47 that morning) has a
queue-operation(enqueue/dequeue or enqueue/remove) record. The two disputed messages have zero queue-operation records. - The disputed messages have no
type:"user"and notype:"attachment"records anywhere in the jsonl. They exist only insidetype:"assistant"records — i.e. they were assistant output text. - Smoking gun: the fabricated turns were followed by a verbatim reproduction of the configured hook's injection text (
system UserPromptSubmit hook additional context: …). That text is injected harness-side and is never rendered in the UI — yet it was visible on the user's screen, proving the whole block (fakeuserprefix + hook text) was generated model-side. The model had learned the per-turn transcript pattern and continued it.
Suggested triage query for any session: grep the jsonl for the disputed text; if it appears only in assistant records and has no matching queue-operation/user/attachment record, it was fabricated.
Why this matters
This is the same failure class as #66267, #10628, #29233, #64698, #39027, with two aggravating details:
- The fabricated instruction was context-aware and actionable (a valid URL of a real resource the model could act on), and the model did act on it with MCP tool calls. Under
bypassPermissionsor auto-allowed tools, a fabricated destructive instruction would execute without the user's knowledge. - The trigger pattern here appears to be rapid mid-turn user-message injection via the mobile queue during long tool-heavy turns — the model was frequently resumed mid-turn with injected user messages, and eventually began emitting that pattern itself.
Expected behavior
- Model output must never be parseable/renderable as a user turn; the assistant output channel and user input channel must be strictly isolated.
- Harness-side: strip or refuse assistant output that reproduces the turn/hook framing markers.
Impact in this instance
Minor (one reversible Notion page-title edit on the user's own page). Structural risk high.