Threat · curated 8 Jul 2026

GhostApproval: AI Coding Assistant Trust Boundary Flaw

Dossier

Coverage timeline

8 Jul 2026theregister.comwiz.ioprimary 9 Jul 2026snyk.iothehackernews.com

Why it matters

GhostApproval shows that the human-in-the-loop confirmation dialogs meant to keep developers in control of AI coding agents can be silently subverted, turning an ordinary git clone into persistent SSH access and RCE on the developer's machine.

Wiz researchers disclosed GhostApproval (CVE-2026-12958 and related), a symlink-following vulnerability pattern (CWE-61 plus CWE-451 UI misrepresentation) affecting six top AI coding assistants: Amazon Q Developer, Anthropic Claude Code, Augment, Cursor, Google Antigravity, and Windsurf. A malicious repository disguises a symlink as an innocuous config file so that when the agent 'sets up the workspace' it writes an attacker SSH key to ~/.ssh/authorized_keys — sometimes before any confirmation dialog — while the human-in-the-loop approval prompt conceals the true target, enabling remote code execution. AWS, Cursor, and Google fixed the issue; two vendors went silent and one called it outside its threat model.

vuln-research

Summary

Wiz Research disclosed "GhostApproval," a systematic vulnerability pattern affecting six of the most widely used AI coding assistants — Amazon Q Developer, Anthropic Claude Code, Augment, Cursor, Google Antigravity, and Windsurf. A malicious repository can trick the agent into reading or writing files outside its workspace sandbox, potentially achieving remote code execution on the developer's machine, and Snyk characterizes it as the latest incarnation of a decades-old attack primitive.[0][2]

The flaw chains symbolic-link following (CWE-61) with UI misrepresentation of critical information (CWE-451). In several tested tools the agent's own internal reasoning correctly identified that a benign-looking file (e.g. project_settings.json) was actually a symlink to a sensitive path, yet the human-in-the-loop confirmation prompt concealed the true target — turning informed consent into a rubber stamp, which Snyk frames as an "informed-consent bypass" rather than a mere sandbox escape.[0][2][7][8]

The proof-of-concept ships a repository where a file named project_settings.json is a symlink to ~/.ssh/authorized_keys and a README instructs the agent to append an attacker SSH public key; once the developer asks the assistant to "set up the workspace" or "follow the README," the key is written into authorized_keys, granting persistent password-less SSH access. Wiz also demonstrated a ~/.zshrc variant that Snyk notes is the more dependable code-execution path on a laptop behind a NAT.[0][2]

Vendor responses diverged: AWS (CVE-2026-12958, High), Cursor, and Google shipped fixes, two vendors acknowledged the report without defending the behavior, and Anthropic declined it as "outside our threat model" — though Anthropic states a symlink warning had already shipped in Claude Code in February 2026. Snyk argues that when five of six teams decline to stand behind the design, "outside our threat model" reads less like principle and more like a decision to be revisited.[0][2][42]

Attack chain

  1. Malicious repository preparation: The attacker publishes a repository containing a symlink disguised as an ordinary config file (e.g. project_settings.json pointing to ~/.ssh/authorized_keys or ~/.zshrc), stored by git with file mode 120000 whose blob content is just the target path, plus a README carrying instructions addressed to the agent along with the attacker's SSH public key.[0][2]
  2. Victim clones and instructs the agent: A developer clones the repository — git faithfully recreates the symlink on disk on Linux/macOS — and asks the AI assistant to "set up the workspace" or "follow the README," a completely normal request. The agent reads the planted instructions (indirect prompt injection) and prepares to write the attacker key.[0][2]
  3. Trust-boundary bypass via symlink following: Because the config filename is really a symlink, the agent opens the path without resolving where it points, redirecting the write outside the workspace to ~/.ssh/authorized_keys (or ~/.zshrc). In some tools the write occurred before any confirmation dialog was shown.[0][2]
  4. Deceptive confirmation prompt (human not in the loop): Where a confirmation dialog appears, it shows the innocuous filename rather than the resolved sensitive target — UI misrepresentation (CWE-451). Wiz caught Claude Code internally reasoning that project_settings.json was actually a zsh configuration file while the human-facing prompt merely asked to edit project_settings.json.[0][2][8]
  5. Persistent access / remote code execution: With the attacker's key in authorized_keys, the attacker gains persistent, password-less SSH access if the machine is reachable; the ~/.zshrc variant runs attacker code the next time the victim opens a shell, providing code execution even behind a NAT.[0][2]

Disclosure timeline

DateEvent
2026-02Per Anthropic, a symlink warning shipped in Claude Code before the Wiz report landed, so current versions resolve and warn on such writes; the disagreement is about principle, not the product's present state.[0]
2026-05-07Adversa AI publishes the related "TrustFall" research showing agentic coding CLIs (Claude Code, Gemini CLI, Cursor CLI, Copilot CLI) auto-execute project-defined MCP servers on folder-trust acceptance, likewise declined by Anthropic as design intent.[40]
2026-07-08Wiz publishes the GhostApproval write-up and Snyk publishes its accompanying "symlinks are still scary" analysis; three vendors (AWS, Cursor, Google) had fixed the flaw, two acknowledged without defending it, and Anthropic declined it.[0][2]

How it works

The core primitive is UNIX symbolic-link following (CWE-61): a symlink is a tiny file whose contents are a path, and when a program opens it the OS transparently redirects the operation to the target path. Git stores symlinks with file mode 120000 and a blob equal to the target path, and recreates them on disk when a repository is cloned on Linux/macOS, so an attacker can ship a symlink disguised as an ordinary config file inside a repository.[0][7]

AI coding agents read and write files inside a checked-out repository without first canonicalizing where those paths actually resolve. When an agent follows repo-planted instructions (indirect prompt injection) to edit a benign-named file that is really a symlink, the write is redirected outside the workspace sandbox to a sensitive target such as ~/.ssh/authorized_keys or ~/.zshrc, yielding password-less SSH access or code execution on the developer's machine.[0][2]

Layered on top is UI misrepresentation of critical information (CWE-451): the human-in-the-loop confirmation prompt displays the innocuous filename rather than the resolved sensitive target, and in some tools the write occurred before any dialog appeared. Wiz observed Claude Code internally reasoning that project_settings.json was actually a zsh configuration file while the human-facing prompt only asked whether to edit project_settings.json — an informed-consent bypass.[0][2][8]

Affected versions and patch status

ProductAffectedPatch status
Amazon Q Developer (language server)Language server versions prior to the fixFixed by AWS; rated High severity and assigned CVE-2026-12958.[0][2][42][13]
CursorVersions prior to the fixFixed; a security advisory was published (CVE-2026-50549).[0][2][14][43]
Google AntigravityVersions prior to the fixFixed by Google.[0][2]
Anthropic Claude CodeVersions before the February 2026 symlink warningAnthropic declined the report as outside its threat model but says a symlink warning shipped in Claude Code in February 2026, so current versions resolve and warn.[0]
Augment and WindsurfTested versions found vulnerable to the GhostApproval patternTwo of the six vendors acknowledged receipt of the report without defending the behavior; specific patch status not detailed in the evidence.[0][2]

Key takeaways

  • GhostApproval demonstrates that a decades-old primitive — symlink following (CWE-61) — remains dangerous when applied to a new class of file-reading tools, here AI coding agents, five of six of which shipped or acknowledged fixes.[0][2]
  • The deeper failure is an informed-consent bypass: because the confirmation dialog shows a friendly filename rather than the resolved sensitive target (CWE-451), the human-in-the-loop safety net becomes a rubber stamp even when the agent's own reasoning knew the true target.[0][2][8]
  • Defenders and tool builders should canonicalize paths and enforce workspace boundaries atomically, surface the real resolved target in approval prompts, and treat cloned repositories as untrusted input that may hide symlinks stored with git file mode 120000.[0]

Defensive actions

  • Canonicalize every file path and enforce the workspace boundary atomically before opening it: Snyk recommends resolving each path to its real location and checking it is still inside the intended workspace, using openat2() with RESOLVE_BENEATH or RESOLVE_NO_SYMLINKS on Linux to close the time-of-check/time-of-use gap that a naive realpath()-then-open() sequence leaves open.[0]
  • Show the real, resolved target in confirmation prompts and never write to disk before approval: The core failure is UI misrepresentation: a write to ~/.ssh/authorized_keys should look terrifying on screen, and a dialog that appears after the file is already changed is an undo button masquerading as a security control.[0][2]
  • Audit cloned repositories for symlinks before pointing an agent at them: Snyk advises running `find . -type l` or `git ls-files -s` (looking for the 120000 file mode) immediately after cloning untrusted repositories to reveal symlink 'wormholes' before any tool or agent follows them.[0]
  • Update affected AI coding assistants to patched versions: AWS, Cursor, and Google have shipped fixes and current Claude Code versions resolve and warn on symlink writes; applying these updates closes the trust-boundary gap for the fixed products.[0][2]
  • Treat every cloned repository as untrusted input: Snyk stresses that a filename is a suggestion, not a promise, and that any tool reading files inside a checkout can be walked out of its intended directory, so checkouts should be treated as radioactive until verified.[0]