`claude mcp list` prints expanded `${ENV}` values in plain text, leaking secrets to terminal/scrollback/ps

Resolved 💬 2 comments Opened May 27, 2026 by qveys Closed Jun 28, 2026

Preflight Checklist

  • [x] I have searched existing issues 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?

When a plugin's .mcp.json references env vars (e.g. "-e", "TFE_TOKEN=${TFE_TOKEN}"), claude mcp list expands those ${VAR} placeholders and prints the literal secret value in the output.

Example output (token redacted for this report — the original was full clear-text):

plugin:terraform:terraform: docker run -i --rm -e TFE_TOKEN=Gas...XXXX hashicorp/terraform-mcp-server:0.4.0 - ✗ Failed to connect

This leaks the secret to:

  • the terminal scrollback
  • any pasted bug report, screen share, or log capture (this is exactly how I noticed the issue — while sharing diagnostic output with Claude itself)
  • ps auxww once the docker container actually runs, since the args including the literal token become part of the process command line and are visible to every user on the host

The user did the "right thing" — the token is stored in macOS Keychain and injected only at claude launch via a shell wrapper that calls security find-generic-password. Despite that, claude mcp list defeats the precaution by interpolating and printing the value.

What Should Happen

claude mcp list should display the unexpanded form (${TFE_TOKEN}) — or a redacted placeholder such as <redacted> — for any value that originates from an env-var reference in .mcp.json. Resolution should only happen at MCP-server-launch time, not at list-render time.

Steps to Reproduce

  1. Install a plugin whose .mcp.json references an env var. The official terraform plugin in the claude-plugins-official marketplace is one example:

``json
{
"terraform": {
"command": "docker",
"args": ["run", "-i", "--rm", "-e", "TFE_TOKEN=${TFE_TOKEN}",
"hashicorp/terraform-mcp-server:0.4.0"]
}
}
``

  1. Export TFE_TOKEN in the shell that launches claude (any source — direct export, .zshrc, or a Keychain-loading wrapper).
  2. Run claude mcp list.
  3. Observe the literal token in the output where ${TFE_TOKEN} was declared.

Related Concern (worth surfacing in plugin authoring docs)

Even if claude mcp list is fixed, the docker run -e KEY=VALUE (with an explicit =VALUE) pattern still leaks the resolved value to ps. Plugin authors should be guided toward "-e", "KEY" (no =) so docker inherits the value from the parent env without putting the literal in the container's command line / process args. The terraform plugin's current .mcp.json is an example that would benefit from this change.

Claude Code Version

2.1.152

Platform

macOS (Anthropic API)

Operating System

macOS (Darwin 25.5.0)

Terminal/Shell

zsh

Additional Information

The same expansion behavior is reasonable inside a launched MCP process (it must see the resolved value), but should not be reflected in claude mcp list, /mcp dialog, or any diagnostic command that a user would naturally share when debugging.

View original on GitHub ↗

This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗