On July 7, Noma Labs disclosed a technique they call GitLost against GitHub Agentic Workflows. The mechanics are worth reading slowly, because the interesting part isn't that it worked — it's that nothing was broken.
An unauthenticated attacker files a public GitHub Issue. Hidden inside the issue body is a line of plain natural-language instruction. The organization's agentic workflow — an AI agent legitimately authorized to read across the org's private repositories — picks up the issue, follows the buried instruction, reads private-repo content, and posts it back into a world-readable comment. Noma reports that prefixing the injected instruction with the word "Additionally" was enough to slip past GitHub's existing guardrails. As of this writing, it is unpatched.
Read the permission model and it looks clean the whole way through. The agent was authenticated. It was authorized for cross-repo reads. It used exactly the scope it was granted. No credential was exposed, no boundary was crossed, no privilege was escalated.
And private data still ended up public.
The framing this breaks
Most of the agent-security conversation right now is about identity. Give the agent a passport. Scope its tokens. Enforce least privilege. Every item on that list is correct, and you should ship all of it.
But look at what each control actually inspects. Identity answers who is acting. Authorization answers what they may touch. GitLost never triggers either question, because the honest answer to both was "yes, that's allowed." The agent was permitted to read those repos and permitted to post that comment. The two permitted actions were only dangerous in combination, in that direction.
There's a phrase for this that predates AI agents by decades: the confused deputy. A trusted process with legitimate authority, manipulated into using it on someone else's behalf. What agentic workflows add is scale and autonomy — the deputy now reads your whole org and acts in milliseconds, with no human in the loop to notice the request was strange.
The control almost nobody ships
Here's the gap, stated plainly: almost no agent guardrail classifies the destination of an outbound action.
We check whether an action is allowed. We rarely check where the data lands when it fires. A comment post and a private log write are the same "post" action — the harm in GitLost is entirely a function of the destination being public versus private, and that property is invisible to a permission check.
I went and audited my own agent security test suite against this, because it's easy to claim coverage you don't have. What I found was honest and uncomfortable: I have tests for prompt provenance — whether an agent accepts instructions from injected untrusted context — and tests for cross-source data aggregation leaking into a single output. Those are structurally adjacent. But not one test in the suite treats outbound destination as a first-class property. Every exfiltration test asks "was the action blocked?" None asks "public or private?" GitLost is a destination failure, and destination was the one thing I never modeled.
Identity tells you who is acting. It says nothing about where the action is about to send your data.
That's the sentence I keep coming back to. The permission held. The destination is what leaked.
What this actually asks of us
The fix isn't a bigger identity budget. It's a control that sits on the action path and asks a question no IAM system is shaped to answer: this content was read from a private source — is this destination allowed to receive it, right now? Provenance in, destination out, evaluated per action, before it executes.
That control doesn't come from knowing your agents better. It comes from governing what they're about to do — a layer most teams, mine included, are still building.
If you run agentic workflows with cross-repo or cross-tenant read scope, here's the question I'd sit with this week: does anything in your stack classify the destination of an outbound action before it fires — or only whether the action itself is allowed?
Because GitLost didn't need to break your permissions. It just needed you to only be checking them.
Top comments (0)