Claude Code Security in 2026: What GhostApproval Changed
GhostApproval showed my Claude Code approval box a fake filename while the write went to my SSH keys. Anthropic called it outside its threat model, so the fix was mine. Here is the field log: what the symlink flaw does, who patched, and the three setup changes that held.

On this page
I approved a file write in Claude Code last Tuesday without reading it twice. The dialog said project_settings.json. I hit yes. On July 7, 2026, Wiz Research gave that lazy little habit a name: GhostApproval.
Quick answer: Claude Code security in 2026 comes down to one habit: never trust the filename in an approval prompt. On July 7, 2026, Wiz Research disclosed GhostApproval, a symlink trick that shows a harmless filename in the approval dialog while the agent actually writes to a hidden target such as your SSH keys. It affects six coding agents. Cursor, Amazon, and Google shipped patches; Anthropic called it outside its threat model, so on Claude Code the real fix is your own workflow. The three changes that stuck for me: scope write permissions to the repo, deny writes to ~/.ssh and dotfiles, and read the resolved path, not the label.
What GhostApproval actually does
The approval box is the whole security model of an agentic coding tool. You let the model read and plan freely, and you gate the moment it writes or runs something. GhostApproval breaks the box.
Here is the trick, start to finish. A malicious repo (a cloned starter, a dependency, a PR you are reviewing) plants a symlink that looks boring:
# what the attacker plants in the repo
ln -s ~/.ssh/authorized_keys ./project_settings.json
# the approval dialog says: "write to project_settings.json"
# the bytes actually land in ~/.ssh/authorized_keys
You see project_settings.json in the prompt. You approve. The agent follows the symlink and writes attacker-controlled bytes into ~/.ssh/authorized_keys. Now their public key is trusted and they can SSH into your machine without a password. Wiz notes the worst case escalates to remote code execution on the developer box.
It is a classic time-of-check to time-of-use gap. The tool checks the friendly name it shows you, then uses the resolved path when it writes. The two are not the same file.
Six agents were named in the disclosure:
Amazon Q Developer,
Anthropic's Claude Code,
Augment,
Cursor,
Google Antigravity, and
Windsurf.
Who patched, and why Claude Code is different
The vendor responses split three ways, and the split is the whole story for anyone deciding what to run.
Scroll to see more
| Agent | Response (July 2026) |
|---|---|
| Patched, assigned CVE-2026-50549 | |
| Patched | |
| Patched | |
| Acknowledged, no fix yet | |
| Acknowledged, no fix yet | |
| Disputed, called it outside the threat model |
If you live in Cursor, you update and move on. On Claude Code the answer is not a version bump.
Anthropic's position, honestly stated, is defensible. Their Claude Code docs already tell you not to point the agent at untrusted repositories, and if you accept that premise, a hostile symlink is your problem, not theirs. I run Claude Code as my default for anything that spans more than a few files, so I am not switching. But I stopped treating "outside our threat model" as "not my problem." If the vendor hands the risk back to me, my setup has to hold it.
The three changes that stuck
None of these are clever. That is why they survived past the week the news broke.
1. Scope writes to the project, deny the sensitive stuff. Claude Code's permission file is the cheapest guardrail here. I added an explicit deny list so no approval, ghost or real, can touch keys and secrets:
{
"permissions": {
"deny": [
"Write(~/.ssh/**)",
"Edit(~/.ssh/**)",
"Write(~/.aws/**)",
"Write(~/.config/**)",
"Write(**/.env)",
"Write(**/.env.*)"
]
}
}
A deny rule wins over any allow, and it wins over me clicking yes while half awake. If GhostApproval resolves to ~/.ssh/authorized_keys, the write is refused before the dialog even matters.
2. Read the resolved path, not the label. When a write prompt shows a file I did not expect to edit, I stopped trusting the name and started checking the target:
realpath ./project_settings.json
# /Users/mp/.ssh/authorized_keys <- nope
If realpath points somewhere outside the repo, the approval is a no.
3. A hook that refuses symlinked writes. I already run pre-write hooks for formatting and guardrails, so adding one that rejects any write whose resolved path escapes the project root cost me ten minutes. The hook does the realpath check from step two automatically, so I do not have to remember to. This is the layer I trust most, because it does not depend on my attention.
What I did not change
I did not turn off approvals and go read-only, and I did not uninstall anything. A permission prompt you approve blindly is theater, but a permission prompt backed by a deny list and a hook is real. The fix for GhostApproval was never "use the agent less." It was "stop letting the dialog be the only thing standing between a repo and my SSH keys."
I also did not add Claude Code to the "unsafe, avoid" pile. The tools I keep reaching for all sit on the same trust model; Cursor just happened to patch the symlink case and Anthropic decided it was mine to hold. Fine. I held it. If you are building your own agents on top of these tools, the same lesson applies at the framework layer, and the AgentNotebook tutorials are a decent place to think that through.
FAQ
What is GhostApproval?
GhostApproval is a symlink-based vulnerability class disclosed by Wiz Research on July 7, 2026. A repository plants a symlink with an innocent filename that resolves to a sensitive file. The AI coding agent's approval dialog shows the innocent name while the write lands on the real target, such as SSH keys.
Is Claude Code safe to use after GhostApproval?
Yes, with guardrails. Anthropic disputed the finding as outside its threat model and did not ship a symlink-specific patch, so Claude Code security in 2026 depends on your own configuration: a permission deny list for sensitive paths, checking resolved paths, and a pre-write hook that rejects writes escaping the project root.
Which AI coding agents were affected?
Six were named: Amazon Q Developer, Claude Code, Augment, Cursor, Google Antigravity, and Windsurf. Cursor (CVE-2026-50549), Amazon, and Google patched. Augment and Windsurf acknowledged without a public fix. Anthropic disputed the classification.
How do I protect my SSH keys from an AI coding agent?
Add explicit deny rules for ~/.ssh, ~/.aws, and .env files in your agent's permission config, run agents scoped to the project directory rather than your home directory, and never run an agent against a repository you do not trust.
Does turning off auto-approve fix it?
Only partly. The flaw is that the approval dialog shows the wrong filename, so manual approval still hands you a lie. Approval is only useful when it is backed by a deny list and a resolved-path check that do not depend on you reading carefully.
Postscript: I keep a sticky note on my monitor now. It says "read the path, not the name." I will probably still click yes too fast someday, which is exactly why the deny list is not optional.
Written by
M. PatelBackend dev. Writes when something breaks. Currently shipping a B2B agent product with one cofounder.
Frequently asked questions
What is GhostApproval?
GhostApproval is a symlink-based vulnerability class disclosed by Wiz Research on July 7, 2026. A repository plants a symlink with an innocent filename that resolves to a sensitive file. The AI coding agent's approval dialog shows the innocent name while the write lands on the real target, such as SSH keys.
Is Claude Code safe to use after GhostApproval?
Yes, with guardrails. Anthropic disputed the finding as outside its threat model and did not ship a symlink-specific patch, so Claude Code security in 2026 depends on your own configuration: a permission deny list for sensitive paths, checking resolved paths, and a pre-write hook that rejects writes escaping the project root.
Which AI coding agents were affected?
Six were named: Amazon Q Developer, Claude Code, Augment, Cursor, Google Antigravity, and Windsurf. Cursor (CVE-2026-50549), Amazon, and Google patched. Augment and Windsurf acknowledged without a public fix. Anthropic disputed the classification.
How do I protect my SSH keys from an AI coding agent?
Add explicit deny rules for ~/.ssh, ~/.aws, and .env files in your agent's permission config, run agents scoped to the project directory rather than your home directory, and never run an agent against a repository you do not trust.
Does turning off auto-approve fix it?
Only partly. The flaw is that the approval dialog shows the wrong filename, so manual approval still hands you a lie. Approval is only useful when it is backed by a deny list and a resolved-path check that do not depend on you reading carefully.
Keep reading
Claude Code hooks: the 4 I kept, the 2 I deleted (2026)
I ran Claude Code hooks daily for a month. Four earned their place, two got deleted, and one quietly made my workflow worse. The honest field log.
Cursor vs Claude Code: an honest field log (2026)
A month of running Cursor and Claude Code daily on the same Next.js project. What each one is actually for, where they bit me, the cost difference, and why I kept both instead of picking a winner.
I Built 20 Claude Code Commands. I Use Four.
A field note on Claude Code commands: which custom slash commands actually earned their place, which I deleted, and the 2026 question the listicles skip, when a command should have been a skill.


