fix(skill-mcp): redact sensitive data from connection errors

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
YeonGyu-Kim
2026-04-08 13:10:06 +09:00
parent 7751402999
commit b81fdef5d9
2 changed files with 53 additions and 2 deletions
@@ -0,0 +1,47 @@
// Redacts sensitive tokens from error messages to prevent credential exposure
// Follows same patterns as env-cleaner.ts for consistency
const SENSITIVE_PATTERNS: RegExp[] = [
// API keys and tokens in common formats
/[a-zA-Z0-9_-]*(?:api[_-]?key|apikey)["\s]*[:=]["\s]*([a-zA-Z0-9_-]{16,})/gi,
/[a-zA-Z0-9_-]*(?:auth[_-]?token|authtoken)["\s]*[:=]["\s]*([a-zA-Z0-9_-]{16,})/gi,
/[a-zA-Z0-9_-]*(?:access[_-]?token|accesstoken)["\s]*[:=]["\s]*([a-zA-Z0-9_-]{16,})/gi,
/[a-zA-Z0-9_-]*(?:secret)["\s]*[:=]["\s]*([a-zA-Z0-9_-]{16,})/gi,
/[a-zA-Z0-9_-]*(?:password)["\s]*[:=]["\s]*([a-zA-Z0-9_-]{8,})/gi,
// Bearer tokens
/bearer\s+([a-zA-Z0-9_-]{20,})/gi,
// Common token prefixes
/sk-[a-zA-Z0-9]{20,}/g, // OpenAI-style secret keys
/gh[pousr]_[a-zA-Z0-9]{20,}/gi, // GitHub tokens
/glpat-[a-zA-Z0-9_-]{20,}/gi, // GitLab tokens
/[A-Za-z0-9_]{20,}-[A-Za-z0-9_]{10,}-[A-Za-z0-9_]{10,}/g, // Common JWT-like patterns
]
const REDACTION_MARKER = "[REDACTED]"
/**
* Redacts sensitive tokens from a string.
* Used for error messages that may contain command-line arguments or environment info.
*/
export function redactSensitiveData(input: string): string {
let result = input
for (const pattern of SENSITIVE_PATTERNS) {
result = result.replace(pattern, REDACTION_MARKER)
}
return result
}
/**
* Redacts sensitive data from an Error object, returning a new Error.
* Preserves the stack trace but redacts the message.
*/
export function redactErrorSensitiveData(error: Error): Error {
const redactedMessage = redactSensitiveData(error.message)
const redactedError = new Error(redactedMessage)
redactedError.stack = error.stack ? redactSensitiveData(error.stack) : undefined
return redactedError
}
@@ -3,6 +3,7 @@ import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js"
import type { ClaudeCodeMcpServer } from "../claude-code-mcp-loader/types"
import { createCleanMcpEnvironment } from "./env-cleaner"
import { registerProcessCleanup, startCleanupTimer } from "./cleanup"
import { redactSensitiveData } from "./error-redaction"
import type { ManagedClient, SkillMcpClientConnectionParams } from "./types"
function getStdioCommand(config: ClaudeCodeMcpServer, serverName: string): string {
@@ -45,10 +46,13 @@ export async function createStdioClient(params: SkillMcpClientConnectionParams):
}
const errorMessage = error instanceof Error ? error.message : String(error)
const fullCommand = `${command} ${args.join(" ")}`
const safeCommand = redactSensitiveData(fullCommand)
const safeErrorMessage = redactSensitiveData(errorMessage)
throw new Error(
`Failed to connect to MCP server "${info.serverName}".\n\n` +
`Command: ${command} ${args.join(" ")}\n` +
`Reason: ${errorMessage}\n\n` +
`Command: ${safeCommand}\n` +
`Reason: ${safeErrorMessage}\n\n` +
`Hints:\n` +
` - Ensure the command is installed and available in PATH\n` +
` - Check if the MCP server package exists\n` +