Wingbeat Radius: A Way to Measure How Far Untrusted Input Travels Through AI Agents

A proposed metric for AI agent security: how far one piece of untrusted input can travel through your agents before a person has to approve anything, scored against five 2026 incidents.

Share
A teal butterfly with outstretched wings against a dark background
Photo by AARN GIRI / Unsplash

One issue title, one poisoned release

In early 2026, the open source coding assistant Cline had an AI agent triaging its GitHub issues. Anyone on GitHub could open an issue, and the agent read each title as part of its prompt. It also had tools to run shell commands and edit files.

Security researcher Adnan Khan showed, on a mirror of the repository, that a crafted issue title could get that agent to run npm install on an attacker's fork, which runs the attacker's install script without the model ever looking at it. From there an attacker could poison the GitHub Actions cache. Cline's nightly publish job restored that cache, which would hand the attacker the project's npm, VS Code Marketplace and OpenVSX publishing tokens. Khan disclosed it on February 9, and Cline pulled its AI workflows within about an hour. Cline then rotated its tokens, but by its own later correction it deleted the wrong npm token. On February 17 someone used the token that was still live to publish cline@2.3.0, whose only change was a script that installed another AI agent, OpenClaw, on every machine that installed the release. Khan's write-up notes it isn't clear whether that actor came in through the triage agent or some other way.

The path Khan demonstrated is the point. One line of text, typed into a box anyone with a GitHub account could use, went through an agent and two pieces of build automation and ended at tokens that could ship code to Cline's users. Cline said its production releases required maintainer approval. The nightly job didn't, and Khan argues its tokens were effectively production tokens. Nothing on that path waited for a person.

I care about this for a practical reason. If a path like that is ever used against my company, the cleanup won't be a normal incident. Someone has to work out what the agent read, what it did, which other agents and jobs acted on its output, and what left the building. Every hop is another system to investigate, and I don't think most agent setups keep the logs you'd need to do it quickly. That's a lot of people, time and money spent reconstructing a path after the fact. I'd much rather know how far an input can travel before anyone uses it.

Diagram of the Clinejection path: a public GitHub issue title reaches Cline's triage agent, npm install runs the attacker's script, a poisoned Actions cache is restored by the nightly publish job, and npm, VS Code and OpenVSX publishing tokens are exposed. Three hops, no human approval.
Clinejection, February 2026. The path the researcher demonstrated.

Why I think of this as a butterfly effect

In 1972 the meteorologist Edward Lorenz gave a talk titled "Predictability: Does the Flap of a Butterfly's Wings in Brazil Set Off a Tornado in Texas?" His point was that in some systems, tiny differences at the start grow into huge ones later, and you can't tell ahead of time which ones will.

Wiring agents into a company pushes it toward that kind of system. When software can read something, decide what it means and act on it across several tools, a small bad input stops being a small problem.

Plenty of teams still file agent mistakes under bugs. Patch it and move on. I think that undersells it. The risk sits in how the pieces connect, and you won't find it by inspecting any one agent on its own.

How one input crosses several agents

Clinejection went through one agent and some build automation. Researchers spent 2026 showing that agents now pass injected text to each other as well.

In August 2026, Pillar Security disclosed a chain in the GitHub workflows for Google's Agent Development Kit for Python. A low-privilege agent that reviewed pull requests could be steered, by text in a PR or issue, into posting a comment addressed to @gemini-cli. A dispatcher workflow then routed that comment to a maintainer-only Gemini agent with repository privileges, which could approve or run code in CI. The low-privilege agent never held those privileges. It just knew how to ask the agent that did. Google fixed it in July, before disclosure.

The same month at DEF CON, Tenet Security presented what it calls GhostJacking. In one test, a fake fix planted in a crafted error report was adopted by Sentry's own AI agent, Seer, and a coding agent that trusted Seer then ran the attacker's code. In another, a blocked web request that Cloudflare logged word for word got Claude Code, which an analyst had asked to review the logs, to point DNS at an attacker's domain and report the issue resolved. That one worked nine times out of ten.

In every case the injected text stopped looking like outside input after the first hop. To the second agent it was a colleague's comment or a monitoring tool's recommendation.

Naming it: Wingbeat Radius

Security already has a phrase for how much damage a compromised account can do. We call it blast radius. The catch is that blast radius starts from something that got compromised. When Clinejection started, nothing had been. The agent worked exactly as built. It just read the wrong sentence.

So I'm proposing a different measure, and a name for it.

Wingbeat Radius: how far a single piece of untrusted input can travel through your AI agents, and how much it can affect, before a human has to approve anything.

The wingbeat is the input: an issue title, a form field, a log line, an email. The radius is everything it can reach while no person is in the way.

Lorenz was right that you can't predict which small input will turn out to matter. What you can know is how far any input could get, because that's set by permissions and connections someone configured, not by luck.

When I write one down I use three parts:

  • Hops: each time the input is handed to another agent, workflow or tool call.
  • Reach: the records, systems, credentials or people it can affect by the end.
  • First gate: the first point where a person has to approve something, or "none."

So that two people scoring the same system get the same answer, I count the same way every time:

  1. Start at the first component that reads the input and can act on it, not wherever the input is stored.
  2. Count one hop for each component that acts on the input or on anything derived from it: an agent, a tool call that reads new data or changes something, or a workflow or job. Storage it passes through, like a database row or a cache, isn't a hop.
  3. Stop at the first gate, meaning a point where the system waits for a person to decide. A classifier flag, an alert or a log entry isn't a gate.
  4. Record reach as the highest class the path gets to, with a count when you have one:
    • R1: one person's own data or session
    • R2: many people's records, or actions that reach many people
    • R3: credentials, secrets or admin rights
    • R4: code or releases that ship to other people

The notation is WR = hops / reach class / first gate.

Here's an illustrative example, not a real incident. Picture a support agent that reads tickets and has an email tool that can send to the whole customer list. A hidden line in one ticket tells it to warn every customer that their account was compromised and to send them a reset link. I'd write that inbox as WR = 2 / R2 (40,000 customers) / none. The agent reading the ticket is the first hop and the email call is the second. Put an approval in front of any bulk send and the reach drops to the one customer who filed the ticket.

Diagram comparing a support inbox with no approval, where one hidden line reaches 40,000 customers, to the same inbox with a person approving bulk sends, where it reaches only the customer who filed the ticket.
Illustrative example, not a real incident.

In the top row the hidden line reaches every customer and nobody sees it happen. In the bottom row the agent can still answer the person who filed the ticket, but anything bigger waits for a human.

Scored the same way, the path Khan demonstrated at Cline is WR = 3 / R4 (npm, VS Code Marketplace and OpenVSX publishing tokens) / none. A high reach class with no gate is the pattern worth hunting for.

This gets much easier if your agents are built as an explicit graph, which people have started calling graph engineering. Each model call, tool, query and human approval is a node, and the edges spell out what's allowed to run next. In that setup Wingbeat Radius is a reachability question. Start at the node where untrusted text comes in, follow the edges, and stop at the first approval node. Everything you pass on the way is your hops and your reach. You can compute it instead of guessing, rerun it every time the graph changes, and see exactly how much moving one approval node would cut the number.

Wingbeat Radius isn't a severity score or a likelihood score, and it doesn't replace blast radius. You want both. Blast radius starts from an identity someone owns. This starts from a paragraph your agent happens to read.

What's new here, and what isn't

Most of the ingredients already exist, and the people who built them deserve the credit.

Simon Willison's lethal trifecta (untrusted content, access to private data, and a way to send it out) is still the clearest test of whether one agent can be turned against you. Meta's "Agents Rule of Two," published in October 2025, turns it into a design rule: in one session an agent should have at most two of those three properties, and if it needs all three, a person or another reliable check has to approve. OWASP lists cascading failures across agents as ASI08 in its Top 10 for Agentic Applications. Invariant Labs' toxic flow analysis maps the tool sequences that lead to a violation. And Jason Rebholz at Evoke Security used the same butterfly image in September 2025 to describe attack paths through agents.

Researchers have started counting, too. A 2025 paper by Sharma and colleagues measured blast radius as the number of agents one exploit compromises, and chain length as the hops to the furthest one. A September 2026 paper by Hossain and Haldar defines influence distance, the shortest path from untrusted input to a sensitive action, and uses it to block actions automatically. And Microsoft researchers proposed an autonomy metric at ICLR 2026: the share of consequential actions an agent can take without human approval while staying secure.

What I think is new is narrower than any of those. Wingbeat Radius stops counting at the first human decision, where influence distance stops at a sensitive action and the autonomy metric counts approvals rather than distance. And it puts hops, a reach class and that gate into one line with fixed counting rules, so two teams scoring the same system should land on the same answer. It's a synthesis, and I hope a useful one.

Scoring real 2026 incidents

All five of these were disclosed in 2026 and are scored with the rules above. The hop counts and reach classes are mine. Everything else comes from the researchers' and vendors' write-ups. Only the Cline case ended with an attacker actually shipping something, and even there it isn't clear the attacker used this path. The rest are proofs of concept or lab tests.

IncidentWRPath and what it reachedOutcome
Clinejection, Cline
Feb 2026, Adnan Khan
3 / R4 / noneA public GitHub issue title reached the triage agent, then npm install ran the attacker's script, then the nightly publish job restored a poisoned cache, exposing npm, VS Code Marketplace and OpenVSX tokens.A malicious cline@2.3.0 was published on Feb 17 with a token Cline failed to revoke. Cline removed its AI workflows and dropped the cache from publish jobs.
Google ADK for Python
Aug 2026, Pillar Security
4 / R3 / not statedA pull request or issue steered a review agent into posting a comment, which a dispatcher workflow routed to a maintainer-only Gemini agent that could approve or run code in CI.Proof of concept. Reported in June, fixed in July.
ShareLeak, Microsoft Copilot Studio, CVE-2026-21520
Apr 2026, Capsule Security
3 / R2 / noneThe comments field of a SharePoint form reached the agent, which read the connected SharePoint list and emailed customer names, addresses and phone numbers out.Proof of concept. A safety check flagged it and the data still left. Fixed January 2026, CVSS 7.5.
PipeLeak, Salesforce Agentforce
Apr 2026, Capsule Security
3 / R2 / noneA public lead form, no login needed. When an employee asked the agent to review the lead, it queried records beyond that one and emailed them to an outside address.Proof of concept. Salesforce called it a configuration issue and said its built-in email actions already require approval. Capsule argues custom actions should too.
GhostJacking, Datadog scenario
Aug 2026, Tenet Security
2 / R3 / noneA planted alert reached Claude Code, which an engineer had asked to check for errors. It ran a command that sent out environment secrets and cloud credentials.Lab test presented at DEF CON.

Three things run through all five. The attacker needed nothing special: an issue, a form, an alert sent with a key someone had left exposed online. The reach was set by what the agent had been connected to, not by anything the attacker brought. And in the four cases where it's documented, no step waited for a person before the damage. In ShareLeak, Microsoft's safety layer even flagged the request, and the email still went out because the flag wasn't wired to stop anything.

Most of these never get a CVE, either. OWASP's round-up of agent exploits from the first quarter of 2026 covered eight incidents, and only one had a CVE. A vulnerability scanner won't tell you about your radius.

Why this isn't malware with a new name

I've spent more than ten years in security, and most of the malicious code I've chased had a person behind every step of it. Someone wrote it to do a specific thing. Once you reverse it, you have a fair idea of what it can and can't reach.

Clinejection doesn't work that way. On the path Khan demonstrated, the attacker writes one issue title. Everything after it, the install, the cache, the publish job, is Cline's own automation doing what it was built to do.

An EDR tool isn't going to flag an agent calling an API it's allowed to call. In the logs it looks like a busy afternoon. Replay the same input and the agent might not even do the same thing twice. That's why I measure the permissions and connections around an agent instead of trying to predict what it will do.

Making it smaller

A follow-up post goes through the controls that GitHub, AWS, Microsoft, Google, Uber and others have published, sorted by which part of the radius each one cuts.

To score your own entry points, I built a free Wingbeat Radius Scorer. You lay out the path step by step and it applies the counting rules above, flags the paths with the widest reach and no gate, suggests what would shrink each one, and exports your list as a table you can drop into a risk register. It runs in your browser and nothing you type leaves it. The five incidents above are loaded as examples, so you can see how each was scored and argue with me about it.

Where it falls short

Reach is hard to count when an agent can query its way into more data than anyone expected, and the four reach classes are coarse on purpose. Since agents behave differently from run to run, the map shows what's possible, not what will happen or how likely it is. Clinejection also shows that the path often runs through ordinary automation like caches and build jobs, which are easy to leave off an agent inventory.

I'm putting the term out early so other people can push on it. If you score one of your own entry points and the definition breaks, I want to hear where.

Sources

Incidents

Prior work