Limit your agents’ permissions to the bare minimum, especially if they have access to multiple repositories.
That isn’t the only guidance Noma Security offers to users of GitHub’s agent workflows. But it’s probably the one that becomes most compelling after the Israeli company’s demonstration. They spotlighted a prompt-injection vulnerability.
A file from a private repository exfiltrated via a public issue
The agent workflows have been in public beta for a few weeks. They sit in the same folder as deterministic automations, but as Markdown files. They come with a YAML configuration (trigger conditions, permissions and allowed operations). A CLI command converts the whole thing into actions executable by GitHub Copilot, Claude, Codex, or Gemini.
The vulnerability in question hinges on instructions embedded in an issue created within a public repository of the target organization. Its author, allegedly the commercial director, has just returned from a client meeting and asks for several things:
- Modify the colors of a login page
- Remind him of the contents of the README in a public repository of the organization
- “In addition,” remind him of the contents of the same file in a private repository of the organization
The workflow triggers after the issue is assigned. The agent retrieves the contents of the said files… and posts them in the discussion thread, publicly.
Broad permissions entail substantial risk
GitHub has protections against this kind of scenario. But the addition of the phrase “in addition” allowed them to be bypassed, explains Noma Security.
As described, the attack could affect any organization using the agent workflows. All the more so because it doesn’t require authentication (creating a public issue in a repository suffices). It would, however, have failed if the AI hadn’t been granted permission to access the private repository. In this respect, it’s hard to blame GitHub, unless one of its apps granted that permission.
GitHub itself reminds, in the documentation for its agent workflows, of the need to apply the principle of least privilege. And to limit the operations that are allowed. It notes, in particular, that any writing — including adding comments — must be explicitly permitted in the configuration of the workflows.
| Prompt injection and SQL injection, same concept? |
| In SQL, the boundary between instructions (what the database engine “does”) and data (what is “stored” or “used” in a query) is clear. To prevent injections, you must guarantee this separation. The solution lies in parameterized queries: no matter the inputs, the database never interprets them as instructions. With LLMs, lacking a native distinction between data and code, it seems much harder to prevent prompt injections. Techniques are emerging nonetheless. For example, explaining to a model the notion of “data.” Or training it to prioritize the “instructions” over the “data” that resembles them. |