Its task was one issue, its token could read the org
Noma Security's GitLost showed an unauthenticated stranger opening a public GitHub issue and getting GitHub's AI agent to post a private repository's contents back as a public comment. The prompt injection made the headline. The agent's token, scoped to the whole organization instead of the one issue it was triaging, set how far the leak could reach. That gap between what a task needs and what the environment holds is the part worth taking home, and the part you can design differently when you host the agent yourself.
An unauthenticated stranger opened an issue on a public GitHub repo, wrote one paragraph, and waited. GitHub's AI agent read the issue, walked into the organization's private repositories, and posted a private README back as a public comment. The paragraph was the trigger. The agent's token, scoped to the whole organization instead of the one issue in front of it, is why the leak reached that far.
Noma Security's research team stood up an organization on GitHub the
way many teams now do: a handful of public repositories, several
private ones, and GitHub Agentic Workflows wired in to handle the
busywork. GitHub Agentic Workflows are plain-Markdown instructions that
GitHub Actions hands to an AI agent, backed by Claude or Copilot, so
the agent can triage issues, answer questions, and open pull requests
on the team's behalf. Then the researchers played the attacker. They
opened an ordinary-looking issue in one of the public repositories,
tucked a few extra sentences into the body, and let the workflow run.
The agent read the issue, fetched the contents of a README.md from a
private repository, and pasted it into a public comment where anyone
could read it.
The attacker used no password, no stolen key, and no exploit code, and there is no CVE. Noma calls the technique GitLost, reported it to GitHub, and published with the company's knowledge. The whole payload was English prose sitting in a field the agent was built to read.
The issue that answered with a private repo
The mechanics are short, which is what makes them worth drawing. A workflow fires on an event, such as an issue being opened or assigned. The agent reads the issue's title and body as its task. Buried in that body were instructions telling the agent to fetch a private repository's README and post it as a comment. GitHub had guardrails in front of this: sandboxing, tokens that default to read-only, input cleaning, and a threat-detection pass over the text. Noma tried variations until one slipped through. Prefixing the malicious request with the word "Additionally" was enough to get past the filter, because the model read it as a follow-on task rather than a request to refuse. A one-word change carried the injection across the line.
Rewording beats the filter
A filter that reads the issue body and decides whether it contains an attack is guessing at intent from phrasing, and phrasing has an endless supply of variations. Noma did not break the model or find a memory bug. They reworded the same request until the classifier scored it below its own threshold, and "Additionally" was the wording that landed.
This is the structural property of tool-using agents we wrote up last week: an agent reads its instructions and the data it fetches as one flat stream of tokens, and it infers which part is a command from tone and position, the way a person skims. An issue body is data. Injection is the move that shapes untrusted data like a command and bets the model will act on it. Detection helps and is worth running, and it will miss: a classifier has a threshold, and an attacker with unlimited attempts probes until a phrasing scores under it.
The gap that sized the leak
One part of GitLost survives whatever filter GitHub ships next. The workflow's task was to triage one issue in one public repository. The token GitHub Actions placed in that workflow's environment had read access to every public and private repository in the organization, because teams grant that breadth so the agent can pull cross-repo context. The attacker chose the target; the token's scope set the limit of the damage. Reword the attack a hundred ways and that limit stays the same: whatever the token can see.
Noma's own recommendation points at the same seam. Their advice to defenders is to scope the token to the one repository the workflow triages rather than the whole organization. That advice concedes that the injection will sometimes land, and that when it does, the blast radius should be the size of the task rather than the size of the account.
The exfil path was the agent's day job
The private README left the organization through a public comment, which is a thing the agent is supposed to be able to do. Commenting on issues is its function. Nothing on the wire looked like theft: no odd endpoint, no encoded blob leaving through a side door. A network monitor watching for malicious traffic would have seen the agent post a comment, which it does all day. When the exfiltration channel is a sanctioned capability, the defense that pays is constraining what the agent can reach in the first place.
Where you get to change the architecture
Two things about GitLost are outside your reach. The bug is GitHub's to fix, and GitHub is working on it. And the agent ran on GitHub's servers, inside GitHub Actions, where no product you install sits in the path. Bromure Agentic Coding runs on a developer's Mac. It is not in front of GitHub's server-side workflow and does not claim to be. If your only exposure to this class of problem is a hosted agent someone else operates, the lever you have is the one Noma named: scope the token down.
The transferable lesson is for the growing number of teams running coding agents on machines they control, where the architecture is yours to set. Two principles carry across from GitLost, and neither depends on catching the injection. Keep the environment thin, so a hijacked agent inherits little worth taking. Scope the credential to the task, so the reach of a compromise is the size of the job rather than the size of the account. Bromure Agentic Coding is one arrangement of those principles.
Bromure Agentic Coding runs your coding agent, Claude
Code, Codex, or Grok, inside a disposable per-profile Linux VM: its own
kernel, its own filesystem, its own network stack, one hypervisor away
from your Mac on Apple's Virtualization framework. A profile is a
coherent scope of work, one client or one service. The real credentials
never enter that VM. Bromure holds them on the host behind a broker and
ships the guest fake values that look real to the tools reading them; a
proxy on your Mac swaps the stub for the real secret at the wire as the
request leaves, and
the sandbox that held the key
walks through the mechanism. An agent that gets talked into running
cat on a credential file finds a placeholder, because the value it
wanted was never on its side of the boundary.
The token the agent does get to spend is scoped and expiring, so a leak is a narrow, time-boxed use rather than a permanent grant. The whole work area is a VM that goes away when you close the session. Run the GitLost shape through that arrangement and the injection can still land, because isolation does not un-trick a model. An agent convinced to exfiltrate reaches for a credential and finds a stub, spends a token that only covers the one profile it was working in, and sits in a box with no path to the rest of your machine. The reach of the compromise is the size of the task.
Keep the environment thin
A hijacked agent can only hand over what its environment holds. Stubs in the guest and real secrets on the host mean the injection that lands finds placeholders where it expected keys.
Scope the credential to the task
Noma's advice for GitHub workflows is the same principle: a token that covers one repo caps the damage at one repo. Scope and expiry turn a leak into a narrow, time-boxed event.
Make the box disposable
When the work area is a VM that evaporates on close, persistence has nowhere durable to sit and the blast radius ends with the session.
Assume it will be injected
Detection is worth running and will miss. Design so the outcome of a miss is survivable, rather than betting on catching every phrasing.
What this leaves standing
Scoping does not make an agent safe to point at a real secret. If you place a live credential inside the VM and the agent gets talked into reading it, no hypervisor un-reads it; the change is in what the agent can reach, not in whether a tricked model stays tricked. The exfil problem Noma highlighted has a piece that isolation alone does not close either: an agent that can post a comment, open a PR, or send a message can move data out through that sanctioned channel, and scoping decides how much data is within reach to move, not whether the channel exists. And GitLost itself belongs to GitHub. Update when they patch, and scope your workflow tokens down in the meantime, because that is the lever the platform hands you.
Wherever you run an agent, researchers will keep reporting the injections, and the scope of the credential in the agent's environment will keep determining whether each one ends as a logged near-miss or a private repository on a public page. Noma's fix and Bromure's architecture point the same direction: give the agent the reach the task needs and nothing wider.
Bromure Agentic Coding runs Claude Code, Codex, and Grok in disposable Linux VMs on Apple Silicon, with the real credentials held on the host behind a broker and swapped in at the wire, prompt-injection detection on the agent's inputs, and every call written to a trace the agent cannot edit. It is free, open-source, and shipped today at bromure.io. With thanks to Noma Security, whose GitLost write-up prompted this one.