Skip to content

fix(security): redact upstream secrets in docker spawn argv debug logs (#712)#713

Merged
Dumbris merged 1 commit into
mainfrom
fix/712-redact-docker-argv-logs
Jun 18, 2026
Merged

fix(security): redact upstream secrets in docker spawn argv debug logs (#712)#713
Dumbris merged 1 commit into
mainfrom
fix/712-redact-docker-argv-logs

Conversation

@Dumbris

@Dumbris Dumbris commented Jun 18, 2026

Copy link
Copy Markdown
Member

Summary

Fixes GH #712: at logging.level: debug, mcpproxy wrote upstream server secrets (Slack/Jira tokens passed as -e KEY=value to docker-command upstreams) in cleartext to ~/Library/Logs/mcpproxy/main.log. Masking was inconsistent — only the shellwrap line was partially handled while several argv-logging sites emitted the full -e KEY=value list.

Fix

  • New shared helper internal/shellwrap/redact.go:
    • RedactDockerArgs([]string) []string — masks the VALUE of docker env flags in an argv slice, leaving keys, flags (run, --rm), and image names untouched. Handles the two-token form (-e, KEY=VALUE), the glued single-token form (-eKEY=VALUE / --env=KEY=VALUE), and the embedded command-string form (the -c arg of a login-shell wrap). Input slice is never mutated.
    • RedactDockerCommandString(string) string — masks -e/--env values inside a single command string (handles quoted tokens).
    • Reuses the existing internal/secret.MaskSecretValue (no import cycle — secret does not import shellwrap).
  • Applied at every argv/command debug log site in the spawn path:
    • shellwrap.WrapWithUserShellwrapped_command + original_args
    • connection_stdio.gooriginal_args (docker-detected), modified_args (injected), final_args + original_args (initialized transport), original_args (wrapWithUserShell)
    • process_unix.go / process_windows.goargs ("Process group configuration applied")

Tests (TDD — failing test written first)

  • internal/shellwrap/redact_test.go: two-token, glued, command-string-element, command-string, no-env-unchanged, input-not-mutated, plus a guard test capturing WrapWithUserShell's zap output to assert no cleartext secret leaks.
  • internal/upstream/core/process_redact_test.go: guard test driving the process-group CommandFunc (off the spawn path, client=nil) for both shell-wrapped and direct-exec forms, asserting no secret in the logged fields.

Acceptance

  • go test -race ./internal/shellwrap/ ./internal/upstream/core/ — green
  • golangci-lint run --config .github/.golangci.yml (v2) — 0 issues
  • GOOS=windows go build ./internal/upstream/core/ — OK
  • A known secret value (xoxc-…) no longer appears in any masked argv/command debug field.

Related #712

At logging.level=debug, docker-command upstreams injected Slack/Jira
tokens as `-e KEY=VALUE` flags that several argv/command log sites
rendered in cleartext to main.log. Masking was inconsistent — only the
shellwrap line was partially handled.

Add a shared redaction helper in internal/shellwrap that masks the VALUE
of docker env flags (`-e`/`--env`) while leaving keys, flags, and image
names intact. It covers the two-token form (`-e`, `KEY=VALUE`), the glued
single-token form (`-eKEY=VALUE`), and the embedded command-string form
(the `-c` argument of a login-shell wrap), reusing secret.MaskSecretValue.

Apply it at every argv/command debug log site in the spawn path:
shellwrap.WrapWithUserShell (wrapped_command + original_args),
connection_stdio.go (original_args/modified_args/final_args), and the
process-group CommandFunc on unix + windows.

Related #712
@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying mcpproxy-docs with  Cloudflare Pages  Cloudflare Pages

Latest commit: c6ffec5
Status: ✅  Deploy successful!
Preview URL: https://5eb5aaac.mcpproxy-docs.pages.dev
Branch Preview URL: https://fix-712-redact-docker-argv-l.mcpproxy-docs.pages.dev

View logs

@codecov-commenter

Copy link
Copy Markdown

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

❌ Patch coverage is 69.38776% with 15 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
internal/shellwrap/redact.go 73.17% 6 Missing and 5 partials ⚠️
internal/upstream/core/connection_stdio.go 20.00% 4 Missing ⚠️

📢 Thoughts on this report? Let us know!

@github-actions

Copy link
Copy Markdown

📦 Build Artifacts

Workflow Run: View Run
Branch: fix/712-redact-docker-argv-logs

Available Artifacts

  • archive-darwin-amd64 (28 MB)
  • archive-darwin-arm64 (25 MB)
  • archive-linux-amd64 (16 MB)
  • archive-linux-arm64 (14 MB)
  • archive-windows-amd64 (28 MB)
  • archive-windows-arm64 (25 MB)
  • frontend-dist-pr (0 MB)
  • installer-dmg-darwin-amd64 (21 MB)
  • installer-dmg-darwin-arm64 (19 MB)

How to Download

Option 1: GitHub Web UI (easiest)

  1. Go to the workflow run page linked above
  2. Scroll to the bottom "Artifacts" section
  3. Click on the artifact you want to download

Option 2: GitHub CLI

gh run download 27743118037 --repo smart-mcp-proxy/mcpproxy-go

Note: Artifacts expire in 14 days.

@mcpproxy-gatekeeper mcpproxy-gatekeeper Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved via Claude Code review: RedactDockerArgs/RedactDockerCommandString covers two-token, glued (-eKEY=, --env=), and embedded command-string forms; preserves keys/quotes; reuses secret.MaskSecretValue; nil-safe & non-mutating. Applied at all 4 leaking log sites. CI fully green (0 fail). Verified for GH #712.

@Dumbris Dumbris merged commit eba4a85 into main Jun 18, 2026
36 checks passed
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.

2 participants