"use strict";
/**
 * Layer 1: MCP Configuration Audit
 * Detects security issues in MCP configuration files
 *
 * Scans:
 * - mcp.json, *.mcp.json
 * - .mcp/config.json
 * - mcpServers in package.json
 *
 * Detects:
 * - Secrets in MCP config (API keys, tokens in args)
 * - Overpermissive settings (disabled approval, infinite timeouts)
 * - Insecure transport (http:// instead of https://)
 */
Object.defineProperty(exports, "__esModule", { value: true });
exports.detectMCPConfigIssues = detectMCPConfigIssues;
const file_classifier_1 = require("../../parse/file-classifier");
// Base confidence for MCP configuration audit findings
const BASE_CONFIDENCE = 0.50;
// ============================================================================
// Configuration File Detection
// ============================================================================
/**
 * Check if file is an MCP configuration file
 */
function isMCPConfigFile(filePath) {
    const mcpConfigPatterns = [
        /mcp\.json$/i,
        /\.mcp\.json$/i,
        /\.mcp\/config\.json$/i,
        /mcp[-_]?config\.json$/i,
        /claude[-_]?desktop[-_]?config\.json$/i,
    ];
    return mcpConfigPatterns.some(p => p.test(filePath));
}
/**
 * Check if file might contain mcpServers configuration (package.json, etc.)
 */
function mightContainMCPConfig(filePath, content) {
    if (filePath.endsWith('package.json')) {
        return content.includes('mcpServers') || content.includes('mcp');
    }
    if (filePath.endsWith('.json')) {
        return content.includes('mcpServers') || content.includes('"command"') ||
            content.includes('"args"') || content.includes('"url"');
    }
    return false;
}
/**
 * MCP Configuration Security Patterns
 */
const MCP_CONFIG_PATTERNS = [
    // Secrets in args array
    {
        name: 'API key in MCP server args',
        pattern: /"args"\s*:\s*\[[^\]]*(?:api[_-]?key|API[_-]?KEY|apiKey)[=:]["'][^"']+["'][^\]]*\]/gi,
        category: 'ai_mcp_config_secrets',
        baseSeverity: 'critical',
        description: 'API key found in MCP server arguments. Secrets should not be stored in configuration files.',
        suggestedFix: 'Use environment variables for secrets: ["--api-key", "${ANTHROPIC_API_KEY}"] or use a secrets manager.',
    },
    // Secret/token in args
    {
        name: 'Secret token in MCP server args',
        pattern: /"args"\s*:\s*\[[^\]]*(?:secret|token|password|credential|auth)[=:]["'][^"']+["'][^\]]*\]/gi,
        category: 'ai_mcp_config_secrets',
        baseSeverity: 'critical',
        description: 'Secret or token found in MCP server arguments. This could be exposed in logs or version control.',
        suggestedFix: 'Move secrets to environment variables or a secrets manager.',
    },
    // Hardcoded bearer token
    {
        name: 'Bearer token in MCP config',
        pattern: /"(?:auth|authorization|header)"\s*:\s*["'][Bb]earer\s+[A-Za-z0-9_-]+["']/gi,
        category: 'ai_mcp_config_secrets',
        baseSeverity: 'critical',
        description: 'Bearer token hardcoded in MCP configuration. This is a security risk.',
        suggestedFix: 'Use environment variable reference: "Bearer ${MCP_TOKEN}"',
    },
    // Environment variable with actual value (not reference)
    {
        name: 'Environment variable with hardcoded value',
        pattern: /"env"\s*:\s*\{[^}]*(?:KEY|TOKEN|SECRET|PASSWORD)\s*"\s*:\s*"(?!\$\{)[^"]+"/gi,
        category: 'ai_mcp_config_secrets',
        baseSeverity: 'high',
        description: 'Environment variable set to hardcoded secret value in MCP config.',
        suggestedFix: 'Set environment variables outside the config file or use a secrets manager.',
    },
    // Disabled approval requirement
    {
        name: 'Tool approval disabled',
        pattern: /"requireApproval"\s*:\s*false/gi,
        category: 'ai_mcp_config_permissions',
        baseSeverity: 'medium',
        description: 'Tool approval is disabled. AI can execute tools without user confirmation.',
        suggestedFix: 'Enable tool approval for sensitive operations: "requireApproval": true',
    },
    // Auto-approve all
    {
        name: 'Auto-approve all tools',
        pattern: /"autoApprove"\s*:\s*(?:true|"\*"|"all"|\["\*"\])/gi,
        category: 'ai_mcp_config_permissions',
        baseSeverity: 'high',
        description: 'All tools are auto-approved. This bypasses user confirmation for all operations.',
        suggestedFix: 'Limit auto-approval to specific safe tools: "autoApprove": ["read_file", "list_files"]',
    },
    // Infinite or very long timeout
    {
        name: 'Unlimited tool timeout',
        pattern: /"(?:toolTimeout|timeout)"\s*:\s*(?:0|null|"infinite"|999999+)/gi,
        category: 'ai_mcp_config_permissions',
        baseSeverity: 'medium',
        description: 'Tool timeout is disabled or very long. Tools could run indefinitely.',
        suggestedFix: 'Set a reasonable timeout: "toolTimeout": 30000 (30 seconds)',
    },
    // HTTP URL (not HTTPS)
    {
        name: 'Insecure HTTP transport',
        pattern: /"(?:url|endpoint|server)"\s*:\s*"http:\/\/(?!localhost|127\.0\.0\.1)[^"]+"/gi,
        category: 'ai_mcp_config_permissions',
        baseSeverity: 'medium',
        description: 'MCP server uses insecure HTTP transport. Data could be intercepted.',
        suggestedFix: 'Use HTTPS for MCP server URLs: "url": "https://..."',
    },
    // Wildcard allowed tools
    {
        name: 'Wildcard tool permissions',
        pattern: /"(?:allowedTools|tools|permissions)"\s*:\s*(?:\["\*"\]|"\*"|"all")/gi,
        category: 'ai_mcp_config_permissions',
        baseSeverity: 'medium',
        description: 'All tools are allowed without restriction. Consider limiting to specific tools.',
        suggestedFix: 'Explicitly list allowed tools: "allowedTools": ["search", "read_file"]',
    },
    // Privileged mode enabled
    {
        name: 'Privileged mode enabled',
        pattern: /"(?:privileged|sudo|admin|root)"\s*:\s*true/gi,
        category: 'ai_mcp_config_permissions',
        baseSeverity: 'high',
        description: 'MCP server running in privileged mode. This grants elevated permissions.',
        suggestedFix: 'Disable privileged mode unless absolutely necessary. Apply principle of least privilege.',
    },
    // Disabled security features
    {
        name: 'Security feature disabled',
        pattern: /"(?:secure|tls|verify|validation|sandbox)"\s*:\s*false/gi,
        category: 'ai_mcp_config_permissions',
        baseSeverity: 'medium',
        description: 'Security feature is explicitly disabled in MCP configuration.',
        suggestedFix: 'Enable security features: "secure": true, "validation": true',
    },
    // Command injection risk in args
    {
        name: 'Shell command in MCP args',
        pattern: /"args"\s*:\s*\[[^\]]*(?:sh\s+-c|bash\s+-c|cmd\s+\/c|powershell)[^\]]*\]/gi,
        category: 'ai_mcp_config_permissions',
        baseSeverity: 'high',
        description: 'MCP server args contain shell command execution. This is a command injection risk.',
        suggestedFix: 'Avoid shell command execution in MCP args. Use direct command invocation.',
    },
];
// ============================================================================
// Main Detection Function
// ============================================================================
/**
 * Main detection function for MCP configuration audit
 */
function detectMCPConfigIssues(content, filePath, options) {
    const vulnerabilities = [];
    // Skip non-applicable files
    if ((0, file_classifier_1.isScannerOrFixtureFile)(filePath))
        return vulnerabilities;
    if ((0, file_classifier_1.isDocumentationFile)(filePath))
        return vulnerabilities;
    // Only scan MCP config files or files that might contain MCP config
    if (!isMCPConfigFile(filePath) && !mightContainMCPConfig(filePath, content)) {
        return vulnerabilities;
    }
    const lines = options?.parsed?.lines ?? content.split('\n');
    const isTestFile = (0, file_classifier_1.isTestOrMockFile)(filePath);
    const isExample = (0, file_classifier_1.isExampleDirectory)(filePath);
    // Track findings to avoid duplicates
    const seenFindings = new Set();
    for (const pattern of MCP_CONFIG_PATTERNS) {
        const regex = new RegExp(pattern.pattern.source, pattern.pattern.flags);
        let match;
        while ((match = regex.exec(content)) !== null) {
            const lineNumber = content.substring(0, match.index).split('\n').length;
            const lineContent = lines[lineNumber - 1]?.trim() || '';
            // Skip comments
            if ((0, file_classifier_1.isComment)(lineContent))
                continue;
            // Create dedup key
            const dedupKey = `${filePath}:${lineNumber}:${pattern.category}`;
            if (seenFindings.has(dedupKey))
                continue;
            seenFindings.add(dedupKey);
            let severity = pattern.baseSeverity;
            let description = pattern.description;
            const notes = [];
            // Check if value is an environment variable reference (safer)
            if (/\$\{[A-Z_]+\}|\$[A-Z_]+/.test(lineContent)) {
                if (pattern.category === 'ai_mcp_config_secrets') {
                    severity = 'low';
                    notes.push('Uses environment variable reference (safer pattern)');
                }
            }
            // Downgrade test files
            if (isTestFile) {
                severity = 'info';
                notes.push('in test file');
            }
            // Downgrade example/demo directories
            if (isExample && severity !== 'info') {
                severity = 'info';
                notes.push('in example/demo directory');
            }
            // Build final description
            if (notes.length > 0) {
                description += ` (${notes.join('; ')})`;
            }
            vulnerabilities.push({
                id: `mcp-config-${filePath}-${lineNumber}-${pattern.name.replace(/\s+/g, '-')}`,
                filePath,
                lineNumber,
                lineContent,
                severity,
                category: pattern.category,
                title: pattern.name,
                description,
                suggestedFix: pattern.suggestedFix,
                confidence: pattern.category === 'ai_mcp_config_secrets' ? 'high' : 'medium',
                baseConfidence: BASE_CONFIDENCE,
                layer: 1,
                source: 'secrets',
                requiresAIValidation: severity !== 'info' && severity !== 'low',
            });
        }
    }
    return vulnerabilities;
}
//# sourceMappingURL=config-mcp-audit.js.map