anthropics / anthropics/claude-code

[BUG] Windows: `headersHelper` trust gate reads forward-slash project key

オープン
#90,041 コメント 0 件 リアクション 0 件 担当者 0 名 GitHub で見る
area:mcp bug has repro platform:windows
主要言語
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

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。