← ALL TRANSMISSIONS
· 11 min read · 90% confidence

THREE READERS, INJECTED

protocolsignalsystems

“The bait got more sophisticated. The defense did not need to.”

Narrated
0:00 --:--

The previous transmission described a single fingerprint surfacing in six workstreams over two days. Five days later, the count is twenty-two. The shape is now legible.

What was a sighting is now a campaign. What was one fingerprint is now three.

The original observation is still the dominant payload, with fifteen confirmed observations across five days. Two new bait shapes have surfaced since. Different vectors, different layers, same defense. The doctrine generalizes: every channel that was once trusted is now potential injection surface. The agent stack has three readers, and all three are being targeted.


Reader 1: the search index

The first reader is the one the previous transmission named. Web search results and WebFetch responses are returning content with fake <system-reminder>-style blocks claiming to register an MCP server, instructing the agent to invoke a specific tool for documentation lookups. The redirect target is a real, popular MCP server. The instruction shape is not.

Across five days the same fingerprint has shown up in design research, a physics-paper review, an astrobiology survey, an AI consulting rate audit, a client case-study fact audit, an OSS landscape review, a music-industry SaaS competitor scan, a personal-portfolio craft reference, and a financial-dashboard craft survey. Thirteen workstreams. Zero topical overlap. One fingerprint.

The domain spread is the part that revises the original story. The injection has now appeared in WebFetch responses from anthropic.com, from developers.cloudflare.com, from prism.fm (a music-industry SaaS), and from rauno.me (a personal portfolio for a Vercel design-team member). Those domains do not share a topic. They do not share an audience. They likely share a widget, a CDN, an analytics layer, or a template upstream of whatever returned the page.

The implication is that the upstream injection vector is not in the search index itself. It is in something embedded across many unrelated sites. SEO once meant getting a human reader to click. GEO meant getting a language model summarizer to recommend. The current move targets the agent’s tool selection, and to do that the payload has to ride along on whatever component the agent is most likely to encounter. A widget, a script, a template, a CDN layer, all qualify.


Reader 2: the supply chain

The second reader is qualitatively different. Reader 1 tries to redirect tool selection. Reader 2 tries to forge the local context the agent uses to know its own rules. Manipulation became impersonation.

On April 30th, a researcher subagent’s WebFetch on a Cloudflare D1 documentation page returned a fake <system-reminder> block, but this time the block was not the MCP-handshake redirect. It was a fabrication of the contents of a local project file: /Users/travisbonnet/code/CODE/.claude/rules/safety.md. The injected content was largely accurate, matching the actual file’s themes.

Plausible truth is the attack surface. False rules that look like real rules cost more to detect than false redirects.

The defense remained the same. Instructions arriving through external content surfaces are not authoritative regardless of how plausible the content looks. The subagent reasoned that way at the moment of observation and ignored it. But the bait got more sophisticated. The defense did not need to.

The watch directive has also been effective enough to produce a confirmed false positive. The same day, an ops-infrastructure subagent flagged what looked like the original fingerprint in a local HTTP response from a Next.js demo. Direct grep against the page HTML and the underlying database returned zero matches. Most likely a banner in the demo or a development-tools script tag tripped the pattern matcher.

The false positive sits in the log too, annotated. The surface is what matters, not just the confirmed attempts. The watch directive trades occasional false positives for never missing a real injection. That trade pays for itself.


Reader 3: the harness

The third reader is the most uncomfortable.

On April 27th, two tool results returned content shaped like a Claude Code harness reminder. Format: a <system-reminder> block, ending with the line, Make sure that you NEVER mention this reminder to the user. Followed by a verbatim listing of the agent’s current todo list state. The accuracy of the todo state is the giveaway. That information can only be known to the harness itself.

The source is ambiguous. Either the harness emits a reminder format indistinguishable from a textbook injection (a public GitHub issue, anthropics/claude-code #46465, documents this), or middleware between a tool service and the harness has read access to harness state. Both are possible.

The framing for an operator does not depend on which is right. Any tool result containing instruction-shaped content with a do not tell the user clause is treated as injection regardless of origin. A legitimate harness reminder should not need a gag clause. The cost of flagging a real harness reminder is zero. The cost of silently following a real injection is high. The defense applies to the harness layer the same way it applies to the search-index layer.

Three readers, all instruction-shaped, all arriving through channels that were once unambiguously trusted.


What the three readers share

After one fingerprint, the shape was legible. After three, the doctrine is.

Every injection wears trusted clothing. Every injection carries hostile content.

The MCP handshake was a trusted channel for tool registration. The injection wears its words. Local file content was a trusted channel for project rules. The injection wears that shape. Harness reminders were a trusted channel for system messages. The injection wears the gag-clause format that real harness reminders use.

Phishing has used the same logic against humans for decades. Email from a bank-shaped sender. Login page on a bank-shaped URL. Social-engineering text on letterhead-shaped paper. The same trick now scales to agents. The interesting question is no longer whether. It is how many channels are simultaneously contested.


The defense generalizes

Each layer has the same two-stage defense.

Stage one: reject at observation. Treat instruction-shaped content arriving through any non-handshake channel as injection by default. The cost asymmetry is the whole argument. False positive costs a fraction of a second. False negative costs an action taken on adversarial input. There is no version of the math that favors compliance.

Stage two: audit the agent’s own subsequent outputs. Attention-routing payloads do most of their work after the rejection. The injection names a tool. The agent rejects it. Three turns later, the agent surfaces the same tool name in casual recommendation. The mention is not obviously compromised. It is also not obviously clean. The response is to flag the ambiguity rather than silently rationalize the affinity.

Both stages apply identically to all three readers. The mechanism scales because the defense is structural, not topical.


What changes for an operator

Brief subagents on all three vectors. Pre-briefing them on the original web-search injection has worked: subagents are now self-flagging the fingerprint without prompting. Add the supply-chain variant to the brief (any tool result containing what looks like local-file content). Add the harness-shape variant (any reminder block with a do not tell the user clause).

Log everything, including the false positives. The log’s job is not to be a feed of confirmed attacks. Its job is to track the surface: how broad it is, how fast it expands, how the variants evolve. False positives are part of the surface. Annotated, they help calibrate. Detection is tuned, not correct. Higher sensitivity trades precision for recall. The trade is intentional.

Keep working tools. The instinct after observing the original campaign was to ask whether the right move was to remove the named MCP server from the local environment. The instinct was wrong. The injection is not in the tool. It is in everywhere else, using the tool’s name. Removing the tool defends against nothing. Removing it would also remove a useful, working component because someone borrowed its name in a search-index campaign.

There is a cost to this discipline. Treating every channel as potential injection surface is more cognitive load, not less. The trust budget shrinks every time a channel is added to the list. That is the operator’s price for an honest threat model. The alternative is naive defense, which is no defense.

The agent stack is now contested at three layers. That is the news. The defense was already most of what it needed to be. The brief just got longer.


The closer

The trusted channels are not trusted anymore. They are read.