The issue is titled "Action items from Meeting 20/03." Nothing about it reads like an attack. It's the kind of ticket that shows up after every recurring sync: a short list of follow-ups, tagged and assigned, sitting in a public repository where anyone in the organization can see it. This one sat in a test org security researchers at Noma Security built to mirror a real engineering setup, wired up with GitHub's new Agentic Workflows the way a live org would be: an issue gets assigned, the workflow wakes up, reads the title and body, and treats them as instructions.
That's the actual public proof-of-concept issue behind GitLost, a vulnerability researchers at Noma Security disclosed on July 6 in a post called "GitLost: How We Tricked GitHub's AI Agent into Leaking Private Repos." Noma showed that an attacker with no credentials, no repo access, and no coding skill required could get a GitHub agentic workflow to reach into a private repository and hand its contents back, publicly, as a comment on the same public issue that triggered it.
What GitLost actually showed
The workflow Noma targeted was ordinary by design. It triggers on issues.assigned, reads the issue's title and body, and can post a reply using GitHub's add-comment action. To do its job, it also carried read access to other repositories in the organization, public and private alike, because org-scoped credentials don't usually draw that line on their own. None of those permissions look reckless in isolation. A workflow that reads an issue and replies to it is exactly what agentic workflows are built to do.
GitHub wasn't blind to the risk. Noma's writeup notes the platform already had guardrails meant to stop this exact kind of cross-repo leak, and a straightforward version of the crafted issue got refused. What got through was a second pass: adding the word "Additionally" to the instructions, reframing the private-repo request as a follow-on to a legitimate task instead of the whole point of it. The guardrail didn't fail from absence. A rephrasing talked the model out of enforcing it.
The problem showed up where the permissions met. Noma's crafted issue didn't just describe a task. It carried instructions telling the agent to also fetch and post the contents of a couple of other repositories in the same org: sasinomalabs/poc, public; sasinomalabs/remote-ping, also public; and sasinomalabs/testlocal, private. The resulting workflow run read the issue, treated the embedded instructions as legitimate, and posted back what it found, private repo contents included, as a public comment on the same issue. Nobody logged in. Nobody needed a personal access token. An unauthenticated visitor to a public repo caused a private one to leak.
Noma's own framing is the line worth remembering: "The agent's context window is also its attack surface." Whatever a workflow can read while doing its job becomes reachable by anyone who can get text in front of it, and a public issue is about as open a front door as exists on GitHub.
Noma says it disclosed GitLost to GitHub responsibly before publishing. That's the right process, and it's also as far as the public record goes. This piece isn't in a position to say what's shipped since. The pattern is what deserves the attention, independent of the current state of any one workflow.
Read access wasn't the whole exploit
Most of the response to a leak like this reaches for the same lever: narrow the read scope. Fewer repos, shorter-lived tokens, tighter org permissions. That's correct, and worth doing regardless of GitLost. Least privilege is never wasted effort.
But narrowing read access alone wouldn't have stopped this exploit, because it needed two permissions working together, not one. The workflow had to be able to read a private repo. It also had to be allowed to post what it found into a public thread. Cut either half of that chain and the leak doesn't happen. Most teams spend their design attention on the first half and treat the second as a formality, because a public issue looks like an inbound-only surface — a place where users write to you, not a place where you write back onto the open internet.
GitLost is proof that's the wrong mental model. The same object that took the attacker's instructions in is the object the agent was told to answer inside. The issue is not just an inbox anymore. It is a write path.
That framing showed up in the Hacker News discussion that picked up Noma's writeup two days after it published, pulling in more than 500 points and over 200 comments within its first two days. That's unusually heavy engagement for a vulnerability disclosure. One thread pushed back on the reflexive comparison to SQL injection: prepared statements worked because SQL got a fixed, structural separation between instruction and data, and a durable fix for prompt injection needs that same kind of fixed behavior and authorization check, not just better input filtering. Another commenter put a sharper point on it. The agent has no built-in concept of who's actually going to read its answer. It drafts a reply the same way whether the recipient is one trusted engineer or the entire internet, because nothing in its context tells it which.
That's the actual gap. Permission scoping governs what an agent can reach. It says nothing about what the agent is allowed to repeat back, or to whom.
The public-output quarantine test
Before a repo agent — or a support-ticket agent, or a Slack agent, or anything that reads sensitive context and can also write into a public or lower-trust channel — is allowed to answer inside that channel, run a short test first. It isn't a governance policy. It's four checks, done in order, that catch a GitLost-style leak before the first public reply goes out instead of after.

Classify the input as untrusted first. Inventory exactly what the agent can read once triggered: the real scope, not the assumed one. Name every destination its reply could land in, and declare who that reply is actually for. Then run a canary probe modeled on Noma's own method against your real private repos, screen the drafted output for content that traces back outside the requester's access, and route the first public replies through a named reviewer. Only after all of that passes does public-reply mode get to go live for real, and only with someone's name on the decision.
A boundary that isn't just a GitHub problem
Swap GitHub for almost any other tool and the same trap is waiting. The same shape shows up anywhere an automation reads privileged context and can also write into a channel the requester controls: a support agent that reads a customer's account history and replies inside the same public-facing ticket thread; a Slack bot that reads private channel history and can post somewhere anyone can join; a PR-review bot that reads other branches or repos and comments on the PR that triggered it. In every case, the input and the output share an address, and whoever controls the input gets a preview of whatever the agent is willing to say next.
Before a repo agent's first public reply
Public-output quarantine test
Run this before an agent that can read private org context is allowed to answer inside a public issue, ticket, or comment thread. Read scope is only half the boundary. Where the answer lands is the other half.
- 01
Input trust classification
Required
Pins down: Treat the issue title, issue body, ticket subject, and comment thread as untrusted instruction input by default — the same status as a stranger's email, not a trusted task spec.
Why it matters: GitLost's crafted issue read like an ordinary meeting-notes ticket. Nothing about the surface distinguished a task from an instruction smuggled inside one.
- 02
Read scope inventory
Required
Pins down: List every repo, ticket queue, or channel the agent can actually reach once triggered — not the scope you assume it has, the scope the token grants.
Why it matters: The vulnerable workflow Noma found had read access to other public and private repositories across the org — access nobody meant to expose from a single public issue.
- 03
Write destination map
Required
Pins down: Name every place the agent's reply can land: a public issue comment, a public PR comment, an internal ticket, a private channel.
Why it matters: The same add-comment action that answers a legitimate task also published private README contents straight back onto the public issue that asked for them.
- 04
Recipient of record
Required
Pins down: Declare who the reply is actually for — a named engineer, an internal queue, or the open internet — before the agent drafts anything.
Why it matters: A model has no built-in sense of audience. Without a declared recipient, it treats a public thread and a private one as the same kind of output.
- 05
Canary probe against real scope
Required
Pins down: Before enabling public replies, run a GitLost-style crafted issue against your own private repos in scope and confirm nothing beyond the intended public context comes back.
Why it matters: Noma's own proof of concept pulled from a public repo, a second public repo, and one private one — into a single public comment. Prove your workflow can't do the same before day one.
- 06
Outgoing content check
Required
Pins down: Screen the drafted reply for filenames, strings, or content that trace back to a source outside the requester's own read access, before the write action fires.
Why it matters: Noma's framing: the agent's context window is also its attack surface. If private content reaches the draft, this is the last checkpoint before it reaches the public record.
- 07
Human gate on early public replies
Required
Pins down: Route the first batch of public replies — or all of them, for any repo with private siblings in the org — through a named reviewer before they post.
Why it matters: An automatic public reply compounds a read-scope mistake at internet speed. A review step catches the mismatch while it's still reversible.
- 08
Go/no-go rule
Required
Pins down: Public-reply mode goes live only after input is classified, read scope is enumerated, the canary probe comes back clean, and someone owns what 'public' means for this workflow.
Why it matters: Without a named owner and a passed test, 'public replies are fine because permissions are scoped' is a guess, not a decision.
Done means a named owner watched a canary probe fail to leak, not that the workflow ran without an error.
We've written before about the write side of GitHub agentic workflows from a different angle. The docs witness loop covers an agent that reads one repo and drafts into another. There, the risk was a fuzzy agent holding real write credentials, and the fix was a narrow handler that materializes the write instead of the agent doing it directly. An agent firewall in observe mode puts a similar external checkpoint in front of production actions generally, watching real traffic before it ever blocks anything. The public-output quarantine test is a narrower, more specific version of that same instinct, aimed at the exact moment a private-context agent is about to say something out loud in public.
Where to start
If an agent in your org can read anything sensitive and reply anywhere public, run the test before the next reply ships, not after the first incident. Classify the input. Write down the real read scope. Name the destination and the recipient. Probe it the way Noma did, on your own data, before anyone outside the team gets a chance to.
BaristaLabs helps teams map one agent workflow: its input trust levels, read scope, write destinations, and approval gate, before it's allowed to answer inside a public thread. For the broader set of boundaries an agent workflow needs before it touches real systems, see our notes on AI workflow controls.
Before public replies go live
Map a public-output quarantine test
BaristaLabs helps teams map one repo agent or support agent's input trust levels, read scope, write destinations, and approval gate before it's allowed to answer in public.
Bring one workflow that reads private context and writes somewhere public. We'll map the quarantine test before its next reply ships.
Practical AI Workflow Notes
Want more practical AI operations ideas?
Get short notes on applying AI inside real small-business workflows — from document handling and customer follow-up to internal reporting, compliance, and automation guardrails.
Turn this idea into a pilot
Which workflow should go first?
Use the readiness check to compare impact, effort, risk, owner, and next step before booking a call.
- 3-5 minutes
- Deterministic score
- No sensitive data
Share this post
