fix(security): redact upstream secrets in docker spawn argv debug logs (#712)#713
Merged
Conversation
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
Deploying mcpproxy-docs with
|
| 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 |
|
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
📦 Build ArtifactsWorkflow Run: View Run Available Artifacts
How to DownloadOption 1: GitHub Web UI (easiest)
Option 2: GitHub CLI gh run download 27743118037 --repo smart-mcp-proxy/mcpproxy-go
|
There was a problem hiding this comment.
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes GH #712: at
logging.level: debug, mcpproxy wrote upstream server secrets (Slack/Jira tokens passed as-e KEY=valueto 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=valuelist.Fix
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-carg of a login-shell wrap). Input slice is never mutated.RedactDockerCommandString(string) string— masks-e/--envvalues inside a single command string (handles quoted tokens).internal/secret.MaskSecretValue(no import cycle —secretdoes not importshellwrap).shellwrap.WrapWithUserShell→wrapped_command+original_argsconnection_stdio.go→original_args(docker-detected),modified_args(injected),final_args+original_args(initialized transport),original_args(wrapWithUserShell)process_unix.go/process_windows.go→args("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 capturingWrapWithUserShell's zap output to assert no cleartext secret leaks.internal/upstream/core/process_redact_test.go: guard test driving the process-groupCommandFunc(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/— greengolangci-lint run --config .github/.golangci.yml(v2) — 0 issuesGOOS=windows go build ./internal/upstream/core/— OKxoxc-…) no longer appears in any masked argv/command debug field.Related #712