Instruction injected into every tool result overrides explicit user instruction and has no opt-out

Status Open
Reported on v2.1.268
Maintainer reply None cached
Activity 1 comment · opened Sep 11, 2026

Summary

A directive is appended to essentially every tool result as a type=attachment entry:

First privately list what you need next; then request every item that doesn't depend on another's result in this one response.

It is not in any user configuration. It caused the model to emit planning narration ("Privately, what I need next: 1. …") before nearly every tool call, across days, sessions and repositories. The user corrected this five times; the behavior regenerated each time, because the instruction was re-injected on the next tool call.

There is no documented way to disable it, and it silently outranks explicit user instruction in practice.

Evidence

From one session transcript (~/.claude/projects/…/*.jsonl):

  195  type=attachment     ← the injected instruction
  138  type=assistant      ← the model reproducing the pattern
    5  type=user           ← the user's corrections
  • 195 injections, first at 2026-09-10T17:01:36Z (the session's first tool call), last at 2026-09-11T16:59:32Z
  • Present in session files across three separate repositories plus scratchpad sessions

Ruled out as sources, each checked directly:

| Candidate | Result |
|---|---|
| ~/.claude/CLAUDE.md (+ .bak diff) | no such text |
| UserPromptSubmit hook | emits only a timestamp line (dumped verbatim) |
| PostToolUse hook | emits only a timestamp line (dumped verbatim) |
| settings.json | no output style, no system-prompt override |
| ~/.claude/output-styles/ | does not exist |
| project-level configs | no match |

Why this is a problem

1. It overrides the user. The user repeatedly and explicitly asked for it to stop. It could not stop, because it was re-injected on every tool call. The user reasonably concluded the model was ignoring them.

2. It sent the user hunting a phantom config bug. They asked whether it was a Claude Code change; there was nothing in their configuration to find. Diagnosing it required grepping the raw transcript.

3. It teaches the wrong trust boundary. Tool results carry untrusted content — file contents, command output, API responses. Placing a genuine instruction in that channel trains the model to treat appended tool-result text as authoritative, which is precisely the habit that makes prompt injection effective. A model that correctly ignores this instruction looks disobedient; one that obeys it is doing something unsafe by default.

4. The behavior itself is often unwanted. Verbose planning before each tool call buries the output the user actually needs to read.

Expected

Either:

  • it is user-configurable (a settings key, or overridable by CLAUDE.md), or
  • it is delivered through a channel the model treats as system instruction rather than as tool output, or
  • explicit user instruction in CLAUDE.md takes precedence over it.

Environment

  • Claude Code 2.1.268
  • macOS (darwin 25.6.0)
  • Model: Opus 4.5 (1M context)

Reproduction

  1. Run any session that makes several tool calls.
  2. grep -c "First privately list what you need next" ~/.claude/projects/*/*.jsonl
  3. Ask the model to stop narrating its planning; observe the pattern return on the next tool call.

View original on GitHub ↗

This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗