Skip to content

Treat stdio server env variables as secrets like HTTP headers - #342

Draft
jancurn wants to merge 1 commit into
mainfrom
claude/security-issue-341-k4fjo3
Draft

Treat stdio server env variables as secrets like HTTP headers#342
jancurn wants to merge 1 commit into
mainfrom
claude/security-issue-341-k4fjo3

Conversation

@jancurn

@jancurn jancurn commented Jul 28, 2026

Copy link
Copy Markdown
Member

A stdio server's env routinely holds API tokens (directly or via ${VAR} substitution), but only headers were protected. Resolved env values were written to sessions.json in plaintext, printed verbatim by mcpc --json @session, and — not in the issue but worse — passed in the bridge's command line, where ps exposed them. They now follow the exact same path as headers.

  • Stored in the OS keychain (account session:{name}:env), removed with the session
  • Redacted to a <redacted> placeholder in sessions.json and every --json output (documented in the help and docs/REFERENCE.md)
  • Delivered to the bridge over IPC after spawn, never in argv; the bridge merges them back into the stdio transport config, so servers get their environment unchanged
  • Sessions created before this change keep working (their on-disk plaintext is used as is); recreate one to move its values into the keychain
  • New stdio/env-security e2e suite proves the secret is absent from ps, sessions.json, both --json shapes, the bridge log and verbose output, while an echo-env tool confirms it still reaches the server

Fixes #341

https://claude.ai/code/session_01Rmdd458q2Bx68bPxuUtQGa

Base automatically changed from draft to main July 31, 2026 21:05
@jancurn
jancurn force-pushed the claude/security-issue-341-k4fjo3 branch from 47b8799 to b91021f Compare August 2, 2026 11:45
A config entry's `env` routinely holds API tokens — directly or via `${VAR}`
substitution — but only `headers` were protected. Resolved `env` values were
written to `sessions.json` in plaintext, printed verbatim by `mcpc --json
@session` / `connect --json`, and passed to the bridge in its command line,
where `ps` exposed them.

They now follow the exact same path as headers: stored in the OS keychain
(`session:<name>:env`), redacted to `<redacted>` in `sessions.json` and all
`--json` output, and delivered to the bridge over IPC after spawn. The bridge
merges them back into the stdio transport config, so servers still get their
environment unchanged. Sessions written before this change keep working —
their on-disk plaintext is used as is; recreate a session to move its values
into the keychain.

Rebuilt on main after the draft branch was squashed in as #316.

Fixes #341

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Rmdd458q2Bx68bPxuUtQGa
@jancurn
jancurn force-pushed the claude/security-issue-341-k4fjo3 branch from b91021f to 2aaa415 Compare August 6, 2026 09:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

--json session output and sessions.json leak stdio env values in plaintext

3 participants