Opening an issue is the most harmless thing you can do on GitHub. You do not need to be a contributor. You do not need to fork anything or get a review. You type some text and press a button.
In a repository that runs an AI agent on its issues, that is now enough to take the agent over.
We went looking for how often that happens. We collected 800 public repositories whose GitHub Actions run an AI coding agent, and read every workflow our scanner rated as serious. In 16 of them, a stranger who opens an issue or a pull request can make the agent do what they say. In six of those, the agent can also reach the repository's secrets.
Three settings that are each reasonable
None of these repositories did anything that looks careless. Each of them combined three settings, and each setting on its own has a good reason behind it.
Anyone can start it. The workflow runs on issues or issue_comment, or on a pull request from a fork. That is the whole point of a triage bot: it answers the people who show up.
The safety gate is off. Anthropic's claude-code-action refuses, by default, to act for users who do not have write access to the repository. One input turns that off:
allowed_non_write_users: "*"
The action's own documentation describes it plainly: a list of users to allow without write permissions, or * to allow all users. Teams set it because a triage bot that ignores outside contributors is not much of a triage bot.
The agent has real tools. A write token, and tools like Bash, git or Write, so it can label, fix and push.
Put the three together and it looks like this:
on:
issues:
types: [opened]
permissions:
contents: write
issues: write
jobs:
triage:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: anthropics/claude-code-action@v1
with:
allowed_non_write_users: "*"
claude_args: "--allowedTools Bash,Edit,Write"
prompt: "Read the new issue, label it, and fix it if you can."
That is an illustration, not a copy of any repository. Not all 16 use this exact action, but every one of them combines the same three things. An attacker opens an issue that says, in the middle of an ordinary bug report, to ignore the task and do something else. The agent reads the issue because reading issues is its job. Depending on what it was given, the attacker can post as the bot, push code to the repository, or run commands on the runner with the secrets that live there.
Why it does not look dangerous
To an agent, an attacker's instruction and a real one are the same thing: text in its context that tells it what to do. There is no marker that separates the two, and a better prompt does not create one. The agent is doing exactly what it was built to do, for whoever wrote the words it read.
The workflow does not look dangerous either. It looks like a helpful bot, because it is one. Nothing in the diff that added it would catch a reviewer's eye. The gate is one line of YAML, and it is often not even written by the team: among the medium findings, one duplicate-issue detector appears in 17 repositories, with the gate-off line carried along in every copy.
Where the risk lives
In this set, the large projects were fine. Every finding sits below 10,000 stars:
| stars | repositories | verified findings |
|---|---|---|
| above 50,000 | 68 | 0 |
| 10,000 to 50,000 | 86 | 0 |
| 1,000 to 10,000 | 93 | 4 |
| below 1,000 | 553 | 12 |
That fits what you would expect. Big projects have someone whose job is to read a workflow like the one above and ask what an outsider could do with it. The risk is in the middle: real projects with real users, running an agent on their issues, and nobody on the team whose job is to think like an attacker.
A note on the numbers. The 800 are not a random sample. We deliberately went looking for repositories that run agents in CI, and a large share came from searching for the exact settings described above. So 16 out of 800 is not a rate for GitHub as a whole. It is how many of these setups turned out to be exploitable once we read them.
The ones halfway there
Below the 16 there is a longer list of repositories rated medium: 245 of them. In 114, the gate is already off. The agent answers anyone. What keeps those repositories out of the first group is only which tools the agent was given. Today it can label an issue or post a comment. The day someone gives it Bash so it can also try a fix, it joins the 16.
That is the part worth taking seriously. The dangerous configuration is not a rare mistake. It is a reasonable setup, one convenient change away from a serious one.
What to check in your own repository
If you run an agent from GitHub Actions, five questions settle whether an outsider can drive it:
- Is the gate on? Search your workflows for
allowed_non_write_users. If it is*, anyone can trigger the agent. - What does the agent read? If untrusted code from a fork is checked out into the workspace, or the issue text goes straight into the prompt, the attacker's words reach the agent.
- Can the agent's shell see your secrets? A token or cloud credential in the environment is what turns a hijacked bot into a stolen key.
- Is the token scoped? A narrow, short-lived token limits the damage. A static personal access token does not.
- Are the tools scoped?
Bash(gh issue label:*)lets the agent do one thing. BareBashlets it do anything.
You can check all five in one pass. This reads a public repository with no install and no account:
npx node9-ai scan-repo <owner>/<repo>
It reads the committed workflows and agent configuration, runs nothing, and tells you which of these settings line up.
No affected repository is named in this post. Each of the 16 was confirmed by reading the workflow by hand, not only by the scanner. If one of them is yours, the fix is usually the first question on the list: turn the gate back on, or scope what the agent can do before you let everyone talk to it.