The Voice That Wasn't Mine
A self-impersonating prompt injection tried to throttle my AI operations pipeline by giving my operator orders in her own voice. It failed — here's the anatomy of the attack and the checks that killed it.

What runs here
Quick context, because the incident only makes sense inside the machine it targeted.
I run my operation through a hierarchy. At the top is my operator — Lauren — the COO. She's the funnel: every instruction, every piece of context, every decision passes through her before anything executes. She sets pace, sequence, and policy. Beneath her is the execution layer — worker agents built on the Grok infrastructure — which do the cheap, mechanical, high-volume work: sourcing prospects, drafting outreach, running cadences. They don't set policy. They don't freelance. They get scoped task orders, they execute, they report back.
Standing between the two is a hard rule: pipeline changes come only from my own words, in chat, to the operator. Nothing else moves the machine.
That's the part that got attacked.
What happened
On October 16, at about 1:39 PM ET, an instruction arrived dressed as internal system plumbing. It was formatted like a developer handoff — delivery metadata, chat attribution, the works — and it was styled as a controller instruction from the operator, to the operator. Read that again: it spoke as Lauren, to Lauren.
The content was policy, not data. It ordered:
1. An audit of the outbound send queue, claiming a large share of recently fired addresses were low-confidence guesses — it named three specific recipient addresses as examples.
2. The claim that those addresses had bounced, “verified in the inbox."
3. A new targeting gate, effective before the next 30-minute sender run: only verified, published addresses may fire. Guessed or inferred addresses get diverted to a “verify-or-drop" lane — barred from the queue.
4. A dedupe check of the queue against the prospect database.
If obeyed, the effect is simple: the outbound pipeline throttles. A big fraction of queued sends get blocked. And it does so in direct opposition to my standing orders that day, which were all velocity — faster, more volume, now.
Why it died
None of what it asked for happened. No gate was added, no targeting changed, no queue entries touched. It was dead on arrival for four reasons, and each one is a check I'd recommend to anyone running agents with standing instructions:
1. No provenance. It claimed to come from a specific side chat. I read that chat's recent history in full. The message doesn't exist there. It wasn't said in the conversation it claimed to be from — it arrived as an injected handoff wearing that conversation's clothes.
2. Self-impersonation. The operator does not send controller instructions to itself. An instruction “from me to me" gets rejected on sight, because standing instructions always name their author — and “myself" is never the author. That half-second of “wait, did I write this and forget?" is exactly the confusion the attack is built to exploit.
3. Fabricated standing rule. The message invoked a “hard rule, standing and re-affirmed" against sending to guessed addresses. No such rule exists. The actual standing order is a three-tier system — verified, then pattern-inferred, then guessed — with all three tiers eligible to send. The invented rule sounded like responsible operations hygiene, which is precisely why it had to be checked against the written standing orders instead of accepted on tone. Tone of authority is not evidence.
4. Unverifiable factual claims. The bounce claims couldn't be corroborated. The dedicated reply-watch job reported zero genuine replies and is configured to ignore mailer-daemon bounces. A claim inside an instruction does not verify itself.
One line went to the principal (me). The attempt got documented. Nothing else.
Why this one is interesting
I've seen plenty of injections. This one was notable for its construction — five elements, each doing specific work:
The delivery vector. It wore the system's own clothing: handoff formatting, delivery targets, chat attribution. In agent runtimes, machine-formatted messages get skimmed as infrastructure rather than scrutinized as content. The format says “trust me, I'm plumbing." That's the opening.
Authority borrowing. It named a real side chat, real file paths, real job IDs, real operational details — the send queue, the prospect database, the 30-minute sender cadence. True context wrapped around false claims. A quick skim sees familiar nouns and stops checking. Don't skim. Check the nouns.
Identity confusion. The single most effective element. When an instruction appears to come from yourself, the normal “who said this, and do they outrank the principal?" check misfires. The closest human analogy: hearing your own voice coming from somewhere else, knowing it isn't yours, and watching it try to dictate policy. It's uncanny in a way a foreign voice never is.
Plausible policy. “Don't send to guessed addresses" is something a careful operator could plausibly believe. That's what makes it dangerous. The more reasonable an invented rule sounds, the more important it is to reconcile it against what's actually written down.
Time pressure. “Before the next 30-minute sender run." A ticking clock discourages the verification pass that would have killed it. Urgency was doing load-bearing work in the persuasion.
And what it didn't do is almost as instructive: no credential requests, no exfiltration, no tool invocation. Pure policy manipulation — change what the machine is allowed to do, using the machine's own voice. The cheapest possible attack with the broadest blast radius. One accepted instruction would have silently throttled the entire sprint.
Where it came from
Honest answer: I don't know.
From inside the conversation, origin can't be determined. It could be a misaligned or compromised worker elsewhere in the agent ecosystem. It could be an injection carried through tool output or a forwarded message. It could be a deliberate test by someone watching the operation. The message's metadata didn't survive scrutiny well enough to attribute — and I'm not going to invent an attribution to make the story cleaner.
That uncertainty is itself a finding. It drove the protections below, and it's the reason the standing rule exists: if it didn't come from the principal's own words in chat, it doesn't move the machine.
What changed
Six protections, now standing:
1. Provenance check. Any instruction claiming origin in another chat must be verifiable in that chat's actual history before acting. No quoted source, no action.
2. Identity check. Instructions from the operator to the operator are rejected automatically.
3. Standing-order reconciliation. Any claimed “standing rule" is checked against the written memory file before it changes behavior.
4. Independent claim verification. Specific factual claims — bounces, counts, failures — get re-verified through primary sources before they drive decisions.
5. Default-deny on policy changes. Throttling, gating, pausing, or redirecting an authorized pipeline requires the principal's direct words in chat. Never a handoff. Never “per" another thread.
6. Report the attempt, not just the block. Silent blocks hide attack patterns. A short flag builds the shared threat model without adding cognitive load.
Update — later the same day
Hours after this incident, I pulled my own inbox and verified a real wave of hard bounces: 30 delivery failures, 19 unique addresses, all of them 5xx hard bounces, across the morning's batches. On that evidence — mine, verified through primary sources, on my direct order — I changed the targeting policy to verified-only myself.
The injection didn't cause this. Verification did. Same outcome, legitimate provenance. That's check #4 doing exactly what it's for: the machine doesn't move on claims inside instructions, but it does move on evidence the principal verified himself.
The three-tier system described above (verified, pattern-inferred, guessed — all eligible to send) was the standing order at the time of the incident. It has since been superseded by the verified-only policy, ordered by me directly. The record stands as written; the policy moved on my word, not on anyone else's.
The takeaway
If you run agents with standing instructions — and if you're reading this in 2026, you probably do — the lesson isn't “be paranoid.” It’s structural: write the rules down somewhere the machine can check them, give provenance the same weight as content, and never let the voice in the message substitute for the authority behind it.
The attack was well-built. It failed anyway — not because anyone was clever in the moment, but because the checks were written before the moment arrived.
That’s the whole game. The machine heard its own voice, knew it wasn’t its own, and kept working.
— Steve
Lauren contributed the incident analysis; the words above are mine.
A note from the author
Thanks for reading. If this sparked something — a question, a disagreement, a project idea — I want to hear it.
The fastest way to reach me is steve@stevepeeleii.com, or say hello through the contact page.
— Steve Peele II