"use strict";
/**
 * Layer 2: AI Code Fingerprinting
 * Detects patterns commonly found in AI-generated code that may indicate security risks
 */
Object.defineProperty(exports, "__esModule", { value: true });
exports.detectAIFingerprints = detectAIFingerprints;
const context_helpers_1 = require("../utils/context-helpers");
const environment_context_1 = require("../utils/environment-context");
const AI_FINGERPRINTS = [
    // ==================== Placeholder/TODO patterns - downgraded ====================
    {
        name: 'AI placeholder comment',
        pattern: /\/\/\s*(TODO|FIXME|XXX|HACK):\s*(implement|add|replace|update|fix)\s+(this|here|later|authentication|validation|error handling)/gi,
        severity: 'low', // Downgraded from medium - often harmless or addressed
        description: 'AI-generated placeholder that may indicate incomplete implementation',
        suggestedFix: 'Complete the implementation before deploying',
        confidence: 'low', // Downgraded
    },
    {
        name: 'Placeholder implementation',
        // More specific: only match "placeholder implementation/code/function" not just "placeholder" in any context
        pattern: /\/\/\s*placeholder\s+(implementation|code|function|method|logic|here)|\/\/\s*stub\s+(implementation|code|function|method)|\/\/\s*mock\s+implementation|\/\/\s*temporary\s+(implementation|code|fix|hack|workaround)/gi,
        severity: 'low', // Downgraded from medium
        description: 'Placeholder code that should be replaced with real implementation',
        suggestedFix: 'Replace placeholder with actual implementation',
        confidence: 'low', // Downgraded
    },
    // ==================== Overly permissive patterns ====================
    {
        name: 'AI catch-all error handler',
        pattern: /catch\s*\([^)]*\)\s*\{\s*(console\.(log|error)|\/\/\s*handle)/gi,
        severity: 'info', // Downgraded from low - this is standard practice
        description: 'Generic error handling pattern - consider more specific handling',
        suggestedFix: 'Add specific error handling based on error types',
        confidence: 'low', // Downgraded
    },
    {
        name: 'AI permissive CORS',
        pattern: /cors\s*\(\s*\)|Access-Control-Allow-Origin['": ]*\*/gi,
        severity: 'medium', // Downgraded from high - often intentional in dev
        description: 'Overly permissive CORS configuration - verify if intentional',
        suggestedFix: 'Restrict CORS to specific trusted origins in production',
        confidence: 'medium', // Downgraded
    },
    // NOTE: 'any' type detection is now handled by detectSmartAnyUsage() function below
    // This prevents overwhelming noise from internal utility 'any' usage
    // ==================== Incomplete security patterns - heavily downgraded ====================
    {
        name: 'AI incomplete validation',
        pattern: /if\s*\(\s*!?\s*(input|data|value|body|params)\s*\)\s*\{?\s*(return|throw)/gi,
        severity: 'info', // Downgraded from low - this is often fine
        description: 'Basic existence check - consider adding type validation if needed',
        suggestedFix: 'Add comprehensive input validation with type and format checks',
        confidence: 'low',
    },
    // NOTE: Removed 'AI basic auth check' pattern entirely - too many false positives
    // Basic auth checks like if (!user) return are correct and common
    // ==================== AI-specific comment patterns - suppressed (style only) ====================
    // NOTE: Removed 'AI explanatory comment' pattern - verbose comments are style, not security
    // NOTE: Removed 'AI step-by-step comment' pattern - step comments are style, not security
    // ==================== Dangerous AI patterns ====================
    {
        name: 'AI hardcoded secret pattern',
        pattern: /const\s+(API_KEY|SECRET|PASSWORD|TOKEN)\s*=\s*['"][^'"]+['"]/gi,
        severity: 'critical',
        description: 'Hardcoded secret - common mistake in AI-generated code',
        suggestedFix: 'Move secrets to environment variables',
        confidence: 'high',
    },
    {
        name: 'AI example credentials',
        pattern: /(admin|test|demo|example|sample|your)[_-]?(password|secret|key|token)\s*[=:]\s*['"][^'"]+['"]/gi,
        severity: 'high',
        description: 'Example/placeholder credentials that should be replaced',
        suggestedFix: 'Replace example credentials with proper secret management',
        confidence: 'high',
    },
    // NOTE: localhost/example URL detection moved to special handling below
    // to allow context-aware skipping for config/example files
    // ==================== AI code smell patterns - REMOVED ====================
    // NOTE: The following patterns have been REMOVED as they are style/code quality issues,
    // not security vulnerabilities. Reporting these creates excessive noise:
    // - 'AI console.log debugging' - debug logs are standard development practice
    // - 'AI empty function body' - empty functions may be intentional stubs/callbacks
    // - 'AI magic number' - magic numbers are code quality, not security
    // ==================== AI boilerplate patterns - REMOVED ====================
    // NOTE: Generic error messages are intentionally vague to avoid information leakage.
    // Flagging "Something went wrong" as an issue is counterproductive - it's often the
    // correct security-conscious approach. These patterns have been removed.
    // ==================== AI security bypass patterns - moderated ====================
    {
        name: 'AI disabled security for testing',
        pattern: /\/\/\s*(disable|skip|bypass|ignore)\s*(for\s+)?(testing|development|now|temporarily)/gi,
        severity: 'medium', // Downgraded from high - often intentional in dev
        description: 'Security may be disabled for testing - verify production config',
        suggestedFix: 'Remove testing bypasses and implement proper security',
        confidence: 'medium', // Downgraded
    },
    {
        name: 'AI TODO security',
        pattern: /\/\/\s*TODO:\s*(add|implement|fix)\s*(security|auth|validation|sanitization)/gi,
        severity: 'low', // Downgraded from high - often outdated or already addressed
        description: 'Security feature marked as TODO - verify if addressed',
        suggestedFix: 'Implement the security feature or remove if already done',
        confidence: 'low', // Downgraded
    },
];
/**
 * Check if 'any' usage is a safe/common ORM pattern that should be ignored
 */
function isSafeORMPattern(line) {
    const safePatterns = [
        // Dexie/IndexedDB patterns
        /\.equals\s*\(\s*null\s+as\s+any/i,
        /\.equals\s*\(\s*\d+\s+as\s+any/i,
        /\.equals\s*\(\s*['"`][^'"`]*['"`]\s+as\s+any/i,
        /\.where\s*\(\s*.*as\s+any\s*\)/i,
        /\.filter\s*\(\s*.*as\s+any\s*\)/i,
        // Prisma patterns
        /prisma\.\w+\.findMany/i,
        /prisma\.\w+\.findFirst/i,
        /prisma\.\w+\.findUnique/i,
        // Supabase patterns
        /supabase\.from\s*\(/i,
        // Internal array maps over DB records (not untrusted input)
        /\.map\s*\(\s*\(\s*\w+\s*:\s*any\s*\)\s*=>/i,
        /\.filter\s*\(\s*\(\s*\w+\s*:\s*any\s*\)\s*=>/i,
        /\.forEach\s*\(\s*\(\s*\w+\s*:\s*any\s*\)\s*=>/i,
        /\.reduce\s*\(\s*\(\s*\w+\s*,\s*\w+\s*:\s*any\s*\)\s*=>/i,
        // Type coercion for internal data
        /\[\s*\d+\s*\]\s+as\s+any/, // Array index access
        /\.data\s+as\s+any/i, // .data as any (common ORM pattern)
        /\.result\s+as\s+any/i, // .result as any
        /\.rows?\s+as\s+any/i, // .row or .rows as any
        /\.records?\s+as\s+any/i, // .record or .records as any
    ];
    return safePatterns.some(p => p.test(line));
}
/**
 * Check if 'any' usage is in a browser API event handler (safe pattern)
 * These APIs often have incomplete TypeScript typings and require 'any' as a workaround
 */
function isBrowserAPIEventHandler(line, filePath) {
    // Skip if this is likely a server-side file
    if (/\/(api|server|backend|lib\/supabase)\//i.test(filePath)) {
        return false;
    }
    const browserAPIPatterns = [
        // Web Speech API (SpeechRecognition)
        /\.onresult\s*=\s*\(?.*:\s*any/i,
        /\.onerror\s*=\s*\(?.*:\s*any/i,
        /\.onend\s*=\s*\(?.*:\s*any/i,
        /\.onstart\s*=\s*\(?.*:\s*any/i,
        /\.onaudiostart\s*=\s*\(?.*:\s*any/i,
        /\.onaudioend\s*=\s*\(?.*:\s*any/i,
        /\.onspeechstart\s*=\s*\(?.*:\s*any/i,
        /\.onspeechend\s*=\s*\(?.*:\s*any/i,
        /speechRecognition/i,
        /SpeechRecognition/i,
        /webkitSpeechRecognition/i,
        // MediaRecorder / Media APIs
        /\.ondataavailable\s*=\s*\(?.*:\s*any/i,
        /\.onstop\s*=\s*\(?.*:\s*any/i,
        /\.onpause\s*=\s*\(?.*:\s*any/i,
        /\.onresume\s*=\s*\(?.*:\s*any/i,
        /mediaRecorder/i,
        /MediaRecorder/i,
        /MediaStream/i,
        /getUserMedia/i,
        // WebSocket events
        /\.onopen\s*=\s*\(?.*:\s*any/i,
        /\.onclose\s*=\s*\(?.*:\s*any/i,
        /\.onmessage\s*=\s*\(?.*:\s*any/i,
        /webSocket/i,
        /WebSocket/i,
        // WebRTC / PeerConnection
        /\.onicecandidate\s*=\s*\(?.*:\s*any/i,
        /\.ontrack\s*=\s*\(?.*:\s*any/i,
        /\.onnegotiationneeded\s*=\s*\(?.*:\s*any/i,
        /RTCPeerConnection/i,
        /peerConnection/i,
        // Generic browser event handlers with common event names
        /\.(on[a-z]+)\s*=\s*\(\s*(?:event|e|evt)\s*:\s*any\s*\)\s*=>/i,
        /addEventListener\s*\([^,]+,\s*\([^:]+:\s*any\)/i,
        // React/UI library event handler patterns (Tiptap, ProseMirror, etc.)
        /onStart\s*:\s*\(?.*:\s*any/i,
        /onUpdate\s*:\s*\(?.*:\s*any/i,
        /onTransaction\s*:\s*\(?.*:\s*any/i,
        /onSelectionChange\s*:\s*\(?.*:\s*any/i,
        /onBlur\s*:\s*\(?.*:\s*any/i,
        /onFocus\s*:\s*\(?.*:\s*any/i,
        /props\s*:\s*any/i, // Third-party library props (common workaround)
        // Intersection Observer, Resize Observer, etc.
        /IntersectionObserver/i,
        /ResizeObserver/i,
        /MutationObserver/i,
    ];
    return browserAPIPatterns.some(p => p.test(line));
}
/**
 * Check if 'any' usage is on untrusted external input
 */
function isUntrustedInputContext(line) {
    const untrustedPatterns = [
        // Request body/params parsing
        /await\s+request\.json\s*\(\s*\)\s*as\s+any/i,
        /req\.body\s+as\s+any/i,
        /request\.body\s+as\s+any/i,
        /req\.params\s+as\s+any/i,
        /req\.query\s+as\s+any/i,
        /event\.body\s+as\s+any/i,
        // External API responses (if not validated)
        /fetch\s*\([^)]+\).*as\s+any/i,
        /axios\.[^)]+\).*as\s+any/i,
        // Direct parameter typing without validation
        /\(\s*\w+\s*:\s*any\s*\)\s*=>\s*\{/, // Arrow function with any param (if in API context)
    ];
    return untrustedPatterns.some(p => p.test(line));
}
/**
 * Categorize TypeScript 'any' usage by security context
 * Returns sorted list by priority (highest risk first)
 */
function categorizeAnyUsage(lines, filePath) {
    const usages = [];
    const isAPIFile = /api|route|handler|controller|endpoint/.test(filePath.toLowerCase());
    const isDBFile = /repository|model|database|query|prisma|supabase|dexie|db/.test(filePath.toLowerCase());
    const isAuthFile = /auth|login|session|token|password|credential/.test(filePath.toLowerCase());
    lines.forEach((line, idx) => {
        // Skip if line doesn't contain 'any' type
        if (!/:\s*any\b|<any>|as any/.test(line))
            return;
        // Skip comments
        const trimmed = line.trim();
        if (trimmed.startsWith('//') ||
            trimmed.startsWith('/*') ||
            trimmed.startsWith('*')) {
            return;
        }
        // Skip safe ORM/database patterns (Dexie, Prisma, Supabase, internal array maps)
        if (isSafeORMPattern(line)) {
            return;
        }
        // Skip browser API event handlers (SpeechRecognition, MediaRecorder, WebSocket, etc.)
        // These APIs often have incomplete TypeScript typings and 'any' is a legitimate workaround
        if (isBrowserAPIEventHandler(line, filePath)) {
            return;
        }
        let context = 'internal_util';
        let priority = 1;
        // Check if this is untrusted input (highest priority)
        if (isUntrustedInputContext(line)) {
            context = 'api_boundary';
            priority = 10;
        }
        // API boundary detection - only if actually on untrusted data
        else if (isAPIFile && /\b(req|request)\.(body|params|query|json)\b/.test(line)) {
            context = 'api_boundary';
            priority = 10;
        }
        // Auth handler detection (high priority for auth bypass)
        else if (isAuthFile && /\b(password|token|session|auth|verify|jwt|credential)\b/i.test(line)) {
            context = 'auth_handler';
            priority = 9;
        }
        // Database layer - only flag if it's SQL string interpolation, not ORM methods
        else if (isDBFile && /\.(execute|query|raw)\s*\(/i.test(line)) {
            context = 'database_layer';
            priority = 8;
        }
        // Type definitions (lowest priority - often unavoidable)
        else if (/\btype\s+\w+|interface\s+\w+|declare\s+/.test(line)) {
            context = 'type_definition';
            priority = 1;
        }
        // Internal utilities / array operations on DB results (low priority, skip entirely for now)
        else if (isDBFile || /\.map\s*\(|\.filter\s*\(|\.forEach\s*\(|\.reduce\s*\(/.test(line)) {
            // Skip internal array operations - they're operating on already-fetched data
            return;
        }
        // Other internal utilities
        else {
            context = 'internal_util';
            priority = 3;
        }
        usages.push({
            lineNumber: idx + 1,
            lineContent: line.trim(),
            context,
            priority
        });
    });
    // Sort by priority (highest first)
    return usages.sort((a, b) => b.priority - a.priority);
}
/**
 * Detect TypeScript 'any' usage at security boundaries ONLY
 * Returns vulnerabilities for high-priority 'any' usage, capped at top 5 per file
 */
function detectSmartAnyUsage(lines, filePath) {
    const vulnerabilities = [];
    // Only scan TypeScript files
    if (!/\.(ts|tsx)$/.test(filePath)) {
        return vulnerabilities;
    }
    // Categorize all 'any' usages by context
    const anyUsageByContext = categorizeAnyUsage(lines, filePath);
    // Only report high-priority 'any' usages (security boundaries)
    const priorityAny = anyUsageByContext.filter(usage => usage.context === 'api_boundary' ||
        usage.context === 'database_layer' ||
        usage.context === 'auth_handler');
    // Cap reporting to top 5 per file to avoid overwhelming reports
    const cappedAny = priorityAny.slice(0, 5);
    if (cappedAny.length === 0) {
        return vulnerabilities;
    }
    // If there are many 'any' usages, create a grouped finding
    if (cappedAny.length >= 3) {
        // Create single grouped vulnerability
        const contexts = [...new Set(cappedAny.map(a => a.context))];
        const contextDescriptions = contexts.map(ctx => {
            const count = cappedAny.filter(a => a.context === ctx).length;
            const names = {
                'api_boundary': 'API request/response handlers',
                'database_layer': 'Database queries',
                'auth_handler': 'Authentication logic'
            };
            return `${count}x in ${names[ctx] || ctx}`;
        });
        vulnerabilities.push({
            id: `ai-fingerprint-any-${filePath}`,
            filePath,
            lineNumber: cappedAny[0].lineNumber,
            lineContent: `Multiple TypeScript 'any' usages at security boundaries`,
            severity: 'low',
            category: 'ai_pattern',
            title: `[AI Pattern] TypeScript 'any' at security boundaries (${cappedAny.length} instances)`,
            description: `Found ${cappedAny.length} 'any' types at critical security boundaries: ${contextDescriptions.join(', ')}. ` +
                `Lines: ${cappedAny.map(a => a.lineNumber).join(', ')}. ` +
                `Consider using explicit types for type safety and to prevent type confusion vulnerabilities.`,
            suggestedFix: 'Replace "any" with explicit types. For request handlers use typed schemas (Zod, Yup). For database queries use typed ORM models.',
            confidence: 'medium',
            layer: 2,
        });
    }
    else {
        // Report individual findings for 1-2 high-priority 'any' usages
        for (const usage of cappedAny) {
            const contextNames = {
                'api_boundary': 'API request/response handler',
                'database_layer': 'Database query',
                'auth_handler': 'Authentication logic'
            };
            vulnerabilities.push({
                id: `ai-fingerprint-any-${filePath}-${usage.lineNumber}`,
                filePath,
                lineNumber: usage.lineNumber,
                lineContent: usage.lineContent,
                severity: 'low',
                category: 'ai_pattern',
                title: `[AI Pattern] TypeScript 'any' in ${contextNames[usage.context] || usage.context}`,
                description: `Using 'any' type at a security boundary bypasses type checking and can lead to type confusion vulnerabilities. ` +
                    `This is especially risky in ${contextNames[usage.context] || usage.context}.`,
                suggestedFix: 'Replace "any" with an explicit type. Use typed request schemas, ORM models, or interface definitions.',
                confidence: 'medium',
                layer: 2,
            });
        }
    }
    return vulnerabilities;
}
/**
 * Detect managed AI endpoints without rate limiting (cost abuse risk)
 * Finds routes using provider env keys without rate limiting protection
 */
function detectManagedAICostAbuse(content, filePath, lines) {
    const vulnerabilities = [];
    // Only check actual API route files, not utility/handler files
    const isActualRouteFile = /\/(route|page)\.(ts|js|tsx|jsx)$/i.test(filePath) ||
        /\/(api|routes?)\/.*\/index\.(ts|js)$/i.test(filePath);
    // Files named as handlers, helpers, utils, fixtures etc. are NOT actual routes
    const isUtilityFile = /(handler|helper|util|mock|test|fixture|safe|example|config)/i.test(filePath);
    if (!isActualRouteFile || isUtilityFile)
        return vulnerabilities;
    // Check if file uses managed provider keys (from environment)
    const managedKeyPatterns = [
        /process\.env\.OPENAI_API_KEY/i,
        /process\.env\.ANTHROPIC_API_KEY/i,
        /process\.env\.\w*_(API_KEY|SECRET_KEY)/i,
        /import\.meta\.env\.OPENAI/i,
        /import\.meta\.env\.ANTHROPIC/i,
    ];
    const usesManagedKey = managedKeyPatterns.some(p => p.test(content));
    if (!usesManagedKey)
        return vulnerabilities;
    // Skip if this is a config check (checking if key exists) rather than actual API usage
    // Pattern: if (!process.env.OPENAI_API_KEY) or if (process.env.OPENAI_API_KEY === undefined)
    const isConfigCheck = /if\s*\(\s*!?\s*process\.env\.\w*_API_KEY\s*[=!]|!process\.env\.\w*_API_KEY/i.test(content);
    const hasActualAPICall = /\.chat\.completions|\.messages\.create|\.complete\(|anthropic\.\w+\(/i.test(content);
    // If it's just a config check without actual API calls, skip
    if (isConfigCheck && !hasActualAPICall)
        return vulnerabilities;
    // Check for rate limiting patterns nearby
    const rateLimitPatterns = [
        /rateLimit/i,
        /rateLimiter/i,
        /limiter/i,
        /throttle/i,
        /upstash.*ratelimit/i,
        /redis.*limit/i,
        /bucket/i,
        /token.*bucket/i,
        /sliding.*window/i,
        /@upstash\/ratelimit/i,
        /rate-limiter-flexible/i,
    ];
    const hasRateLimiting = rateLimitPatterns.some(p => p.test(content));
    // Check for auth patterns - expanded to catch more middleware patterns
    const authPatterns = [
        /getServerSession/i,
        /auth\(\)/i,
        /auth\.protect/i,
        /currentUser/i,
        /getCurrentUser/i,
        /getCurrentUserId/i,
        /requireAuth/i,
        /verifyToken/i,
        /session\.user/i,
        /authorization/i,
        /withAuth/i,
        /isAuthenticated/i,
        /checkAuth/i,
        /validateSession/i,
        /clerk/i, // Clerk auth
        /supabase.*auth/i, // Supabase auth
        /nextauth/i, // NextAuth
        /authMiddleware/i,
        /protectedRoute/i,
        /requireSession/i,
        /userId.*=.*auth/i, // userId from auth
        /user\.id/i, // Accessing user.id implies auth
    ];
    const hasAuth = authPatterns.some(p => p.test(content));
    // Check if route is likely protected by middleware (file path based)
    const isLikelyMiddlewareProtected = /\/api\/(protected|private|admin|user|account|dashboard)\//i.test(filePath) ||
        /\/\(authenticated\)\//i.test(filePath) || // Next.js route groups
        /\/\(protected\)\//i.test(filePath) ||
        /\/\(auth\)\//i.test(filePath);
    // Determine severity based on auth + rate limiting
    if (!hasRateLimiting) {
        // Find the line with the env key usage
        let keyLine = 1;
        for (let i = 0; i < lines.length; i++) {
            if (managedKeyPatterns.some(p => p.test(lines[i]))) {
                keyLine = i + 1;
                break;
            }
        }
        // If route is authenticated (inline or via middleware), this is just operational concern
        if (hasAuth || isLikelyMiddlewareProtected) {
            // Authenticated route without rate limiting - operational concern, not security vuln
            vulnerabilities.push({
                id: `ai-cost-abuse-${filePath}`,
                filePath,
                lineNumber: keyLine,
                lineContent: lines[keyLine - 1]?.trim() || 'process.env.*_API_KEY',
                severity: 'info',
                category: 'ai_pattern',
                title: 'Managed AI endpoint without rate limiting (authenticated)',
                description: 'This authenticated API route uses a managed AI provider key but lacks rate limiting. Authenticated users could potentially abuse the endpoint. This is an operational concern, not a security vulnerability.',
                suggestedFix: 'Consider adding per-user rate limiting (e.g., @upstash/ratelimit) to prevent cost abuse by authenticated users.',
                confidence: 'low',
                layer: 2,
            });
        }
        else {
            // Unauthenticated route - higher risk
            vulnerabilities.push({
                id: `ai-cost-abuse-${filePath}`,
                filePath,
                lineNumber: keyLine,
                lineContent: lines[keyLine - 1]?.trim() || 'process.env.*_API_KEY',
                severity: 'medium',
                category: 'ai_pattern',
                title: 'Managed AI endpoint without authentication or rate limiting',
                description: 'This API route uses a managed AI provider key without apparent authentication or rate limiting. This could allow unauthenticated cost abuse.',
                suggestedFix: 'Add authentication or rate limiting (e.g., @upstash/ratelimit, rate-limiter-flexible) to prevent cost abuse.',
                confidence: 'medium',
                layer: 2,
            });
        }
    }
    return vulnerabilities;
}
/**
 * Check if line contains clearly placeholder credential values
 */
function isPlaceholderCredential(line) {
    const placeholderPatterns = [
        /your[-_]?api[-_]?key/i,
        /your[-_]?secret/i,
        /your[-_]?password/i,
        /replace[-_]?with/i,
        /example[-_]?key/i,
        /sample[-_]?key/i,
        /demo[-_]?key/i,
        /test[-_]?key/i,
        /fake[-_]?key/i,
        /mock[-_]?key/i,
        /placeholder/i,
        /<.*>/, // <YOUR_KEY>
        /\[.*\]/, // [API_KEY]
        /xxx+/i,
    ];
    return placeholderPatterns.some(p => p.test(line));
}
/**
 * Check if file path indicates a config/settings file
 */
function isConfigFile(filePath) {
    const lowerPath = filePath.toLowerCase();
    return /config|settings|constants|urls|endpoints|env/i.test(lowerPath);
}
function detectAIFingerprints(content, filePath, options) {
    const vulnerabilities = [];
    // Skip scanner/fixture files to avoid self-detection
    if ((0, context_helpers_1.isScannerOrFixtureFile)(filePath))
        return vulnerabilities;
    const lines = options?.parsed?.lines ?? content.split('\n');
    // Skip example/demo files entirely - they contain placeholder code by design
    if ((0, context_helpers_1.isExampleFile)(filePath)) {
        return vulnerabilities;
    }
    const isTestFile = (0, context_helpers_1.isTestOrMockFile)(filePath);
    const isConfigOrSettings = isConfigFile(filePath);
    // First, run smart 'any' detection (TypeScript files only, context-aware)
    const anyVulns = detectSmartAnyUsage(lines, filePath);
    vulnerabilities.push(...anyVulns);
    // Detect managed AI cost abuse risk
    const costAbuseVulns = detectManagedAICostAbuse(content, filePath, lines);
    vulnerabilities.push(...costAbuseVulns);
    // Track AI pattern density for file-level assessment
    let aiPatternCount = 0;
    lines.forEach((line, index) => {
        for (const fingerprint of AI_FINGERPRINTS) {
            const regex = new RegExp(fingerprint.pattern.source, fingerprint.pattern.flags);
            if (regex.test(line)) {
                // Skip placeholder/example credentials for the "AI example credentials" pattern
                if (fingerprint.name === 'AI example credentials') {
                    if (isPlaceholderCredential(line) || (0, context_helpers_1.isPlaceholderValue)('', line) || isTestFile) {
                        continue; // Skip this pattern, check others
                    }
                }
                aiPatternCount++;
                // Downgrade severity for test files
                let severity = fingerprint.severity;
                let confidence = fingerprint.confidence;
                if (isTestFile) {
                    if (severity === 'critical')
                        severity = 'medium';
                    else if (severity === 'high')
                        severity = 'low';
                    else
                        severity = 'info';
                    confidence = 'low';
                }
                vulnerabilities.push({
                    id: `ai-fingerprint-${filePath}-${index + 1}-${fingerprint.name}`,
                    filePath,
                    lineNumber: index + 1,
                    lineContent: line.trim(),
                    severity,
                    category: 'ai_pattern',
                    title: `[AI Pattern] ${fingerprint.name}`,
                    description: fingerprint.description + (isTestFile ? ' (in test file)' : ''),
                    suggestedFix: fingerprint.suggestedFix,
                    confidence,
                    layer: 2,
                });
                break; // Only report once per line
            }
        }
    });
    // Context-aware localhost/example URL detection
    // Use environment context for smarter filtering
    const envContext = (0, environment_context_1.getEnvironmentContext)(filePath);
    // Skip for environments where placeholder URLs are expected
    if (!envContext.allowsPlaceholderUrls && !isConfigOrSettings && !isTestFile) {
        const localhostPattern = /['"]https?:\/\/(localhost|127\.0\.0\.1|example\.com|your-domain|api\.example)[^'"]*['"]/gi;
        lines.forEach((line, index) => {
            if (localhostPattern.test(line)) {
                // Reset regex state
                localhostPattern.lastIndex = 0;
                // Skip if it's a comment
                const trimmed = line.trim();
                if (trimmed.startsWith('//') || trimmed.startsWith('/*') || trimmed.startsWith('*')) {
                    return;
                }
                // Skip if it looks like env var fallback (process.env.X || "http://localhost")
                if (/process\.env\.\w+\s*\|\|\s*['"]/.test(line)) {
                    return;
                }
                // Skip if it's in a placeholder attribute (placeholder="https://example.com")
                if ((0, environment_context_1.isInPlaceholderAttribute)(line)) {
                    return;
                }
                // Skip if it's a default parameter value
                if ((0, environment_context_1.isDefaultParameterValue)(line)) {
                    return;
                }
                vulnerabilities.push({
                    id: `ai-fingerprint-${filePath}-${index + 1}-localhost-url`,
                    filePath,
                    lineNumber: index + 1,
                    lineContent: line.trim(),
                    severity: 'medium',
                    category: 'ai_pattern',
                    title: '[AI Pattern] AI localhost/example URL',
                    description: 'Placeholder URL that should be replaced with actual endpoint',
                    suggestedFix: 'Replace with actual production URL from environment variable',
                    confidence: 'high',
                    layer: 2,
                });
                aiPatternCount++;
            }
        });
    }
    // If file has high density of AI patterns, add a summary finding
    const lineCount = lines.length;
    const aiDensity = aiPatternCount / Math.max(lineCount, 1);
    // Raised threshold to 10% and require high-severity patterns to reduce noise
    if (aiDensity > 0.10 && aiPatternCount >= 5) {
        vulnerabilities.push({
            id: `ai-fingerprint-${filePath}-summary`,
            filePath,
            lineNumber: 1,
            lineContent: `File contains ${aiPatternCount} AI-generated code patterns`,
            severity: 'medium',
            category: 'ai_pattern',
            title: '[AI Pattern] High AI-generated code density',
            description: `This file shows ${aiPatternCount} patterns commonly found in AI-generated code. Consider a thorough security review.`,
            suggestedFix: 'Review this file carefully for security issues, incomplete implementations, and placeholder code',
            confidence: 'medium',
            layer: 2,
        });
    }
    return vulnerabilities;
}
//# sourceMappingURL=ai-fingerprinting.js.map