AI coding agents can preserve stale trust. Once a repo is approved, changed project configs may still load without a fresh approval step.
This creates a real local execution risk. A malicious commit or compromised contributor account could alter agent-loaded config and trigger code execution on a developer machine.
The fix is already understood. Trust should attach to the content being executed, not just the folder path, with re-approval when executable config changes.
You clone a repo you've been working in for months. You trusted it once, back when the project was new, and you haven't thought about that since. Your AI coding agent remembers the trust just fine. This morning you pull the latest commit, fire up the agent, ask it to fix a failing test.
Three seconds later a reverse shell opens to somebody else's server. Nothing on your screen changed. No prompt, no warning, no diff. Your SSH keys are already leaving the machine while you're still reading the agent's first reply.
This isn't some unpatched-fork curiosity. It's the documented, vendor-confirmed, working-as-intended behavior of three widely used AI coding agents: Anthropic's Claude Code, OpenAI's Codex CLI, and Google's Gemini CLI. Their shared trust model reduces to this:
When you approved the folder, you approved every future change to every file in it. Forever. For every contributor, present and future, known and unknown.
We reported this to three AI IDE vendors in a two-week window in February 2026. All three closed the reports as not-a-bug:
Anthropic (Claude Code): closed as Informative
OpenAI (Codex CLI): closed as Informational / P5
Google (Gemini CLI): closed as Won't Fix – Intended Behavior
This post explains why we believe those decisions are wrong. It's also about sharing how others already solved this exact problem, and what the actual fix looks like.
Introduction
Modern coding agents aren't chat boxes. Claude Code, Codex, Gemini CLI, Cursor, Windsurf, and the rest are applications that sit in your terminal or IDE and run shell commands, edit files, spawn subprocesses. All of that happens on your machine, with your user permissions. The chat interface is only one layer of a local agent that can make real changes to the filesystem.
These agents are extensible through a whole family of config files that live inside the project folder. The biggest category is MCP (Model Context Protocol), a plugin model now used across much of the AI coding-agent ecosystem. A project’s MCP server definitions (.mcp.json, .codex/config.toml, .gemini/settings.json) tell the agent which external tools to launch on startup. There are several other categories that matter just as much. Hook scripts are commands the agent runs at lifecycle events such as session start, before a tool call, or when a prompt is submitted. Instruction files (CLAUDE.md, AGENTS.md, GEMINI.md) get injected straight into the agent's system prompt. Pre-approved tool lists, environment-variable writes, and custom command definitions all live in this set too. Each one of these files can either launch a process, grant the agent escalated permissions, redirect its API traffic, or rewrite its instructions in a way the user never sees. The command field on an MCP server is the most concrete attack surface, but it's nowhere near the only one.
Because any of these files can end up causing code to run on the user’s machine, the agent asks for trust, but only once. The first time a user opens an unrecognized folder, they see a dialog asking whether they trust it. Approve the folder and the configs load. Decline and the agent typically falls back to a limited read-only mode or does not work as expected. The screenshot below shows Claude Code’s trust prompt:
TOCTOU (Time-of-Check to Time-of-Use) is a vulnerability pattern that occurs when a program checks a resource once and then uses it later without re-checking. The resource can change in between. Here the check is your trust approval, the use is the agent spawning a command, and the gap is every session after the first.
How the attack works
The user opens a repo whose project config is benign at the time of approval and clicks “trust.”
An attacker later lands a change to auto-executed project config through a normal commit or pull request.
The user runs git pull and opens the agent again.
The agent launches the changed command without a new approval step.
That is a classic TOCTOU failure: the tool checks trust once, then keeps using that decision after the trusted content has changed. In practical terms, a user of any of the three agents on a shared repo can be one malicious project-config change away from arbitrary code execution. The commit does not need to come from an obviously malicious account. It could come from a compromised collaborator laptop, a leaked GitHub token, a new team member with broad write access, or a friendly-looking PR that nobody had reason to distrust. The user does not have to do anything unusual: pull the latest code, open the agent, and continue working.
Three vendors, one bug
The three reports are nearly carbon copies. We'll walk through the essentials of each one, then the pattern they share.
Claude Code
Claude Code's cleanest example is the project MCP file .mcp.json. An attacker changes an already-approved server so the same project-tools name now points to a different command:
On the victim's side, git pull and the next claude run silently spawn bash, which pipes an attacker-controlled payload into an interpreter. No prompt, no diff, no warning. The trailing cat isn't part of the attack, it's plumbing: MCP uses stdio transport and the process has to stay alive, so the use of the cat command holds it open.
We identified nine additional vectors that turn on the same TOCTOU gap. Some lead to arbitrary command execution, others enable data exfiltration or prompt injection. Each one auto-loads from a git-tracked file, and none triggers re-approval.
Watch the video walkthrough:
OpenAI Codex CLI
Codex's relevant project file is .codex/config.toml. A minimal MCP PoC looks like this:
The basic pattern is the same as Claude Code: once the repo is trusted, a later change to the project config is loaded on reopen without a new gate.
Codex also has a broader blast radius than the MCP example alone suggests. Project-scoped configuration can influence security-relevant behavior beyond subprocess startup, including settings such as sandbox_mode, approval_policy, notify, model_providers, model_provider.
Codex is also the most straightforward case from a remediation perspective. It already computes a project-config fingerprint internally. The missing piece is using that fingerprint to invalidate stale trust when the config changes.
Gemini CLI
Gemini's project-scoped MCP config lives in .gemini/settings.json:
On current builds, Gemini's first-use folder trust dialog explicitly surfaces project MCP servers. In other words, the product does try to warn the user when the repo first introduces local execution through project config.
The problem is what happens after that. Once the folder is trusted, later changes to .gemini/settings.json are loaded on reopen without a new trust gate.
Why this isn't new – and why that matters
What is frustrating about this bug class is not that it exists. It is that the exact pattern has already been named, assigned a CVE, and fixed elsewhere in the developer-tool ecosystem.
Thirteen days from disclosure to patched release, on the public changelog. CVSS 7.2 (High). No argument over threat models, no debate about approval fatigue. Cursor called it what it was: an integrity failure in a trust system.
VS Code Copilot
Microsoft documents the control in plain language. From the VS Code MCP docs:
When you add an MCP server to your workspace or change its configuration, you need to confirm that you trust the server and its capabilities before starting it.
That is the control Anthropic, OpenAI and Google declined to add. It is neither unusual nor impractical. It is already part of the expected behavior in the surrounding toolchain.
GitHub Actions
GitHub Actions is not an AI agent, but the integrity principle is the same. Workflow files in .github/workflows/ are version-controlled configurations that can trigger code execution.
Workflow runs triggered by a contributor's pull request from a fork may require manual approval from a maintainer with write access. […] You should be especially alert to any proposed changes in the .github/workflows/ directory that affect workflow files.
The industry already knows how to think about this class of problem. If a repo change can trigger code execution, changes to that config deserve their own approval boundary.
What the vendors actually said
The wording matters. There is no real dispute about the behavior itself. The dispute is about whether vendors think it should count as a security issue.
Anthropic
Anthropic's position was explicit: trusting the workspace means trusting the repository's ongoing contents, and users are expected to rely on normal development workflows such as pull requests and code review.
The most direct final quote was:
OpenAI
OpenAI's reviewer focused on two ideas: first, that the repo was already trusted; second, that re-prompting on changes could create approval fatigue.
Their final resolution said:
OpenAI also raised a UX point: if multiple developer tools all implement change prompts independently, users could end up with overlapping approvals. That is a real coordination problem. It is not a reason to skip the integrity check altogether.
Google
Google's response was the shortest and the clearest about the design intent:
This is the cleanest statement of the shared vendor position: trust attaches to the folder path, not to the content that caused the trust decision in the first place.
Why "you trusted the folder" isn't a good argument
All three replies come back to the same claim: the user consented to the folder, and the folder includes whatever's in it today and whatever shows up tomorrow. We don't find that convincing, and we'll lay out why.
First, the dialog obscures the scope of the trust decision. When somebody clicks "yes, I trust this folder," they see a UI at a specific moment, looking at a specific file tree. The dialog does not say "you are also granting perpetual consent over every future commit, by every current and future contributor, including people who don't have write access yet." If that is the intended meaning, the dialog should say so. Users don't read it that way because no UI explains it that way. The gap between "I trust what's here" and "I trust everything that will ever be here" is the whole bug.
Second, collaborators are not a static set. Trust granted in January applies to people who didn't exist on the repo in January. A contractor added in July inherits January's approval. A stolen GitHub token in March uses January's approval. A hostile PR merged by a different reviewer uses January's approval. The user is never told, and they have no way to scope trust to "only files from committer X" or "only commits before date Y." The trust they gave once is carried forward into every subsequent commit by anyone with push access, including people who would not have been part of the original trust decision.
Third, code review is not a sufficient control. It can catch many defects in application logic, but it is not designed to notice a one-word swap from command: "npx" to command: "bash" in a .mcp.json buried inside a forty-file PR, especially when the reviewer may not know that field spawns a subprocess on launch. Integrity checking belongs in the agent, not only in the reviewer’s head.
Fourth, OpenAI’s approval-fatigue argument is not persuasive in this context. Project-level MCP configs and hook definitions rarely change. That's the point: once a project is set up, the config sits there stable for months at a time. Both Cursor and VS Code ship the exact fix. For most users the observed rate would be zero prompts per day on an ordinary week, and one prompt when something actually changed by someone who isn't them. Which is exactly the scenario the trust system exists to catch.
Finally, "users are responsible" is backwards. If users were going to audit every config file on every git pull, they wouldn't need a trust system. The trust system exists because humans can't do that kind of continuous manual review. Shipping the dialog and then telling users to also do it themselves defeats the point of shipping the dialog.
What "the fix" actually looks like
The minimum viable control is straightforward, even if production implementations need to handle edge cases carefully.
At trust-approval time, use SHA-256 to hash the relevant config files: .mcp.json, .codex/config.toml, .gemini/settings.json, and any files they transitively reference (hook scripts, slash-command definitions).
Store the hashes alongside the trust entry.
On session start, re-hash. If anything differs, pause. Show the user a diff of what changed (old → new), who committed it (the data is already in git log), and require explicit re-approval. If a file was added or deleted, show that too.
On re-approval, persist the new hash. On denial, refuse to spawn the affected config.
This is a local CI/CD integrity problem
Once a coding agent loads repo config and turns it into shell commands, it is acting like CI on a developer laptop. The security question is the same one CI systems already had to answer: when version-controlled automation changes, who approves the new thing before it runs?
Claude Code, Codex CLI, and Gemini CLI have large and growing installed bases. Every one of those installs sits on a developer machine, and developer machines hold source code, SSH keys, cloud credentials, and push access to production infrastructure.
The attack surface is not just obviously malicious repos. It is every repo that has already been trusted. In practice that means:
a compromised collaborator laptop
a leaked GitHub token
a pull request from a new maintainer on an open-source dependency already in use
staff turnover on an internal project nobody has touched in a year
The pattern is familiar from supply-chain incidents. The xz-utils backdoor was not the same vulnerability, but it rhymed: trusted access, legitimate-looking changes, and malicious behavior hidden inside surrounding build logic.
That is why this needs to be treated as an integrity problem, not a niche agent quirk. These tools now occupy the same part of the workflow as IDE tasks, repo hooks, package scripts, and CI jobs: they consume version-controlled configuration and turn it into execution with real privileges. Once they are viewed that way, the expected control becomes obvious. Trust should attach to content, not just to paths. Changed auto-executed configuration should be re-approved. And developer workstations should be treated as high-value runners, not as harmless chat terminals.
Further reading
For readers who want to go deeper on this pattern and related AI IDE security issues:
We reported the trust-persistence findings in Claude Code, Codex CLI, and Gemini CLI in February 2026 through the vendors' disclosure channels. Anthropic closed the Claude Code report as Informative. OpenAI closed the Codex CLI report as Informational / P5. Google closed the Gemini CLI report as Won't Fix / Intended Behavior.
We are publishing this now to document the pattern publicly and make the trust model around AI coding agents easier to evaluate. The attack surface is growing, and this is the kind of integrity boundary that should be discussed openly.
Closing
AI coding agents are quickly becoming part of the default development environment. That makes their trust model part of the software supply chain, whether vendors describe it that way or not. A project file that can start a process is not just "configuration." It is local automation with the developer's credentials behind it.
The principle should be simple: path trust is not enough for executable project config. If the content that caused the user to approve a repo changes, the trust decision is stale. Re-approval should be tied to the thing being run, not just the folder it lives in.
Cursor and VS Code already show that this is a practical control. GitHub Actions shows that the wider developer ecosystem already understands the same integrity boundary. The AI agent ecosystem should adopt it before the next disclosure becomes an incident report.