From 99643d3993dcb394941a50c4c9d5a2a64f3268cb Mon Sep 17 00:00:00 2001 From: "anthropic-code-agent[bot]" <242468646+Claude@users.noreply.github.com> Date: Tue, 10 Feb 2026 14:52:29 +0000 Subject: [PATCH 1/2] Initial plan From 1a0a54964634f863c30e7994b9503799d26c00fd Mon Sep 17 00:00:00 2001 From: "anthropic-code-agent[bot]" <242468646+Claude@users.noreply.github.com> Date: Tue, 10 Feb 2026 14:58:33 +0000 Subject: [PATCH 2/2] Sanitize all log outputs to prevent auth token exposure - Fix env passthrough logging to use TruncateSecret instead of custom truncation - Sanitize session IDs in transport.go HTTP connection logs - Sanitize request/response bodies in http_helpers.go and transport.go - Sanitize tool call arguments and results in unified.go - Sanitize stderr output from backend MCP servers in connection.go - All changes use existing sanitize.SanitizeString() and sanitize.TruncateSecret() - Tests pass, build succeeds Co-authored-by: lpcox <15877973+lpcox@users.noreply.github.com> --- internal/launcher/log_helpers.go | 6 +----- internal/mcp/connection.go | 10 ++++++---- internal/server/http_helpers.go | 10 +++++++--- internal/server/transport.go | 6 ++++-- internal/server/unified.go | 10 +++++++--- 5 files changed, 25 insertions(+), 17 deletions(-) diff --git a/internal/launcher/log_helpers.go b/internal/launcher/log_helpers.go index 3d42bab9..86866060 100644 --- a/internal/launcher/log_helpers.go +++ b/internal/launcher/log_helpers.go @@ -54,11 +54,7 @@ func (l *Launcher) logEnvPassthrough(args []string) { if !strings.Contains(nextArg, "=") { // This is a passthrough variable, check if it exists in our environment if val := os.Getenv(nextArg); val != "" { - displayVal := val - if len(val) > 10 { - displayVal = val[:10] + "..." - } - log.Printf("[LAUNCHER] ✓ Env passthrough: %s=%s (from MCPG process)", nextArg, displayVal) + log.Printf("[LAUNCHER] ✓ Env passthrough: %s=%s (from MCPG process)", nextArg, sanitize.TruncateSecret(val)) } else { log.Printf("[LAUNCHER] ✗ WARNING: Env passthrough for %s requested but NOT FOUND in MCPG process", nextArg) } diff --git a/internal/mcp/connection.go b/internal/mcp/connection.go index 269056cb..c515fa9c 100644 --- a/internal/mcp/connection.go +++ b/internal/mcp/connection.go @@ -212,8 +212,9 @@ func NewConnection(ctx context.Context, serverID, command string, args []string, scanner := bufio.NewScanner(stderrPipeReader) for scanner.Scan() { line := scanner.Text() - logger.LogInfoWithServer(serverID, "backend", "[stderr] %s", line) - logConn.Printf("[%s stderr] %s", serverID, line) + sanitizedLine := sanitize.SanitizeString(line) + logger.LogInfoWithServer(serverID, "backend", "[stderr] %s", sanitizedLine) + logConn.Printf("[%s stderr] %s", serverID, sanitizedLine) } }() @@ -239,9 +240,10 @@ func NewConnection(ctx context.Context, serverID, command string, args []string, // Log captured stderr output from the container/process stderrOutput := strings.TrimSpace(stderrBuf.String()) if stderrOutput != "" { - logger.LogErrorMd("backend", "MCP backend stderr output:\n%s", stderrOutput) + sanitizedStderr := sanitize.SanitizeString(stderrOutput) + logger.LogErrorMd("backend", "MCP backend stderr output:\n%s", sanitizedStderr) log.Printf(" 📋 Container/Process stderr output:") - for _, line := range strings.Split(stderrOutput, "\n") { + for _, line := range strings.Split(sanitizedStderr, "\n") { log.Printf(" %s", line) } } diff --git a/internal/server/http_helpers.go b/internal/server/http_helpers.go index cd70ec91..ad5b26d3 100644 --- a/internal/server/http_helpers.go +++ b/internal/server/http_helpers.go @@ -9,6 +9,7 @@ import ( "github.com/github/gh-aw-mcpg/internal/auth" "github.com/github/gh-aw-mcpg/internal/logger" + "github.com/github/gh-aw-mcpg/internal/logger/sanitize" "github.com/github/gh-aw-mcpg/internal/mcp" ) @@ -52,13 +53,16 @@ func logHTTPRequestBody(r *http.Request, sessionID, backendID string) { logHelpers.Printf("Request body read: size=%d bytes, sessionID=%s, backendID=%s", len(bodyBytes), sessionID, backendID) + // Sanitize the body before logging + sanitizedBody := sanitize.SanitizeString(string(bodyBytes)) + // Log with backend context if provided (routed mode) if backendID != "" { - logger.LogDebug("client", "MCP client request body, backend=%s, body=%s", backendID, string(bodyBytes)) + logger.LogDebug("client", "MCP client request body, backend=%s, body=%s", backendID, sanitizedBody) } else { - logger.LogDebug("client", "MCP request body, session=%s, body=%s", sessionID, string(bodyBytes)) + logger.LogDebug("client", "MCP request body, session=%s, body=%s", sessionID, sanitizedBody) } - log.Printf("Request body: %s", string(bodyBytes)) + log.Printf("Request body: %s", sanitizedBody) // Restore body for subsequent reads r.Body = io.NopCloser(bytes.NewBuffer(bodyBytes)) diff --git a/internal/server/transport.go b/internal/server/transport.go index a44474e3..5fc6a0dd 100644 --- a/internal/server/transport.go +++ b/internal/server/transport.go @@ -7,6 +7,7 @@ import ( "time" "github.com/github/gh-aw-mcpg/internal/logger" + "github.com/github/gh-aw-mcpg/internal/logger/sanitize" sdk "github.com/modelcontextprotocol/go-sdk/mcp" ) @@ -49,7 +50,8 @@ func withResponseLogging(handler http.Handler) http.Handler { lw := newResponseWriter(w) handler.ServeHTTP(lw, r) if len(lw.Body()) > 0 { - log.Printf("[%s] %s %s - Status: %d, Response: %s", r.RemoteAddr, r.Method, r.URL.Path, lw.StatusCode(), string(lw.Body())) + sanitizedBody := sanitize.SanitizeString(string(lw.Body())) + log.Printf("[%s] %s %s - Status: %d, Response: %s", r.RemoteAddr, r.Method, r.URL.Path, lw.StatusCode(), sanitizedBody) } }) } @@ -86,7 +88,7 @@ func CreateHTTPServerForMCP(addr string, unifiedServer *UnifiedServer, apiKey st logger.LogInfo("client", "MCP connection established, remote=%s, method=%s, path=%s, session=%s", r.RemoteAddr, r.Method, r.URL.Path, sessionID) log.Printf("=== NEW STREAMABLE HTTP CONNECTION ===") log.Printf("[%s] %s %s", r.RemoteAddr, r.Method, r.URL.Path) - log.Printf("Authorization (Session ID): %s", sessionID) + log.Printf("Authorization (Session ID): %s", sanitize.TruncateSecret(sessionID)) log.Printf("DEBUG: About to check request body, Method=%s, Body!=nil: %v", r.Method, r.Body != nil) diff --git a/internal/server/unified.go b/internal/server/unified.go index db71ed93..afc85b9e 100644 --- a/internal/server/unified.go +++ b/internal/server/unified.go @@ -15,6 +15,7 @@ import ( "github.com/github/gh-aw-mcpg/internal/guard" "github.com/github/gh-aw-mcpg/internal/launcher" "github.com/github/gh-aw-mcpg/internal/logger" + "github.com/github/gh-aw-mcpg/internal/logger/sanitize" "github.com/github/gh-aw-mcpg/internal/mcp" "github.com/github/gh-aw-mcpg/internal/middleware" "github.com/github/gh-aw-mcpg/internal/sys" @@ -326,7 +327,8 @@ func (us *UnifiedServer) registerToolsFromBackend(serverID string) error { // Log the MCP tool call request sessionID := us.getSessionID(ctx) argsJSON, _ := json.Marshal(toolArgs) - logger.LogInfo("client", "MCP tool call request, session=%s, tool=%s, args=%s", sessionID, toolNameCopy, string(argsJSON)) + sanitizedArgs := sanitize.SanitizeString(string(argsJSON)) + logger.LogInfo("client", "MCP tool call request, session=%s, tool=%s, args=%s", sessionID, toolNameCopy, sanitizedArgs) // Check session is initialized if err := us.requireSession(ctx); err != nil { @@ -341,7 +343,8 @@ func (us *UnifiedServer) registerToolsFromBackend(serverID string) error { logger.LogError("client", "MCP tool call error, session=%s, tool=%s, error=%v", sessionID, toolNameCopy, err) } else { resultJSON, _ := json.Marshal(data) - logger.LogInfo("client", "MCP tool call response, session=%s, tool=%s, result=%s", sessionID, toolNameCopy, string(resultJSON)) + sanitizedResult := sanitize.SanitizeString(string(resultJSON)) + logger.LogInfo("client", "MCP tool call response, session=%s, tool=%s, result=%s", sessionID, toolNameCopy, sanitizedResult) } return result, data, err @@ -440,7 +443,8 @@ func (us *UnifiedServer) registerSysTools() error { } resultJSON, _ := json.Marshal(result) - logger.LogInfo("client", "MCP session initialization complete, session=%s, result=%s", sessionID, string(resultJSON)) + sanitizedResult := sanitize.SanitizeString(string(resultJSON)) + logger.LogInfo("client", "MCP session initialization complete, session=%s, result=%s", sessionID, sanitizedResult) return nil, result, nil }