claude mcp add --header exposes Authorization/Bearer token value in stdout

Status Fixed / completed
Reported on v2.1.128
Maintainer reply ✓ Yes — localden
Activity 3 comments · opened Jul 18, 2026 · closed Jul 20, 2026
💡 Likely answer: A maintainer (localden, collaborator) responded on this thread — see the highlighted reply below.

Bug summary

claude mcp add --transport http <name> <url> --header "Authorization: Bearer <token>" prints the header value verbatim to stdout, exposing the secret in terminal history and any log/transcript that captures the session.

Reproduction

claude mcp add --transport http my-server https://example.com/mcp --header "Authorization: Bearer secret-token-123"

Output includes the raw header value on stdout:

"Authorization": "Bearer secret-token-123"
}
File modified: /path/to/.claude.json

Expected behavior

The header value should be masked (e.g. "Authorization": "Bearer ***") or omitted entirely from stdout, similar to how claude mcp add --client-secret (interactive prompt) handles secrets. The token is still correctly stored in .claude.json — the issue is only the echo to stdout.

Actual behavior

Full token value printed to stdout. Anyone who reviews the terminal buffer, tmux buffer, screen recording, session transcript, or agent conversation log can extract the raw secret.

Impact

  • High in agent-driven workflows: any AI agent (Claude Code itself, or an external orchestrator running the CLI) that executes claude mcp add captures the leaked token in its conversation transcript. If that transcript is shared, uploaded for debugging, or ingested by other systems, the token propagates.
  • Token rotation is the only mitigation once the leak happens.

Environment

  • Claude Code CLI version: 2.1.128
  • OS: Windows 11 (behavior is not OS-specific — the print happens in the config-write confirmation path)
  • Shell: PowerShell / Git Bash

Suggested fix

Detect sensitive header names (Authorization, X-Api-Key, X-Auth-Token, Cookie, etc.) in --header values before printing config confirmation, and mask the value. Alternatively, support a --header-env VAR_NAME flag that reads from an env var and never prints the resolved value.

Related

Common pattern in other CLIs: curl -v masks auth by default in newer versions; gh auth login never echoes tokens; docker login --password-stdin avoids the same issue by reading from stdin.

View original on GitHub ↗

3 Comments

0xbrainkid · 2 months ago

This is worth treating as an agent-boundary leak, not just a CLI formatting bug.

In human-only use, stdout is often ephemeral. In agent-driven workflows, stdout becomes durable context: copied into transcripts, logs, reviews, task memories, and sometimes secondary model calls. Once an MCP bearer token lands there, the blast radius is larger than the terminal session that ran the command.

A clean fix would separate the stored config from the displayed confirmation:

  • redact sensitive header values before any stdout/stderr rendering
  • avoid echoing resolved values for env-backed secrets
  • add a regression fixture that runs mcp add --header "Authorization: Bearer test-secret" and asserts the secret never appears in stdout, stderr, or structured confirmation output
  • ideally emit a stable non-secret fingerprint so users can verify which header was set without exposing the credential

That last bit matters for auditability. Operators need evidence that the MCP server was configured, but the evidence should prove the binding shape, not disclose the bearer material.

This maps closely to the AgentFolio/SATP framing we keep using: authorization can stay local to the tool/runtime, but provenance and receipts need to be safe to share. A receipt that contains the credential is not a receipt; it is another secret store.

localden collaborator · 2 months ago

This was fixed in v2.1.161: the claude mcp add confirmation now redacts sensitive header values (Authorization, API keys, cookies) instead of echoing them. You're on 2.1.128, so upgrading past 2.1.161 stops the token from being printed. Any token that already hit a transcript should be rotated. Reopen with the version and command output if you still see the raw value on 2.1.161 or later.

github-actions[bot] · 28 days ago

This issue has been automatically locked since it was closed and has not had any activity for 7 days. If you're experiencing a similar issue, please file a new issue and reference this one if it's relevant.