security
Audit MCP server configurations to identify hardcoded secrets, tokens in arguments, and shell injection patterns.
Instructions
Audit all MCP server configs for security issues like hardcoded secrets, tokens in args, and shell injection patterns
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
No arguments | |||
Implementation Reference
- src/security.ts:24-87 (handler)The core handler function `checkSecurity` that implements the security checking logic. It iterates over all MCP servers and checks for: hardcoded secrets in env vars (high/medium severity), shell operators in commands (medium severity), missing arguments for npx/node (low severity), and unencrypted HTTP URLs (high severity).
export function checkSecurity(servers: McpServer[]): SecurityIssue[] { const issues: SecurityIssue[] = []; for (const server of servers) { if (server.env) { for (const [key, value] of Object.entries(server.env)) { const isSensitiveName = SECRET_PATTERNS.some((p) => p.test(key)); if (isSensitiveName && value && !value.startsWith("${") && !value.startsWith("$")) { const isHardcoded = HARDCODED_SECRET_PATTERNS.some((p) => p.test(value)); if (isHardcoded) { issues.push({ server, severity: "high", message: `Hardcoded secret in env var "${key}"`, detail: `Value matches known API key pattern. Use environment variables or a secrets manager instead of hardcoding in config.`, }); } else if (value.length > 10) { issues.push({ server, severity: "medium", message: `Possible hardcoded secret in "${key}"`, detail: `Env var name suggests a secret and value appears hardcoded. Consider using $ENV_VAR references.`, }); } } } } if (server.command) { if (server.command.includes("&&") || server.command.includes("|") || server.command.includes(";")) { issues.push({ server, severity: "medium", message: "Command contains shell operators", detail: `Command "${server.command}" uses shell operators which could be a security risk.`, }); } } if (server.type === "stdio" && server.command && (!server.args || server.args.length === 0)) { if (server.command === "npx" || server.command === "node") { issues.push({ server, severity: "low", message: "Command has no arguments", detail: `"${server.command}" is called without arguments — likely misconfigured.`, }); } } if (server.url && server.url.startsWith("http://")) { issues.push({ server, severity: "high", message: "SSE server using unencrypted HTTP", detail: `URL "${server.url}" uses HTTP instead of HTTPS. Data is transmitted in plaintext.`, }); } } return issues; } - src/index.ts:48-66 (registration)The 'security' command is registered as a CLI subcommand using Commander.js. It calls `checkSecurity(servers)` and either prints via `printSecurityIssues` or outputs JSON.
program .command("security") .description("Check MCP configs for security issues") .option("--json", "Output results as JSON") .action(async (opts) => { const servers = await discoverServers(opts.json); if (servers.length === 0) return; if (!opts.json) { const secSpinner = ora("Running security checks...").start(); var issues = checkSecurity(servers); secSpinner.succeed("Security scan complete"); console.log(); printSecurityIssues(issues); } else { const issues = checkSecurity(servers); console.log(JSON.stringify(issues.map(formatSecurityIssue), null, 2)); } }); - src/types.ts:20-25 (schema)The `SecurityIssue` interface defines the shape of security issues: server reference, severity level (high/medium/low), message, and detail.
export interface SecurityIssue { server: McpServer; severity: "high" | "medium" | "low"; message: string; detail: string; } - src/types.ts:1-10 (schema)The `McpServer` interface used by the security handler, containing server fields like type, command, args, url, and env.
export interface McpServer { name: string; source: string; // e.g. "Claude Code (~/.claude.json)" configPath: string; // full path to the config file type: "stdio" | "sse" | "unknown"; command?: string; args?: string[]; url?: string; env?: Record<string, string>; } - src/ui.ts:73-105 (helper)The `printSecurityIssues` helper function that displays security issues in a formatted table to the console.
export function printSecurityIssues(issues: SecurityIssue[]): void { if (issues.length === 0) { console.log(chalk.green(" ✓ No security issues found.\n")); return; } const table = new Table({ head: [ chalk.white("Severity"), chalk.white("Server"), chalk.white("Issue"), ], style: { head: [], border: ["dim"] }, colWidths: [12, 20, 60], wordWrap: true, }); for (const issue of issues) { const sev = issue.severity === "high" ? chalk.red("HIGH") : issue.severity === "medium" ? chalk.yellow("MEDIUM") : chalk.dim("LOW"); table.push([sev, chalk.cyan(issue.server.name), `${issue.message}\n${chalk.dim(issue.detail)}`]); } console.log(table.toString()); console.log( `\n Found ${chalk.yellow(String(issues.length))} issue(s)\n` ); }