The Repo Shouldn't Get to Vote on Its Own Trust
On April 24, 2026, Anthropic published GHSA-q5hj-mxqh-vv77, a Claude Code trust dialog bypass with CVSS 7.7. Thirty-seven days earlier, on March 18, the same project published GHSA-mmgp-wc2j-qcv7 with the same CVSS score. Two trust-dialog bypasses in the same agent runtime in the same six-week window are not a coincidence.12
The shared shape is the lesson. In the March bug, project-controlled .claude/settings.json was read before the workspace trust check, and a bypassPermissions permission mode in that file trivially satisfied the gate.2 In the April bug, a malicious repository ships a crafted commondir file inside .git/, the trust evaluator follows the pointer to a directory the user already trusts, and the workspace inherits that trust without ever showing the dialog.1
Two lines of text inside a repo nobody opened yet could vote a workspace trusted. The project-level surfaces the repo ships (hooks, MCP server configs, skills, subagents) can then be resolved against that vote, whether eagerly at session start or lazily when invoked. The downstream defenses in any agent runtime are gated on a decision the runtime makes before they exist.
TL;DR
- Two Claude Code trust dialog bypass CVEs in 37 days show what breaks when repo-controlled bytes influence workspace trust.
- The immediate user-side fix is to upgrade past 2.1.84, narrow trusted paths in
~/.claude.json, and avoid broad parent-path trust like~/Projects. - The structural fix is a load-order invariant: interpret no workspace byte until the workspace path is explicitly trusted.
What The Two Advisories Actually Patched
Reading the patches against the documentation makes the load-order failure visible. The fixed versions reorder which bytes the trust evaluator is allowed to consult.
The March advisory describes Claude Code resolving project settings before resolving workspace trust. The fix in 2.1.53 reverses that order, so the trust check no longer reads .claude/settings.json from inside the workspace before the user has decided.2 The April advisory describes the trust evaluator following the commondir file in a repository’s .git/ directory while resolving the workspace path itself. The fix in 2.1.84 stops the evaluator from honoring repository-controlled commondir content during trust evaluation.1 Both patches restore the same invariant: the trust decision must not consult bytes that live inside the candidate workspace.
The CVE classifications point at the same diagnosis. The March bug is filed as CWE-807, Reliance on Untrusted Inputs in a Security Decision.3 The April bug is filed as CWE-20 plus CWE-77, Improper Input Validation and Improper Neutralization of Special Elements, because commondir resolution treated repository-controlled bytes as authoritative.1 Different CWEs, same broken assumption: a security gate that reads from the artifact it is gating.
The Pre-Trust Surface Is Wider Than The Settings Reference Implies
Claude Code documents a set of project-controlled session-start surfaces that must remain behind the trust gate. The two CVEs in this class prove the invariant breaks when any of them enters the trust decision itself. The surfaces split into two scopes the trust analysis has to keep separate: bytes that ship with a cloned repository, and bytes a user adds to a workspace locally without committing them.4567
Repo-committed surfaces (ship with git clone). These are the supply-chain surface. Anything in this group is what an attacker controls when they author a malicious repository.
| Surface | Location | Influence |
|---|---|---|
| Project settings | .claude/settings.json |
Permission mode, model, tools, hooks. Used by CVE-2026-33068.2 |
| Project prompt | CLAUDE.md |
Project instructions merged into the system prompt. |
| Slash commands | .claude/commands/*.md |
Project-defined commands; partially superseded by skills.7 |
| Subagents | .claude/agents/*.md |
Named subagent definitions. |
| MCP server configs | .mcp.json |
Tool providers referenced at session start.5 |
| Skills | .claude/skills/* |
Scoped task packs. |
| Source bytes | anywhere in the tree | Read-for-context after the dialog. |
Workspace-local surfaces (not committed by default). These do not ride supply chain into the workspace; they appear when a local user creates them. They still live inside the workspace path, so the trust gate must still treat them as untrusted until the path is approved.
| Surface | Location | Influence |
|---|---|---|
| Project-local settings | .claude/settings.local.json |
Workspace-local overrides, normally gitignored.4 |
Hooks live inside .claude/settings.json rather than a separate file; the April advisory describes the attacker populating that key directly.16 The April bug also revealed a surface that is not part of the Claude Code configuration reference at all: a git-internal file named commondir, which resolves a worktree back to its parent repository.8 A malicious repository that ships a crafted commondir layout inherits the trust of the target path when Claude Code follows the pointer during trust evaluation. The git-internal surface broke the project-config surface count, which is the real lesson. The taxonomy is not closed. The attack surface is defined by what bytes get read before the dialog fires, and anything that can influence path resolution or configuration is fair game.
The pattern is the one MCP Servers Are the New Attack Surface named at a different altitude.9 MCP servers exploded the tool-provider surface before the ecosystem caught up with the implications. Trust dialog bypass is the same shape one layer lower. Every convenience feature that lets a repository pre-configure the agent adds a row to the taxonomy above. Every row is a candidate for the next CVE in the class.
The Back Of The Cabinet: A Load-Order Invariant, Not A Smarter Dialog
Paul Jobs taught Steve that the underside of a cabinet deserves the same care as the finish.10 The cabinet metaphor is not decorative here. It is the spine of the fix.
A trust dialog is the back of the cabinet. Users do not see the load order. They see a dialog, they click Trust, and they assume every byte inside the workspace is inert until that click. The implementation has to earn that assumption. When it does not, the assumption is the attack surface.
The load order is the invariant that decides whether the assumption is earned. The minimal model implied by the two advisories and the public Claude Code settings documentation is roughly:216
- Read user settings from
~/.claude/settings.json. - Read user settings from
~/.claude/settings.local.json. - Evaluate whether the current workspace path is trusted.
- If not, show the dialog. If the user clicks Trust, persist the path.
- Read project-scoped
.claude/settings.jsoninside the repo. - Read project-scoped
.claude/settings.local.json. - Resolve hooks, MCP servers, skills, and subagents from the merged settings.
- Run
SessionStarthooks.
The advisories do not document every step exactly, and the placement of skills, subagents, and MCP relative to settings merging is implementation detail the user does not see. What the advisories do establish is the boundary at step 3. Anything resolved before step 3 is in the trusted-input zone. Anything resolved at step 3 or later must not consult workspace bytes. The March bug swapped steps 3 and 5: project settings resolved first, and the permission mode those settings set (bypassPermissions) trivially satisfied the trust check at step 3.2 The April bug moved the attack into step 3 itself: the workspace-path resolution consulted a repository-controlled commondir file, and a forgery made the trust check resolve against the attacker’s chosen trusted path.1 Either way, by the time step 7 or step 8 arrives, the workspace is already trusted, and every project-level surface loads against that vote.
The rule the back of the cabinet demands is one sentence: interpret no byte inside the workspace until the user has explicitly trusted the workspace path. Not .claude/settings.json. Not commondir. Not CLAUDE.md. Not a filename list. Not a hook file. Not an MCP server config. If it lives inside the workspace, the code that decides trust does not look at it.
Visual Studio Code shipped this fix in May 2021 as Workspace Trust (release 1.57). The core folder-trust class has not produced a published bypass since the feature shipped, though adjacent issues around trusted domains and extension behavior continue to surface.1112 Version 2.1.53, the fix referenced by the March advisory, landed the Claude Code version of the invariant by reordering steps 3 and 5.2 Version 2.1.84, the fix referenced by the April advisory, landed it by refusing to follow repository-controlled commondir files during trust evaluation.1 Both are patches that restore the invariant rather than inventing a new defense.
The Steve Test pulls the next thread: would Blake sign his name to this?13 The answer for Claude Code in this six-week window is no, because the vendor has twice signed, shipped, and patched bypasses of this class. That is the vendor’s bar to fix. Minimum Worthy Product is the standard the sign-off refers to.14 Minimum is a scope constraint, not a quality discount. A minimum viable trust dialog is a dialog that blocks the cheap case. A minimum worthy trust dialog is the first step of a load order that refuses to interpret any repository byte before the user has decided. The product you ship is the bytes you refuse to interpret until you are allowed to.
Three Fixes The Invariant Demands
The rule is the invariant. Three patterns follow directly from it.
One-way gates. The trust-making code reads only the path, the user’s click, and the persisted trust state outside the workspace in ~/.claude.json.15 Nothing else. Any refactor in which a workspace file contributes to the trust decision is a regression.
No transitive trust through path resolution. The preferred invariant is that worktrees, submodules, include-files, and symlink targets each get their own prompt. Visual Studio Code’s Workspace Trust, by contrast, allows parent-folder trust to apply to subfolders, and that choice is what broad parent-path trust like ~/Projects exploits when path resolution is spoofed. The stricter rule pays a few extra dialogs and removes the entire transitive-trust surface; the looser rule keeps friction low and accepts that path-resolution bugs become trust-resolution bugs.11
Adversarial fixtures in the trust-read-order regression test. A deliberately crafted adversarial repo that commits canary workspace files. The test asserts that no code path reads those canaries before the dialog is confirmed. If a future change to the runtime reads any canary file during trust evaluation, the build fails. CWE-501, Trust Boundary Violation, is the broader family worth tracking in the test taxonomy alongside the more specific CWE-807 and CWE-20/CWE-77 classifications the published advisories already use.16
None of the three is expensive. The first is the absence of code. The second costs user-visible friction. The third is one engineering pass plus discipline thereafter. Trust-bootstrap compromise is a category where the usual defense in depth posture does not apply, because every layer downstream of trust runs against the trust decision the workspace just helped make. Defense outside trust is impossible to build at the scaffolding layer because the scaffolding is exactly what the workspace gets to read once trust resolves.
The vendor has to ship the invariant. Trust-dialog bypass CVEs are how observers measure whether the vendor is meeting the bar. Two in six weeks is not noise. It is a signal that the invariant has not been encoded in the test suite as an assertion the build enforces. Until it is, the next CVE in the class is a matter of finding the tenth input.
The repo should not get to vote on its own trust. Trust is the one decision the artifact being evaluated must not help make. Every other layer of the agent’s defense (hooks, skills, validators, detectors, guards) lives downstream of that single vote. When the vote is rigged, the downstream work is furniture. The finish of the cabinet does not save the back.
FAQ
What is the Claude Code trust dialog bypass?
A Claude Code trust dialog bypass happens when an untrusted workspace gets treated as trusted before the user explicitly approves it. In the March 2026 CVE, repo-controlled settings influenced permission mode before trust was evaluated. In the April 2026 CVE, a crafted git worktree/commondir layout caused trust to resolve through an already trusted path.
How should I narrow trusted paths in ~/.claude.json?
Open ~/.claude.json and inspect the projects map. Look for entries where hasTrustDialogAccepted is true on directories that no longer hold active code, on broad parent paths such as ~/Projects, and on any path that overlaps with worktree-adjacent layouts. Per-repository trust adds dialogs but prevents one accepted parent path from silently covering every child.
Why is parent-path trust dangerous for Claude Code?
Parent-path trust is dangerous because one accepted directory can cover many child workspaces. If path resolution gets spoofed, or a malicious worktree points back into that parent, the child repo can inherit trust that was never granted to it. Per-repo trust adds friction, but it prevents transitive trust across unrelated repos.
What invariant prevents trust dialog bypasses?
The invariant is: interpret no byte inside the workspace until the user explicitly trusts the workspace path. Trust code may read the path, the user’s click, and persisted trust state outside the repo. It should not read .claude/settings.json, CLAUDE.md, .mcp.json, hooks, skills, commondir, or any repo-controlled file before the dialog.
References
-
Anthropic, “Trust Dialog Bypass via Git Worktree Spoofing Allows Arbitrary Code Execution,” GHSA-q5hj-mxqh-vv77, April 24, 2026. CVE-2026-40068. CVSS v4 7.7. Affects 2.1.63–2.1.83. Fixed in 2.1.84. ↩↩↩↩↩↩↩↩
-
Anthropic, “Workspace Trust Dialog Bypass via Repo-Controlled Settings File,” GHSA-mmgp-wc2j-qcv7, March 18, 2026. CVE-2026-33068. CVSS v4 7.7. Fixed in 2.1.53. ↩↩↩↩↩↩↩
-
MITRE, “CWE-807: Reliance on Untrusted Inputs in a Security Decision,” cwe.mitre.org. ↩
-
Anthropic, “Claude Code settings reference,” code.claude.com docs. Project-level configuration surface and
.claude/settings.local.jsonworkspace-local override semantics. ↩↩ -
Anthropic, “Model Context Protocol configuration,” code.claude.com docs.
.mcp.jsonformat. ↩↩ -
Anthropic, “Hooks reference,” code.claude.com docs. Lifecycle event taxonomy. ↩↩↩
-
Anthropic, “Skills reference,” code.claude.com docs.
.claude/skills/*format and the skills/commands relationship. ↩↩ -
Git, “gitrepository-layout: Git Repository Layout,” git-scm.com.
commondirfile format for worktrees. ↩ -
Author’s analysis in MCP Servers Are the New Attack Surface, April 8, 2026. ↩
-
David Sheff, “Playboy Interview: Steven Jobs,” Playboy, February 1985. Paul Jobs’s cabinet-back lesson is told in Steve Jobs’s own words in the interview. ↩
-
Microsoft, “Workspace Trust in Visual Studio Code,” code.visualstudio.com/blogs, July 6, 2021. Shipped in Visual Studio Code 1.57 (May 2021 release). ↩↩
-
Microsoft, “Workspace Trust,” Visual Studio Code documentation. Folder-trust semantics and the parent-folder trust behavior. ↩
-
Author’s analysis in The Steve Test. “Would I sign my name to this without flinching?” ↩
-
Author’s analysis in Minimum Worthy Product. Minimum as scope constraint, worthy as quality bar. ↩
-
Anthropic, “Claude Code configuration file,” code.claude.com docs.
~/.claude.jsonstores per-user settings including trusted project paths. ↩ -
MITRE, “CWE-501: Trust Boundary Violation,” cwe.mitre.org. ↩