1. Acquired OAuth tokens are stored in plaintext in oauth.json
The secret store (OS keychain, with secrets.json/memory fallbacks, #1356/#1950) protects OAuth client secrets, the enterprise IdP client secret, and stdio env: values — but the most sensitive values the Inspector holds never went there. Access, refresh, and ID tokens acquired by completing an OAuth flow, IdP session tokens (EMA), and dynamically registered (DCR) client secrets are all written in plaintext to ~/.mcp-inspector/storage/oauth.json.
Proposal: split oauth.json at the persistence choke point. The file keeps only non-secret state (flow bookkeeping, discovered metadata, public client ids) and acts as the index; token material lives in the secret store, joined back on read. A pre-existing plaintext oauth.json is migrated lazily on first read when the store is durable (under the memory store the file stays authoritative — it is the only durable copy). A new MCP_INSPECTOR_PERSIST_TOKENS=all|access|none variable controls which acquired tokens are persisted at all (access drops refresh tokens; none means re-auth every run; registration client secrets persist regardless).
2. Concurrent clients clobber each other's oauth.json state
Every mutation flushes the client's entire in-memory snapshot over the shared file. A long-lived client holding a stale snapshot (web page, TUI) erases entries other processes wrote since it loaded — e.g. an IdP login completed in the CLI is destroyed by any subsequent web-client auth write (observed in practice).
Proposal: mutation-scoped writes — each mutation names the sections (server entries / IdP sessions) it touched, and the persist layer overlays only those over a fresh locked read of the file. A stale client can no longer destroy entries it didn't touch.
Read-side staleness (a long-lived client not seeing other clients' writes) is a separate, smaller problem and is deliberately out of scope here; it will be addressed after the daemon-cli work merges.
Docs: docs/secret-storage.md, docs/environment-variables.md, README/Docker/CLI-README security wording.
1. Acquired OAuth tokens are stored in plaintext in
oauth.jsonThe secret store (OS keychain, with
secrets.json/memory fallbacks, #1356/#1950) protects OAuth client secrets, the enterprise IdP client secret, and stdioenv:values — but the most sensitive values the Inspector holds never went there. Access, refresh, and ID tokens acquired by completing an OAuth flow, IdP session tokens (EMA), and dynamically registered (DCR) client secrets are all written in plaintext to~/.mcp-inspector/storage/oauth.json.Proposal: split
oauth.jsonat the persistence choke point. The file keeps only non-secret state (flow bookkeeping, discovered metadata, public client ids) and acts as the index; token material lives in the secret store, joined back on read. A pre-existing plaintextoauth.jsonis migrated lazily on first read when the store is durable (under the memory store the file stays authoritative — it is the only durable copy). A newMCP_INSPECTOR_PERSIST_TOKENS=all|access|nonevariable controls which acquired tokens are persisted at all (accessdrops refresh tokens;nonemeans re-auth every run; registration client secrets persist regardless).2. Concurrent clients clobber each other's
oauth.jsonstateEvery mutation flushes the client's entire in-memory snapshot over the shared file. A long-lived client holding a stale snapshot (web page, TUI) erases entries other processes wrote since it loaded — e.g. an IdP login completed in the CLI is destroyed by any subsequent web-client auth write (observed in practice).
Proposal: mutation-scoped writes — each mutation names the sections (server entries / IdP sessions) it touched, and the persist layer overlays only those over a fresh locked read of the file. A stale client can no longer destroy entries it didn't touch.
Read-side staleness (a long-lived client not seeing other clients' writes) is a separate, smaller problem and is deliberately out of scope here; it will be addressed after the daemon-cli work merges.
Docs:
docs/secret-storage.md,docs/environment-variables.md, README/Docker/CLI-README security wording.