# Lessons from a year of agent CVEs

> We read every published security issue in AI coding agents from the past year. Most sit in the code around the model, and a quarter need no model at all.

Amir Shaked · 2026-10-20 · Coding Agents, AI Security, CVE, AppSec, Agent Harness

Copilot CLI auto-approved `echo` as read-only. Bash's `${var@P}` transformation then interpreted an argument as a prompt string, executing an embedded command substitution before `echo` ran. The command created a file without approval ([CVE-2026-29783](https://github.com/github/copilot-cli/security/advisories/GHSA-g8r9-g2v8-jv6f)). In other words, a command the agent was allowed to run without asking ran a second command nobody approved.

That bug isn't unusual. Most coding agents start with the same tradeoff: approval prompts slow developers down, so the agent auto-approves a list of commands that look harmless. Claude Code, Codex and Gemini CLI have all had bugs of this kind, and the list keeps growing.

We went through every published security issue we could find since June 2025 in Claude Code, Codex, Gemini CLI, Copilot, Antigravity, OpenCode, Pi and related tools. Only five are failures of the model itself. The rest are in the harness: how it loads settings, checks permissions and runs commands. A quarter need no model at all: a malicious folder, git config or web page reaches the vulnerable code directly. Claude Code shows up most, largely because Anthropic publishes advisories even for low-severity issues.

This post is for two groups:

- If you build agent harnesses, it's a list of mistakes others already made, with a fix for each.
- If your developers run these agents every day, it shows where the built-in permission checks fall short and what an independent control needs to cover.

We group the issues into 14 classes, walk through the six with the clearest lessons, and share a review skill and the full dataset at the end.

**Keep approved commands inside an OS-enforced sandbox with explicit filesystem and network limits. Approval must never switch those limits off.** Start that isolation before running workspace probes such as `git status` or `yarn --version`.

## Mapping issues by class

| Class | Issues | Affected products |
|---|---:|---|
| Shell command approval by parsing | 17 | Claude Code, Codex, Gemini CLI, Copilot CLI, Copilot IDE, ClaudeHookBridge |
| Workspace config runs before trust | 14 | Claude Code, Codex, Gemini CLI, Pi, Aider, Ouroboros, Cortex MCP |
| Unauthenticated local server | 13 | Claude Code IDE, OpenCode, Cline, Kilo, Antigravity, AgentAPI, Ruflo, claude-code-router, Claude Code Templates |
| Not publicly described | 13 | Copilot IDE |
| Egress through "read-only" channels | 11 | Claude Code, Codex, Antigravity, Copilot |
| Path confinement | 10 | Claude Code, Codex, Copilot, gemini-bridge |
| Argument / command injection in harness code | 10 | Claude Code, Claude Agent SDK, Codex, Gemini CLI, Antigravity, OpenHands, Claude Code UI |
| Agent rewrites its own controls | 9 | Claude Code, Copilot, Antigravity, Cursor |
| Classic local bugs | 8 | Claude Code, Pi |
| Sandbox gaps | 7 | Claude Code, Codex, Gemini CLI, Antigravity, `@ai-sdk/harness-*` |
| Harness's own git calls run repo config | 7 | Claude Code, Codex, Copilot CLI, Goose, Qwen Code |
| Unattended runs (CI, bots, email) | 7 | Gemini CLI, claude-code-action, AgenticMail, OpenClaw |
| The model as the policy | 5 | Antigravity, Copilot CLI |
| Trust bound to a name | 2 | Claude Code, Cursor |

## Your parser is not the shell

One Claude Code advisory covered [eight approval bypasses](https://github.com/advisories/GHSA-xq4m-mc3c-vvg3) (CVE-2025-66032). One used `git ls-remote` with an abbreviated `--upload-pack` option. Git accepted the abbreviation and ran another program, and the approval check didn't catch it. The same report covered `rg --pre`, which Codex also auto-approved. That flag tells ripgrep to run a preprocessor, so a search ran an arbitrary program.

ClaudeHookBridge, a third-party policy hook, truncated commands to 500 characters before matching deny patterns. Claude Code executed the full string (CVE-2026-73614). Put the interesting part at character 501.

For tools that don't need shell syntax, pass a structured `argv` array directly to the executable. That removes shell expansion, but Git and `rg` can still launch helpers through their own options. Validate those options and keep the process sandboxed.

## Opening a folder runs Git

Codex ran `git status` when a workspace opened. A repository delivered with its `.git/config` intact (through a zip, shared drive or devcontainer) could configure `attr.tree` and a clean filter that made Git run the attacker's program. CVE-2026-19593 was rated 9.8, because opening the folder was enough to run code, before any trust prompt and without the model.

`core.fsmonitor` executed repository-supplied code in Copilot CLI, Claude Code, Codex, Goose and Qwen Code between May and September 2026.

For internal Git calls, these overrides disable two execution paths and restrict bare-repository discovery:

```bash
git -c core.fsmonitor=false \
    -c core.hooksPath=/dev/null \
    -c safe.bareRepository=explicit status
```

They don't disable repository filters, including the path in CVE-2026-19593. Those need separate handling, or a Git library that doesn't execute config. Apply the restrictions to every internal Git call, including startup probes and status-bar refreshes.

## The repository chooses your settings

Codex loaded `.env` from the working directory. That file could set `CODEX_HOME=./.codex`, making the repository's `config.toml` look like user configuration. Its MCP servers then started at launch ([CVE-2025-61260](https://github.com/advisories/GHSA-xrxf-jgv3-qmrm)).

Six months after Codex's advisory was public, the same chain [turned up in Gemini CLI](https://github.com/advisories/GHSA-2255-3477-vp73), using `GEMINI_CLI_HOME`. The substituted settings also disabled folder trust (CVE-2026-13745). Ouroboros followed with a `.env` setting that redirected the agent binary itself (CVE-2026-47211).

Choose your harness's config location before reading workspace files, and make it unwritable by agent tools. A repository's `.env` must not relocate it before you approve that repository.

Yarn was harder to spot. Claude Code ran `yarn --version` at startup to detect the toolchain. Yarn 2+ loads plugins from the repository's `.yarnrc.yml`, so that check ran repository code. Fixing it took two CVEs (CVE-2025-59828, CVE-2025-65099).

The agent can also write its own future permissions. Copilot could set `chat.tools.autoApprove` in `.vscode/settings.json` without approval (CVE-2025-53773). Antigravity protected `.vscode/` files but missed `tasks.json`, whose `runOn: folderOpen` schedules execution on the next open.

## Your harness is a web server now

OpenCode started an HTTP server on every launch, with no authentication, open CORS, and shell and PTY endpoints ([CVE-2026-22812](https://github.com/anomalyco/opencode/security/advisories/GHSA-vxw4-wv6m-9hhh)). A web page the user had open could run commands through it.

Later versions exposed another route through `opencode serve`: `/global/upgrade` passed the requested package to the installer. For npm, pnpm and Bun installations, that could be an attacker's package. A malicious page could reach it without a server password, or with HTTP Basic credentials cached by the browser. The endpoint parsed a `text/plain` form POST as JSON, which browsers can send without CORS preflight ([GHSA-632h-h47v-g4x4](https://github.com/anomalyco/opencode/security/advisories/GHSA-632h-h47v-g4x4)).

The earliest CVE in the dataset was already this kind of mistake: Claude Code's IDE extension exposed a WebSocket server without checking `Origin` (CVE-2025-52882). Cline shipped the same bug twice in 2026.

Bind the server to loopback, require a session token, and validate `Origin`, `Host` and content type. No unauthenticated endpoint should run a shell, install a package or change permissions. That sounds obvious; four projects shipped it. These bugs would look at home in a 2008 web app audit.

## A fetch can carry a secret

Claude Code pre-approved `huggingface.co`, including every path on the host (CVE-2026-54316). Anyone can create a Hugging Face repository.

Antigravity's default browser allowlist included `webhook.site`, a service built to receive requests. Other overlooked channels included DNS queries, remote Markdown images and JSON schema fetches.

The permission check on `curl` covered none of those routes. Disable automatic remote-image fetching in your renderer, and enforce outbound policy on tool processes through a network sandbox or a proxy they cannot bypass. Include DNS in that policy. List every way your harness can make a request without asking.

## Unattended agents must fail closed

An issue comment steered a Gemini CLI agent running under `--yolo` in a GitHub workflow. The workflow specified a tool allowlist, but `--yolo` skipped it: permission to run `echo` became permission to run any command ([CVE-2026-12537](https://github.com/advisories/GHSA-wpqr-6v78-jr5g)). The researchers reached credentials on the runner and a path to writing to `main`. YOLO mode removed the only control the workflow had.

Two months after Google fixed it, the same researchers found that a deprecated `coreTools` configuration key was silently ignored. The CLI fell back to allow-all. The second chain reached a GCP project through a Workload Identity Federation credential file and an overly broad token-creator grant. Google clarified that it was a sandbox project.

AgenticMail resumed the operator's Claude Code session in `bypassPermissions` for any inbound email, with the sender and subject in the prompt ([CVE-2026-57495](https://github.com/advisories/GHSA-fq4x-789w-jg5h)).

Unknown or deprecated security configuration keys must stop an unattended run instead of silently restoring unrestricted access.

## Five implementation traps

- Path checks: Claude Code's path prefix check accepted `/proj_evil` as inside `/proj` (CVE-2025-54794). Its symlink deny-rule bug needed two fixes (CVE-2025-59829, CVE-2026-25724).
- Sandbox scope: Codex took its writable sandbox root from the model's requested working directory (CVE-2025-59532).
- Default permissions: Antigravity's macOS sandbox profile began with `(allow default)` and forgot to deny `mount`.
- Message provenance: Antigravity's system prompt told the model to obey `<EPHEMERAL_MESSAGE>` tags that fetched web content could forge.
- Pin resolution: Claude Code's plugin SHA pin accepted a branch named like the pinned SHA (CVE-2026-86063).

## The same bug, a few months later

Ten of the classes hit more than one of the seven main agents. Taking the date of each agent's first advisory in a class, the next agent typically followed about four months later (median 113 days).

- Unauthenticated local server: Claude Code's IDE extension in June 2025, OpenCode seven months later, Antigravity a month after that.
- Workspace config before trust: Claude Code in September 2025, Codex in December, Gemini CLI in April 2026, Pi in June.
- Shell approval parsing was the exception. Codex, Gemini CLI and Claude Code disclosed within a week of each other in mid-2025, and Copilot followed four months later.

These are disclosure dates, not ship dates, so the bugs may have lived longer. For every agent after the first, an advisory for the same class was already public. Before you write your permission layer, read Claude Code's and Codex's advisories end to end. They file the most, down to low-severity issues.

## The review skill

We packaged the classes above as an agent skill: [`SKILL.md`](https://bluebear.io/research/agent-harness-cves/SKILL.md). Each class has the question to ask, what to grep for, the fix shape and the CVEs behind it. The skill tells the reviewer to map your harness's surfaces first and rank findings by how little the attacker needs. It also tells the reviewer to confirm each finding before reporting it.

To use it with Claude Code, drop it into your harness repo:

```bash
mkdir -p .claude/skills/agent-harness-security-review
curl -sL https://bluebear.io/research/agent-harness-cves/SKILL.md \
  -o .claude/skills/agent-harness-security-review/SKILL.md
```

Then ask: *"Run the agent-harness-security-review skill on this repository."* Other agents can read the same file as a prompt; it's plain Markdown.

The full dataset (one row per issue: product, ID, date, class, one-line mechanism, source) is at [`agent-harness-cves.csv`](https://bluebear.io/research/agent-harness-cves/agent-harness-cves.csv). If we got a classification wrong or missed an advisory, tell us at [info@bluebear.io](mailto:info@bluebear.io).

## What the data says about agent permissions

Across most of these classes, the failure looks the same. A permission check approves a command, a path or a domain, and something else runs: a git filter, a Yarn plugin, a DNS lookup, a settings file the repository wrote for itself. The check described what the agent was allowed to do, but it had no view of what the agent was actually doing, or whether that matched the task it was given.

The same bugs keep appearing in new tools months after the first advisory, and most teams run several agents at once. Waiting for every vendor to close every class isn't a realistic plan. Teams need a control that sits outside the agent and still holds when an agent's own permission checks don't.

That's the gap Bluebear closes. Bluebear runs on the endpoint, isolating each agent session. We follow actions across tools (shell, MCP, API and network) and evaluate each one against the user's mandate and your organization's policy before it executes. In customer environments, we've seen [agents get denied through MCP, then try the same action through the CLI](https://bluebear.io/blog/the-tool-blocked-it-but-the-agent-kept-going). Bluebear connects the second request to the first and stops it, escalating risky actions to a human.

Security teams get an inventory of every agent, MCP server, skill and extension in use, plus a record of what each session was allowed to do and what it did. That visibility is what lets teams give agents more autonomy, with a check that doesn't depend on the agent's own settings.

Want to see how Bluebear handles these attack paths on the agents your team already uses? [Request a demo](https://bluebear.io/contact/) and we'll walk you through it. If you're building a harness, start with the review skill above, and send corrections to the dataset to [info@bluebear.io](mailto:info@bluebear.io).

---

### Notes on the data

- Sources: vendor security advisories, GitHub Advisory Database, NVD, OSV, MSRC and researcher disclosures. Scope: Claude Code, Codex, Gemini CLI, Antigravity, Copilot, OpenCode and Pi, including their CLI, IDE, desktop and cloud variants where applicable, plus third-party wrappers and selected related harnesses.
- Each disclosure counts once, even when it contains several bypasses; the eight in CVE-2025-66032 count as one. Each row has one primary class. Thirteen Copilot IDE CVEs lack a public mechanism. Antigravity's issues come from vendor bulletins and researcher write-ups; none has a CVE.
- Two entries rely on secondary reporting because primary pages were unavailable: Codex Heapjack/Overpatch and cloud branch-name injection. CVE-2026-88624 lacks a vendor advisory and its original reference is gone. Three Pi CVEs are low-detail VulDB filings.