anthropics / anthropics/claude-code
[BUG] Windows: `headersHelper` trust gate reads forward-slash project key
- 主要言語
- Python
- スター
- 145k
- フォーク
- 23.1k
- PR マージ指標
- PR 指標を取得中
説明
### Preflight Checklist
- [x] I have searched [existing issues](https://github.com/anthropics/claude-code/issues?q=is%3Aissue%20state%3Aopen%20label%3Abug) 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?
# Windows: `headersHelper` trust gate reads forward-slash project key, but the trust dialog writes backslash — MCP server can never connect
## Summary
On Windows, the workspace-trust gate that guards `headersHelper` execution looks up the
project in `.claude.json` using a **forward-slash** path, while the interactive trust
dialog persists that project using a **backslash** path. The two never match, so for any
project-scoped MCP server that uses `headersHelper`:
- the helper is never executed;
- the server connects with no `Authorization` header;
- the remote returns 401;
- Claude Code falls back to OAuth and writes a sticky `needs-auth` cache entry.
The user sees a server that silently never connects. Accepting the trust dialog — the
remedy the debug message itself recommends — does not fix it, because the dialog writes
the key in the format the gate cannot read.
## Environment
- Windows 11 Enterprise 26200
- Claude Code 2.1.246 (also reproduced on 2.1.241)
- Entrypoint: claude-desktop; also reproduced via the CLI binary directly
- Node v26.3.0
- Server type: `"type": "http"` with `headersHelper`
## Impact
Breaks **any** project-scoped `headersHelper` MCP server on Windows. There is no error
surfaced in the UI — the server simply never appears. The natural user response is to
re-accept workspace trust, which cannot resolve it. Only a manual `.claude.json` edit works.
macOS/Linux appear unaffected (no backslashes in paths).
This is a regression: see version bisect below.
## Minimal reproduction
1. Create a throwaway project with a trivial helper:
`C:\temp\mcp-trust-repro\helper.ps1`
```powershell
Write-Output '{"Authorization":"Bearer dummy"}'
```
`C:\temp\mcp-trust-repro\.mcp.json`
```json
{
"mcpServers": {
"trustGateProbe": {
"type": "http",
"url": "https://example.invalid/mcp",
"headersHelper": "powershell.exe -NoLogo -NoProfile -NonInteractive -File C:/temp/mcp-trust-repro/helper.ps1"
}
}
}
```
2. Run from that directory:
```
claude --debug-file log.txt -p "hi"
```
3. Observe in `log.txt`:
```
MCP server "trustGateProbe": headersHelper not run: this workspace has no persisted
trust; accept the trust dialog here once interactively, or set
projects["C:/temp/mcp-trust-repro"].hasTrustDialogAccepted in C:\Users\\.claude.json.
```
Note the lookup key uses **forward slashes**.
4. Accept the trust dialog interactively for that workspace. Inspect `.claude.json`:
the persisted key is `C:\temp\mcp-trust-repro` — **backslashes**.
5. Re-run step 2. The gate still reports "no persisted trust". The helper still does not run.
## A/B confirmation that slash direction is the sole variable
Using an isolated config directory (`CLAUDE_CONFIG_DIR`) so nothing else differs, with a
single `projects` entry containing only `hasTrustDialogAccepted: true`:
| `projects` key | Result |
|---|---|
| `C:/temp/mcp-trust-repro` (forward) | **Gate passes** — `Successfully retrieved 1 headers from headersHelper` |
| `C:\temp\mcp-trust-repro` (backslash) | **Gate blocked** — `headersHelper not run: this workspace has no persisted trust` |
Same path, same value, same everything else. Only the slash direction changes.
## Version bisect
| Version | Behaviour |
|---|---|
| 2.1.237 | No trust gate at all — `Executing headersHelper…` proceeds directly |
| 2.1.241 | Gate present, blocks on the forward-slash lookup |
| 2.1.246 | Gate present, blocks on the forward-slash lookup |
(Versions between 2.1.237 and 2.1.241 were not tested.)
The gate appears to have been introduced in that range. Workspaces trusted under an
earlier build carry a backslash-keyed record that the new gate cannot read, so this
surfaces on update.
## Expected behaviour
The trust lookup should normalise path separators, or query using the same format the
trust dialog persists. A workspace the user has explicitly trusted should satisfy the gate.
## Workaround
Manually add a forward-slash duplicate of the project key in `.claude.json`:
```json
"projects": {
"C:\\temp\\mcp-trust-repro": { "hasTrustDialogAccepted": true, ... },
"C:/temp/mcp-trust-repro": { "hasTrustDialogAccepted": true }
}
```
Claude Code must be fully closed while editing — a running instance rewrites `.claude.json`
on exit and reverts the change.
## Secondary issue (possibly worth splitting out)
`${VAR}` environment-variable expansion works in a server's `command` field but **not** in
`headersHelper`. In the same `.mcp.json`, `"command": "${USERPROFILE}/foo/bar.exe"` expands
correctly, while `"headersHelper": "powershell.exe -File ${SOME_VAR}/helper.ps1"` is passed
through literally and fails.
Also: `-Command` forms of `headersHelper` fail with `did not return a valid value`, while the
identical command line works when run directly from a shell — suggesting the `headersHelper`
string is tokenised in a way that breaks `-Command` payloads. Only `-File ` works.
Combined, these mean the only working form is a **literal absolute path**, which cannot be
committed to a shared `.mcp.json` used by developers with different workspace roots.
### What Should Happen?
Paths need to be normalised when compared.
### Error Messages/Logs
```shell
```
### Steps to Reproduce
See explanation.
### Claude Model
None
### Is this a regression?
I don't know
### Last Working Version
_No response_
### Claude Code Version
Claude Code 2.1.246 (also reproduced on 2.1.241)
### Platform
Anthropic API
### Operating System
Windows
### Terminal/Shell
PowerShell
### Additional Information
_No response_
コントリビューションガイド
このリポジトリのコントリビューションガイドは索引されていません
調査の方向性
Start with the claude-desktop and CLI entry points involved in headersHelper, then trace the trust lookup in .claude.json against the project path persisted after accepting the trust dialog. Reproduce the forward-slash and backslash cases from the report on Windows, and keep the environment-variable and -Command observations separate. Done means a trusted workspace passes the gate using the persisted path format and the existing helper reproduction succeeds.
索引モデルが issue の本文から書いたものです。
評価
- 技術スタック
- json, powershell, python
- 領域
- authentication, backend, security
- issue の種類
- バグ
- 難易度
- 4/5
- 見積もり時間
- 3〜5日
- 活発さ
- 活発
- 明瞭さ
- おおむね明確
- 初心者へのやさしさ
- 48/100