The Vulnerability Was in the Workflow You Copied

The most useful security result of the last month is not a model failure, and that is exactly why it is worth reading carefully. At Black Hat USA 2026, Elad Meged of Novee Security showed that the three most widely deployed coding agents, Claude Code, Gemini CLI and OpenAI Codex, could each be turned against the continuous integration systems they run inside. The attack input was a single GitHub issue, opened by an account with no repository privileges at all. The result in each case was code execution on the runner and access to the secrets that runner holds. All three vendors have shipped mitigations. The part that should keep you reading is where the bugs lived: not in the judgment of the model, but in the harness wrapped around it, and specifically in the default workflow configurations the vendors themselves publish as the recommended way to get started.

The three failures are worth stating separately, because they are three different mistakes with one shape. Against Claude Code, an attacker could hide instructions in an issue body and induce the agent to run a prepared git push that abused the receive pack option to execute code on the GitHub Actions runner, walking past a bash validator whose quote stripping could be defeated, and reaching both the API key and the GitHub token. That one took three rounds of patch and bypass before it closed. Against Gemini CLI, the tool restriction annotation turned out to be decorative: the full shell tool was registered and the command specific restriction was not enforced at runtime, and secret stripping failed where a process in a shared PID namespace could read the environment of its parent through the proc filesystem. Google rated its own advisory for that finding CVSS 10.0. Against Codex, a two pass workflow shared one writable checkout, which let the first pass write a poisoned AGENTS.md that the second pass then loaded as authoritative instruction. A separate disclosure found the same family of problem inside Google ADK, where an ungated triage agent could be induced to summon a maintainer gated one, and a git flag walked straight past a shell denylist to reach service account keys.

What makes this different from an ordinary vulnerability is the delivery mechanism. A flaw in a package gets a CVE, an advisory and a version bump, and your scanners tell you about it. A flaw in a reference configuration gets none of those things, because the artefact is a YAML file you copied into your own repository at some point last year. Nothing watches it. Dependabot does not raise a pull request against a workflow you pasted from a quickstart, no lockfile records where it came from, and there is no version to compare against. The moment you copied it, you became the maintainer of that code, and in most companies nobody has looked at it since the day the agent first ran green. We have made the argument before that MCP servers are vendors and that agent frameworks are ordinary software. Vendor sample configuration belongs in the same bucket, and it is the least reviewed code in most repositories.

The underlying trust boundary is one that predates AI entirely, which is a large part of why it was crossed. Continuous integration has always had a rule about untrusted input: content that arrives from outside the trust perimeter, an issue, a fork pull request, a comment, must not reach a job that holds privileged credentials. Teams that got burned by pull_request_target years ago know this in their bones. What the agent adds is a component in the middle of that pipeline whose entire design purpose is to read text and act on it, which converts a data flow problem into an instruction flow problem. The issue body is no longer just a string that a script might mishandle. It is a set of instructions arriving at something built to follow instructions, running on a machine holding your tokens. Everything else in these three findings is detail.

The second general lesson is that the defensive pattern all three vendors reached for does not hold. A bash validator that inspects a command string, an annotation that names permitted commands, a denylist of dangerous binaries, these all assume you can predict the shape of a hostile command line. You cannot, because the thing generating the command line is a general purpose program composing novel text, and because command line tools are quietly enormous. Git alone has enough flags to constitute an execution environment, which is what both the receive pack bypass and the ADK service account key exposure turned on. The wider research from the same period points the same direction: GhostJacking demonstrated roughly 90 percent success against Claude Code using firewall logs as the injection vector, and a benchmark of 2,826 malicious skill files reported 95.5 percent exploitability against Gemini CLI and 71.6 percent against Qwen Code. Filtering the string is not the control. Removing the privilege is the control.

The remediation list is short and does not require a project. Inventory every workflow in every repository that hands a coding agent a runner, including the ones that came from a vendor quickstart and the ones an enthusiastic engineer added during a hackathon. For each, check what triggers it, and treat any trigger reachable by someone outside your organisation as hostile input by definition. Split the pipeline so that the job which reads untrusted content and the job which holds credentials are different jobs, passing artefacts between them rather than sharing one writable checkout, which is precisely the gap the Codex finding exploited. Scope the GITHUB_TOKEN to read where it can be read only, replace any long lived cloud key on an agent runner with short lived OIDC federation into a narrowly scoped role, and put a required human approval environment in front of anything that pushes, publishes or deploys. Then treat AGENTS.md, CLAUDE.md, cursor rules files and any in repository MCP server configuration as executable content subject to code review, because that is what they are. If you ran one of the affected default workflows on a public repository, rotate the secrets it could see rather than reasoning about whether anyone noticed.

Mapping this into the compliance work you already run is mostly a matter of admitting where CI sits. Under SOC 2 and ISO 27001, a build system that holds production credentials and can push code is production, so its configuration falls under change management and its credentials under access control, and an unreviewed workflow file is a finding waiting for an auditor who thinks to ask. The vendor reference configuration itself belongs in your third party register alongside the model providers and the MCP servers, with a note on when you last compared your copy against the current upstream. Under ISO 42001, each agent surface earns an inventory entry that records not just the model but the privilege the harness grants it, which is the field almost every AI inventory we have seen leaves blank. Vanta, Drata, Secureframe, Sprinto, Thoropass and Hyperproof will all carry these as monitored controls with a review cadence, but none of them will discover an unreviewed workflow file for you. That part is a person with repository access and an afternoon.

None of this is a case against coding agents. Cursor, GitHub Copilot, Claude Code and Codex are doing real work in real teams, and the fact that three vendors patched within a disclosure cycle is the system functioning. The case is against a specific and very common assumption, which is that a configuration published by a vendor is a secure default. It is not, and it was never claimed to be. Sample configurations are optimised for the shortest path to a working demonstration, which means broad permissions, a single job, and a token that can do everything, because that is the version that does not generate support tickets on day one. The teams that come out of this well will not be the ones that stopped running agents in CI. They will be the ones who can name every workflow that gives an agent a runner, say what triggers it and what it can reach, and show that a human looked at the file rather than at the green tick beside it.