[BUG] Workspace trust is keyed on a raw, unnormalized path string — trust granted in the CLI doesn't apply in the VS Code extension for the same folder, silently voiding all permission rules
Preflight Checklist
- [ ] I have searched existing issues and this hasn't been reported yet
- [x] This is a single bug report (please file separate reports for different bugs)
- [x] I am using the latest version of Claude Code
What's Wrong?
Environment
- Claude Code (CLI): 2.1.152 — VS Code extension (Claude Code for VS Code) on the same machine
- VS Code: 1.128.1
- OS: Windows 11 Pro (10.0.26200)
---
Workspace trust (hasTrustDialogAccepted, stored per project in ~/.claude.json) is keyed by the literal path string, with no canonicalization — not case, not separator. The CLI and the VS Code extension resolve the same folder to different strings, so they read different trust rows:
- CLI →
C:/Tools/ai-stack(uppercase drive) - VS Code extension →
c:/Tools/ai-stack(lowercase drive)
I accepted the trust dialog via the CLI. The extension then treated the same folder as a different, untrusted project and — per documented behavior ("Project allow rules and workspace trust") — read every permissions.allow rule and silently ignored it, indefinitely. The CLI kept working perfectly, which made this nearly impossible to diagnose. It took four days.
Evidence (from my ~/.claude.json → projects): both C:/Tools/ai-stack (trusted) and c:/Tools/ai-stack (untrusted) exist as separate entries for one folder. Setting hasTrustDialogAccepted: true on the lowercase key alone fixed the extension immediately — one variable, controls held.
It's broader than the drive letter. C:\TEMP\AI (backslashes) and C:/TEMP/AI/cli (forward slashes) coexist in the same table, so there's no separator normalization either. Any path-string variation — folder-name case, separators, trailing slash, 8.3 short names, junction vs. real path, UNC vs. mapped drive — creates a new untrusted project and silently voids its permissions.
Three things made it far worse than the bug itself:
- No signal. An untrusted workspace gives no indication that rules are being ignored. Tools just keep prompting, and every fix to the rule files does nothing. (I proposed and disproved five root causes before checking the gate.)
- The dialog only fires on an interactive session start. A window reload resumes the conversation and never re-fires it — so a user who reloads (the normal VS Code flow) is never offered the dialog and has no path to trust the workspace at all.
- It presents as non-determinism. With allow-rules inert, auto-mode's classifier decides instead — waving through read-only tools, prompting for others. So you see "some tools silent, some prompting" with byte-identical rules, and conclude your rule syntax is wrong. It isn't.
Suggested fixes:
- Normalize the project key (case + separators + trailing slash), or resolve to a canonical real path, before the trust lookup.
- Surface the untrusted state explicitly — "this workspace is untrusted; your permission rules are being ignored" — instead of failing silently.
- Offer a way to grant trust that doesn't depend on catching an interactive first-run (a command, or re-offer it in the extension).
- If a trusted key differs from the current key only by normalization, say so: "You already trusted this folder as
C:\…."
Security note (worth flagging): the gate failing closed is what protected me — a blanket run_script-style rule that executes arbitrary code sat in a committed, team-shared .claude/settings.json, inherited by everyone who clones the repo, and was inert only because trust happened to be off. A user who "fixes" this by hand-setting the trust flag will silently activate whatever a repo has checked in. So normalization + a visible untrusted state isn't just UX — it changes who's protected by accident vs. by design.
What Should Happen?
Behavior of CLI and VScode extension being the same, same os path is same things (case insensitive for windows, or forward backward slashes) and if 2 things are defined with the same path one with grant one with deny then deny should be the default for both CLI and Vscode extension instead of different behavior on each. see the suggestions in the message.
Error Messages/Logs
Steps to Reproduce
- On Windows, have a project folder on a drive whose letter can be expressed in different case (e.g.
C:\Tools\ai-stack). - In that folder, add a permission rule to
.claude/settings.json(project scope) — any allow rule, e.g. an MCP toolmcp__companion__usageunderpermissions.allow. - Start Claude Code via the CLI (
claude) in that folder and accept the workspace-trust dialog ("Yes, I trust this folder"). - Confirm the rule works in the CLI — the tool runs without prompting.
- Open the same folder in the VS Code Claude Code extension and trigger the same tool. Observed: it still prompts — the project allow-rule is silently ignored, as if the workspace were untrusted.
- Inspect
~/.claude.json→projects. There are two entries for the same folder, differing only in drive-letter case:
"C:/Tools/ai-stack"→"hasTrustDialogAccepted": true(written by the CLI)"c:/Tools/ai-stack"→"hasTrustDialogAccepted": false/ absent (used by the VS Code extension)
Confirming the cause (one variable): set "hasTrustDialogAccepted": true on the lowercase c:/… entry and restart VS Code. The rule now applies and the tool stops prompting. Changing only that one flag fixes it — proving the extension keys the project by the lowercase path and never inherits the trust the CLI recorded under the uppercase path.
Broader repro (same root cause): the key isn't normalized for separators either — opening the same folder as C:\TEMP\AI (backslashes) vs C:/TEMP/AI (forward slashes) yields two distinct projects entries.
Expected: the project key is normalized (or resolved to a canonical real path) before the trust lookup, so trust for a folder applies regardless of how the path was expressed or which surface (CLI vs. extension) recorded it.
Claude Model
None
Is this a regression?
I don't know
Last Working Version
_No response_
Claude Code Version
2.1.152
Platform
Anthropic API
Operating System
Windows
Terminal/Shell
VS Code integrated terminal
Additional Information
_No response_
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗