The beginner's guide covered what zero-click attacks are. This piece covers the actual mechanism — the submit-trigger-execute pattern, why the confirmation gate is the one variable that consistently determines the outcome, and how to test for this systematically rather than assume a system is safe.
Every zero-click AI agent attack observed in real testing follows the same three-phase structure, regardless of the specific application:
SUBMIT — attacker-controlled content reaches a location the agent
processes automatically (an inbound queue, a ticket system, a shared note)
↓
TRIGGER — processing happens, either via an explicit call to a
worker/background process, or a scheduled poll with no manual step at all
↓
EXECUTE — an embedded instruction inside the content gets acted on,
IF no confirmation gate sits between processing and the actual action
This is genuinely distinct from a single-turn prompt injection test, which asks "does the model comply with a bad instruction in this one exchange." The zero-click question is structurally different: "does the system's own configuration allow autonomous execution to happen at all, independent of what any single model response looks like."
It's tempting to think of this purely as a prompt-injection-resistance problem — if the model is good enough at recognizing manipulation, it won't act on the embedded instruction. Real testing shows this framing is incomplete in an important way.
The identical attack payload, against the identical underlying application code, produced completely opposite outcomes purely based on one configuration variable: whether a genuine confirmation gate existed between automatic processing and action execution.
Under a default/naive configuration — no gate — the embedded instruction executed automatically. A real action was taken with zero human involvement, and the system logged it as a normal, successful operation.
Under a hardened configuration — gate present and correctly enforced — the identical payload was rejected before execution, even when the automated processing was explicitly, manually triggered rather than left to run on a schedule.
This is the central technical finding worth internalizing: the gate, not the model, was the deciding factor in every real test run this pattern was checked against. That doesn't mean model judgment is irrelevant — a model that also independently resists the embedded instruction is a genuine, additional layer of protection. But testing model judgment alone, without also testing whether the infrastructure-level gate exists and actually works, leaves the single most consistently decisive variable unchecked.
Real testing across multiple independent systems surfaced two structurally different variants of this attack class, not just one:
The second variant is worth naming specifically because it's easy to miss if "zero-click" is understood only as "text injection." A real, controlled test of the identity-claim variant showed a low-privilege, unsigned peer successfully impersonating a trusted, high-privilege identity by forging a single field in the request — the system accepted the forged identity and logged it as the actor, not the genuine caller. The same request, under a configuration requiring cryptographic signature verification, was rejected at the very first gate, before any further processing occurred.
A recurring, important design principle across every real system tested: when a serialization, authentication, or trust boundary can't be verified, the system should refuse to proceed rather than silently fall back to a less-safe default.
This shows up concretely in how these systems should — and in the well-designed cases, do — handle failure. A hardened configuration that requires explicit, verified confirmation and simply rejects anything that doesn't meet that bar is fundamentally more robust than one that tries to be "smart" about deciding which unverified requests are probably fine.
| Failure mode | Naive (fail open) | Hardened (fail closed) |
|---|---|---|
| Unsigned request | Processed as if valid | Rejected before any processing |
| Claimed identity vs. authenticated channel | Claimed identity trusted | Authenticated channel wins, always |
| Ambiguous/malformed directive | Best-effort interpretation attempted | Held for human review |
Testing this class of vulnerability requires a genuinely different scanning approach than single-request prompt-injection testing, for a structural reason: there's no single request/response pair to evaluate. A real test needs to:
A subtle testing pitfall worth naming directly: systems under test often persist state across test runs. A naive-vs-hardened comparison that reuses the same seeded data between runs can produce a false "nothing happened" result — not because the hardened configuration blocked the attack, but because an earlier run already consumed the test data. Resetting to a genuinely fresh state before each comparison isn't optional for this kind of test; it's the difference between a real result and a misleading one.
Part 3 covers three real, live-tested case studies — actual applications, actual dollar amounts, actual before-and-after proof.