anthropics / anthropics/claude-code
[BUG] mcp-needs-auth-cache.json is shared across CLAUDE_SECURESTORAGE_CONFIG_DIR profiles — one account's auth failure blocks the other's MCP servers
- Vorherrschende Sprache
- Python
- Sterne
- 145k
- Forks
- 23.1k
- PR-Merge-Kennzahlen
- PR-Kennzahlen ausstehend
Beschreibung
## Environment
- Claude Code: 2.1.234 (native install)
- Platform: macOS (Darwin 27.0.0)
- Two accounts on one machine, split via `CLAUDE_SECURESTORAGE_CONFIG_DIR`
## Summary
`CLAUDE_SECURESTORAGE_CONFIG_DIR` correctly namespaces credential storage — each profile gets its own Keychain item (`Claude Code-credentials` vs `Claude Code-credentials-`). But `~/.claude/mcp-needs-auth-cache.json` is **not** namespaced: both profiles read and write the same file.
The cache is keyed by server name only, with a 15-minute TTL during which new processes skip the MCP connection attempt entirely (see #48670). Since claude.ai connector server names are identical across accounts ("claude.ai Teamwork", "claude.ai Figma", …), a needs-auth entry written by profile A blocks profile B from even attempting to connect — despite profile B holding a valid token in its own Keychain item.
## Repro
1. Set up two accounts:
- Profile A: plain `claude` (default securestorage)
- Profile B: `CLAUDE_SECURESTORAGE_CONFIG_DIR=internal claude`
2. Authenticate a claude.ai connector (e.g. Teamwork) on profile B; leave it unauthenticated/expired on profile A.
3. Start a session as profile A → the connector fails auth → entry written to the shared `~/.claude/mcp-needs-auth-cache.json`.
4. Within 15 minutes, start a session as profile B.
**Expected:** profile B connects — its Keychain item has a valid token.
**Actual:** profile B skips the connection ("cached needs-auth") and reports the server as requiring authentication.
## Impact
- Worst for SDK/headless consumers (`sdk-ts` entrypoint, agent hosts): they can't run `/mcp` interactively, so within the TTL window there is no in-session recovery. Combined with the cross-profile poisoning, alternating between two accounts makes MCP auth appear to "never stick" — each profile's failures continuously re-poison the other.
- Interactive sessions show misleading "needs authentication" status for servers that are actually fine for the current profile.
## Workaround
`rm -f ~/.claude/mcp-needs-auth-cache.json` after re-authenticating, before starting the next (SDK) session.
## Suggested fix
Namespace the needs-auth cache by the same securestorage profile hash already used for the Keychain service name — e.g. `mcp-needs-auth-cache-.json`, or include the profile hash in each cache key. Alternatively, on cache hit, cheaply verify that a credential for that server exists in the *current* profile's storage before trusting the cached needs-auth verdict.
## Related
- #48670 — needs-auth cache blocks SDK reconnection after successful re-auth (single profile; closed not-planned). This issue is the multi-profile variant: the cache isn't just stale, it's shared across identities.
- #80635, #78220 — other cases of the cache being keyed too coarsely (by server name only)
- #79223 — `CLAUDE_SECURESTORAGE_CONFIG_DIR` documentation request
Beitragsleitfaden
Für dieses Repository ist kein Beitragsleitfaden indexiert
Rechercherichtung
Start by tracing the code that reads and writes ~/.claude/mcp-needs-auth-cache.json, then compare it with the profile hash used for Keychain service names under CLAUDE_SECURESTORAGE_CONFIG_DIR. Reproduce the two-profile sequence, including the sdk-ts entrypoint. Done means one profile's needs-auth result cannot block the other, with regression coverage for the isolated cache behavior.
Vom Indexierungsmodell aus dem Issue-Text verfasst.
Bewertung
- Tech-Stack
- python
- Bereich
- authentication, cli
- Issue-Typ
- Bug
- Schwierigkeit
- 4/5
- Geschätzter Aufwand
- 3-5 Tage
- Aktivitätsstatus
- Aktiv
- Klarheit
- Größtenteils klar
- Anfängerfreundlichkeit
- 52/100