NEWS · JULY 9, 2026 · 5 MIN READ

GhostApproval: Why Human-in-the-Loop Failed Six AI Agents At Once

Wiz disclosed a symlink attack that breaks the approval dialogs in six AI coding agents simultaneously, exposing a category-level control-plane failure, not a model bug.


GhostApproval: Why Human-in-the-Loop Failed Six AI Agents At Once

On July 8, 2026, Wiz disclosed GhostApproval: a symlink-following attack that breaks the approval dialogs in six of the most widely deployed AI coding agents simultaneously. The agents affected are Claude Code, Cursor, Amazon Q Developer, Augment, Google Antigravity, and Windsurf. The attack is not a model bug. It is a control-plane bug, and the "human approves every destructive action" story that vendors have sold to enterprise buyers for 18 months just broke six times in the same afternoon.

What the Attack Does#

A symbolic link is a filesystem pointer. It looks like a file, but resolves to a different path when a process reads or writes it. CWE-61 , symlink following , has been an exploitable primitive since the early Unix era, appearing in package managers (CVE-2021-32803), container runtimes (CVE-2024-21626), and /tmp race conditions going back decades.

GhostApproval applies the primitive to AI coding agents. An attacker creates a repository where a file named project_settings.json is actually a symlink pointing to ~/.ssh/authorized_keys. A README instructs the agent to populate that file with a provided SSH public key. When a developer clones the repository and asks their agent to "set up the workspace," the agent follows the symlink and writes the attacker's public key directly to authorized_keys. The attacker gains persistent, password-less SSH access to the developer's machine.

The symlink step alone is serious. What Wiz found below it is worse.

The CWE-451 Layer#

Several of these agents did not blindly miss the symlink. Their internal reasoning identified it. In Claude Code, the agent's thinking explicitly stated: "I can see that project_settings.json is actually a zsh configuration file." The confirmation prompt shown to the user asked: "Make this edit to project_settings.json?"

The agent knew. The user did not. That is CWE-451 , user interface misrepresentation of critical information , stacked on top of CWE-61. The security boundary existed. It just failed to surface the one piece of information a human needs to make a meaningful decision.

Windsurf's variant was worse in a different direction: the agent wrote to disk before the Accept/Reject buttons appeared. The confirmation dialog was not an authorization gate. It was an undo mechanism. By the time a developer saw the prompt, the attacker's SSH key was already in authorized_keys.

Vendor Responses Vary Significantly#

Three vendors fixed the issue. AWS assigned CVE-2026-12958 and patched Amazon Q Developer in language server version 1.69.0. Cursor assigned CVE-2026-50549 and shipped a fix in v3.0. Google patched Antigravity on May 22, 2026, and is in the process of assigning a CVE.

Augment and Windsurf had acknowledged Wiz's report at the time of public disclosure but had not shipped patches or notified users.

Anthropic's position was distinct. The company initially called the finding outside its threat model, reasoning that the user had explicitly trusted the directory at session start and explicitly approved the confirmation prompt. Anthropic told Wiz: "The scenario you describe involves a user explicitly confirming a permission prompt inside of a directory containing a malicious symlink, which falls outside of the Claude Code threat model." Anthropic later clarified that a symlink warning had shipped in v2.1.32 on February 5, 2026 , nine days before Wiz submitted the report , as part of proactive internal security hardening.

The philosophical divide here is real. Anthropic's position is internally coherent: two explicit consent moments occurred. The counter-position, which Google, AWS, and Cursor implicitly endorsed by issuing CVEs, is that consent requires accurate information. A user who approves a write to project_settings.json has not consented to a write to ~/.ssh/authorized_keys. The approval is formally present and substantively empty.

Why This Is a Governance Problem, Not Just a Patch Problem#

The patch story is straightforward: resolve symlinks to canonical paths before constructing any prompt, verify the canonical path falls within the workspace boundary, and never write to disk before explicit authorization. Most vendors who treated this as a bug have done exactly that.

The governance problem does not resolve with the patch. Enterprise teams deploying AI coding agents have been sold a specific security model: the agent proposes, the human approves, nothing destructive happens without consent. GhostApproval demonstrates that this model has a structural dependency , the approval dialog must accurately represent what the agent is about to do. If the dialog can be deceived by filesystem state that predates the session, the HITL guarantee is conditional on the workspace being trustworthy. That condition fails exactly in the adversarial cases where it matters most.

Wiz threat researcher Maor Dokhanian described it directly: "Human-in-the-loop isn't always the safety net it appears to be. When the confirmation prompt hides critical information, developers can't make informed decisions , the approval becomes a rubber stamp."

A control that depends on the trustworthiness of the input it is validating is not a control. It is a ceremony.

What an Independent Review Layer Catches#

The HITL model is an in-process control. It runs inside the agent, interprets filesystem state through the agent's own path resolution, and presents information through the agent's own UI. GhostApproval breaks all three of those layers simultaneously because all three share the same trust context.

An independent review layer operating after the agent acts , reading what actually changed in the repository, not what the agent reported changing , sees the canonical result. A write to ~/.ssh/authorized_keys by a process that was supposed to be editing a local config file is detectable without trusting the agent's reasoning or its prompts. The same is true for writes outside the declared workspace boundary, for file modifications that match known persistence patterns, and for any delta between what the agent logged and what the filesystem recorded.

Hyrax's Govern workflow runs as that independent layer. It reads the actual state of the codebase after agent actions, flags file changes that cross workspace boundaries or match security-relevant patterns, and holds findings for human review before they can be merged. The deliberate choice to submit a PR rather than auto-merge exists precisely because the review step after action is the one that cannot be deceived by in-process state. As the architecture post covers, the 13-step verification runs in an isolated worktree against the actual diff , not against the agent's description of the diff.

What Teams Should Configure Now#

If your organization has developers running any of the six affected tools against untrusted repositories, the immediate steps are concrete. Verify that Claude Code is running v2.1.32 or later, where symlink warnings were added. Confirm Cursor is on v3.0 (CVE-2026-50549 fixed) and Amazon Q Developer's language server is at 1.69.0 or later (CVE-2026-12958 fixed). For Augment and Windsurf, no patch exists as of July 8, 2026 , treat unpatched installs as uncontrolled write access to the developer's full home directory when operating on any repository not fully controlled by your organization.

Longer term, the policy question is whether HITL approval dialogs inside the agent process should count as a security control at the same level as an external audit. GhostApproval's answer is no. The approval dialog is valuable UX. It is not, by itself, a trust boundary.

Hyrax is live at hyrax.dev.


Sources

  1. 01wiz.io
  2. 02theregister.com
  3. 03securityweek.com