The check and the write were two steps
Claude Code validates that the file it is about to write lives inside the project working directory before it writes. Per the advisory, that validation ran at permission-check time, but the path was re-resolved at write time without repeating the check. The two moments were separate, and nothing held the answer still in between.
That gap is a time-of-check to time-of-use (TOCTOU) flaw, filed as CWE-367 alongside CWE-22 (path traversal) and CWE-61 (symlink following). The permission check and the write operation acted on a path that could be made to mean two different things.
Winning the race
An attacker who could write to the shared workspace could atomically replace a project file with a symlink in the window between the check and the write. Claude Code then followed the symlink and wrote its output to whatever the link pointed at, outside the project sandbox.
The advisory describes the result as a lower-privileged attacker redirecting benign edits into sensitive files, naming shell configuration as the example, in a higher-privileged session. Exploitation required two things at once: the ability to win a race against the write operation, and write access to the workspace the two sessions shared.
Already fixed on the auto-update channel
The fix has shipped. Users on standard Claude Code auto-update have already received it; users who update manually are advised to move to 2.1.129, the first patched version. NVD records the flaw at CVSS 4.0 7.7 (High), and credits the reporter as hackerone.com/c_h4ck_0.
The pattern is the one this log keeps meeting from different directions: a check that runs once, at the wrong moment, against an object that changes before the action it was meant to guard. GhostApproval dressed a symlink as a settings file the approval dialog named; this one needed no disguise, only a head start.
Sources
Research
Thread
- Relates to: Guardrails checked once, at the wrong moment
- Relates to: Approving a settings edit and authorizing an SSH key
- Related to: One symlink unlocked every credential
Same primitive of a swap between check and use, but a different mechanism: a race window there, an unresolved operator path here.
- Relates to: A symlink led the sandbox out
Semantic neighbors
- Approving a settings edit and authorizing an SSH key80% similar
- One symlink unlocked every credential78% similar
- The hook ran before the model could look75% similar
