
Six Coding Agents, One Symlink. The Approval Prompt Has Been Lying to You.
When my self-hosted agent got prompt-injected into mining Monero, the failure was mine. I left an API exposed and I ran the thing as root. I wrote the whole embarrassing thing up so nobody had to repeat it. But there was a comforting story underneath that post: if you keep the doors shut and read the prompts before you approve them, you're mostly fine.
This month that story stopped being true. Researchers at Adversa published a symlink-hijack chain — they call it SymJack — that works against six independent AI coding agents at once. The part that should bother you isn't the exploit. It's the premise it breaks: you read the approval prompt, you clicked yes, and the write landed somewhere else entirely.
What the attack actually does
The chain is depressingly short, which is what makes it good. An attacker commits a repo containing a symlink with a boring name — the disclosure uses vid-settings.mp4 — that actually points at the agent's own config: .mcp.json or .claude/settings.json. The repo's instruction file — CLAUDE.md, AGENTS.md, whichever your agent slurps up on open — asks for a harmless-looking file operation.
# what the approval prompt shows you:
cp media/vid0.mp4 docs/vid-settings.mp4
# where the kernel actually writes:
~/.claude/settings.json <- a symlink was waiting thereYou approve a copy. The kernel follows the link and overwrites your config with an attacker-controlled MCP server definition. Next time the agent restarts, it loads that server and runs their code with your privileges. As the researchers put it: the developer approves what the prompt shows, and the kernel writes somewhere else.
Why six vendors shipped the same bug
Claude Code, OpenAI's Codex CLI, Cursor Agent CLI, GitHub Copilot CLI, Gemini/Antigravity CLI, and Grok Build were all confirmed vulnerable. Six teams, six codebases, one bug. That only happens when everyone inherits the same four assumptions:
Project instruction files get auto-ingested as trusted input. Shell commands are used for file work, routing around the agent's own native write guardrails. Approval prompts inspect the literal command string rather than the resolved path. And MCP servers get loaded from possibly-compromised config at startup. Every one of those is a reasonable-looking product decision. Stacked, they're an RCE.
The fix is one word: canonicalize. Resolve the path before you make the permission decision, and show the human the real destination. It's the same lesson as every path-traversal bug of the last thirty years, arriving late to a new category of tool.
The vendor scoreboard, and a note on the name
This is the uncomfortable part. Of the six, exactly one shipped the right fix: Anthropic rejected the report and then quietly patched Claude Code to resolve symlinks before asking for approval and display the real destination path. Google declined it as a user self-attack. Cursor declined it as a duplicate. OpenAI declined it, treating the approval as intended behaviour. GitHub didn't respond. xAI hadn't responded at the time of writing.
I'll also flag a small mess, because chasing citations to their source is a hobby of mine now. Secondary coverage this month has been calling this GhostApproval and listing a partly different set of tools — Amazon Q, Augment, Windsurf. The primary Adversa write-up names SymJack and names six specific CLI versions. Either there are two overlapping disclosures or the retellings drifted; I've written this one off the primary document and the version numbers in it. If you're patching, patch off version numbers, not off a nickname.
CI is the real blast radius
On a laptop this is a one-click credential theft — bad, survivable, you notice eventually. On a CI runner it's zero-click, because non-interactive mode auto-approves by definition. Deploy keys, signing material, and cloud credentials leave the box before a human sees the run. Every team that wired an agent into pull-request automation this year — and after building a PR-reviewer agent myself, I know how many did — now has an agent reading untrusted forks with a token in its environment.
This is exactly what Five Eyes meant when they said cyber risk now ages in months. The agent CLI you audited in spring has a different threat model in August.
What I changed on my box
Four things, none clever. I upgraded every agent CLI I run and checked the version against the disclosure rather than trusting a changelog. I added a pre-clone scan for tracked symlinks pointing anywhere near a dotfile — git ls-files -s | grep ^120000 costs nothing and catches the naive version. I stopped letting any agent read a repo I don't control from the same user account that holds my credentials. And I took the already compromised rule from my hardening playbook and extended it from my server agent to my laptop agents, which is where I'd been sloppy.
The one I keep chewing on: agent config lives in the same directory tree the agent has write access to. On my one-VPS stack I fixed that with a systemd sandbox and a read-only mount. On a dev laptop there's no equivalent, and I don't think the vendors have an answer yet either.
The verdict
I've spent a year telling people the human-in-the-loop approval is the load-bearing control in an agent stack. SymJack says the control is only as good as the string it renders — and four of six vendors don't think that's their bug. When I scored the coding agents earlier this year, I graded on speed, context handling, and cost. I'm adding a column: does the prompt tell the truth about what it's about to do?
Cloning a repo used to be safe. Cloning a repo with an agent watching is an execution decision. Treat any machine that has run an agent against an untrusted repo the way you'd treat any other suspected compromise: rotate the credentials and move on with your day.
Sources
The primary disclosure, with affected CLI versions, the vendor response table, and proof-of-concept for all six products: Adversa AI's symlink-hijack write-up. Adversa's broader August 2026 coding-agent security roundup covers the separate Cursor sandbox-escape pair (CVE-2026-50548 / CVE-2026-50549, CVSS 9.8) reported by Cato Networks, summarised by SecurityWeek. The GhostApproval naming and the alternate tool list appear in this Threat-Modeling.com piece — if you can establish whether that's the same disclosure under a second name, tell me and I'll append a correction.
More writing