By A. Akotkar · 3 September 2026
The Claude Code GitHub Actions prompt injection disclosed this year has an uncomfortable shape: the attacker does not need your repository, your credentials, or your attention. They need to open an issue. Your workflow does the rest, because it fires on its own and reads what they wrote as instructions.
Two separate disclosures landed in 2026, by different researchers, against different weaknesses. Neither is the “hostile web page tricks your chatbot” story you have already read. I have not reproduced either exploit, and nothing below is a payload — it is what the published research and the vendors’ own fixes say, with the workflow patterns you can check yourself.
TL;DR: AI agents in CI interpolate untrusted GitHub fields into their prompts and run with credentials. One disclosure got API keys printed into public comments across three vendors’ agents. The other chained an issue into write access on Anthropic’s own action repository. The fixes are architectural, and one vendor declined to make them.
- How can a pull request title run commands in your CI?
- Why is this different from the prompt injection you have already read about?
- How did one GitHub issue reach the supply chain?
- What did the vendors actually do about it?
- Is your workflow one of the exposed ones?
- What actually fixes this?
- What should you check before your next workflow run?
How can a pull request title run commands in your CI?
Because the title is a string, and the workflow pastes it into a prompt.
The technical root cause is the improper neutralisation of untrusted input used for prompting. A workflow triggers on issues.opened or pull_request.opened, then passes fields like github.event.issue.title or github.event.issue.body straight into the agent’s instructions. The model has no way to tell the maintainer’s words from a stranger’s. Both arrive as text in the same prompt.
In April 2026, security engineer Aonan Guan, with Zhengyu Liu and Gavin Zhong of Johns Hopkins, published an attack class they called Comment and Control. They demonstrated it against three agents from three vendors:
- Claude Code Security Review — a crafted PR title led the agent to run commands and expose
credentials through the Actions logs.
- Gemini CLI Action — a poisoned issue comment bypassed the guardrails and the agent wrote its
own GEMINI_API_KEY into a public issue comment, readable by anyone.
- GitHub Copilot Agent — the payload was hidden in an HTML comment, invisible in the rendered
page, and got past environment filtering and the network firewall.
No attacker-controlled server was needed at any point. The credentials came back out through the same GitHub surfaces the attacker was already writing to.
Why is this different from the prompt injection you have already read about?
The trigger. Classic indirect injection is reactive: it needs a victim to point their agent at the poisoned document. This is proactive, and that changes who can attack you.
GitHub Actions workflows fire automatically on pull_request, issues and issue_comment events. Nobody has to ask the agent to read anything. A stranger opening an issue on a public repository is the whole delivery mechanism, and on a public repo that is not a privilege — it is the point of having one.
This is also where Claude Code’s auto mode does not help you. Its classifier reviews an interactive session, and it explicitly blocks launching unattended agent loops with no human approval. A CI workflow is that loop, running somewhere else, with a token.
How did one GitHub issue reach the supply chain?
The second disclosure is the more serious one, and it is a different bug.
RyotaK of GMO Flatt Security found that claude-code-action‘s checkWritePermissions function unconditionally allowed any actor whose identity ended in [bot], on the assumption that a bot must be legitimate. It is not a safe assumption: anyone can register a GitHub App, and a GitHub App can open issues on a public repository without being installed there.
From that foothold the chain ran four steps. The attacker’s App files an issue carrying the injection. The agent is led to read /proc/self/environ, which exposes ACTIONS_ID_TOKEN_REQUEST_TOKEN and ACTIONS_ID_TOKEN_REQUEST_URL. Those request an OIDC token, which is exchanged at Anthropic’s own endpoint for a Claude GitHub App installation token. That token carries write access — to anthropics/claude-code-action itself, and so to everyone downstream of it.
It was rated CVSS 7.8 and earned a $4,800 bounty. Anthropic reported it fixed within four days: reported 12 January 2026, patched 16 January, published 1 June. A similar flaw was exploited in Cline’s GitHub Actions in February.
What did the vendors actually do about it?
Anthropic shipped real changes in v1.0.94: a checkHumanActor check so bots cannot trigger the agent, the workflow run summary disabled by default, environment variables scrubbed from child processes, and issues ignored if they are edited after the workflow is triggered — closing the trick of editing a benign issue into a malicious one mid-run.
The response to Comment and Control was thinner, and the bounties are the tell. Anthropic rated it critical and paid $100, mitigating in part by disabling the ps command rather than moving to least privilege. Google paid $1,337 and added guardrail prompts to its system prompt, leaving the threat model unchanged. GitHub paid $500, classified it as a known architectural limitation, declined to address the root cause, and noted that the work had sparked great internal discussions.
Adding guardrail text to a system prompt as a defence against untrusted text entering the same prompt is not a fix. It is the same surface, asked more firmly.
GitHub did move at the platform level three months later, changing actions/checkout to safer pull_request_target defaults in June.
Is your workflow one of the exposed ones?
Open your workflow files and look for the combination, not any single line. The dangerous pattern is untrusted text reaching a prompt in a job that holds secrets:
- A trigger of
issues,issue_comment, orpull_request_target— the last one runs with your
secrets available, unlike pull_request
- A GitHub event field interpolated into a prompt:
${{ github.event.issue.title }},
.issue.body, .comment.body, .pull_request.title
permissions:grantingcontents: write,issues: writeorpull-requests: writein the same
job as the agent
allowed_non_write_users: "*", which hands the trigger to anyone at all- A third-party action pinned to a floating tag such as
@v1rather than a full commit SHA
One of these is a question. Three of them together is the reported attack.
What actually fixes this?
Keeping untrusted text out of the prompt, and keeping credentials out of the thing that reads it.
Two different bugs hide in that one line, and only one of them has a clean fix. Interpolating ${{ github.event.issue.title }} directly into a run: step is ordinary script injection: the expression is expanded before the shell sees it, so a title containing shell syntax simply executes. Moving it to an env: variable fixes that, and you should do it.
It does not fix prompt injection. The model still reads the text, and still cannot tell your instructions from a stranger’s. So the controls that matter are the ones that assume the agent will be fooled and limit what that costs. Split the agent’s reasoning from anything holding credentials, so the part reading a stranger’s words has nothing worth stealing. Prefer pull_request over pull_request_target where you can, and where you cannot, gate the secret-using job behind an approval — GitHub’s environment protection rules do this. Pin third-party actions to a full commit SHA. Apply least-privilege permissions: per job rather than repository-wide.

The honest caveat is that none of this makes an agent able to tell instructions from data. That problem is unsolved; OpenAI said publicly in December 2025 that prompt injection in AI browsers may never be fully solved. What the controls above do is make it not matter as much when the agent is fooled, which is a different and more achievable goal.
What should you check before your next workflow run?
- Update
claude-code-actionto v1.0.94 or later, and Claude Code itself to v1.0.93 or later - Grep your workflows for
github.event.*.titleand.bodyreaching a prompt, and move them to
environment variables
- Remove
allowed_non_write_users: "*"if it is there at all - Check whether any agent job holds
writepermissions it does not use - Replace floating action tags with commit SHAs, so a compromised action repository cannot reach
you through a moved tag
- Assume a public repository’s issues are attacker input, because they are, and treat a workflow
that reads them as running attacker-supplied text
Related reading: Claude Code’s Restricted Mode covers the tool-level blast radius on your own machine, and auto mode covers what the classifier does and does not see in an interactive session.



Leave a comment