"use strict";
/**
 * Layer 2: Security Headers Detector
 * Detects missing HTTP security headers in server configurations
 *
 * OWASP A02:2021 - Cryptographic Failures / Security Misconfiguration
 * CWE-693: Protection Mechanism Failure
 */
Object.defineProperty(exports, "__esModule", { value: true });
exports.detectSecurityHeaders = detectSecurityHeaders;
const context_helpers_1 = require("../utils/context-helpers");
/**
 * Check if a file is client-side (not a server file)
 */
function isClientSideFile(content, filePath) {
    // Explicit 'use client' directive
    if (/['"]use client['"]/.test(content))
        return true;
    // Client-side file paths
    const clientPatterns = [
        /\/components\//i,
        /\/hooks\//i,
        /\/pages\/(?!api\/)/i, // pages/ but not pages/api/
        /\.client\.(ts|js|tsx|jsx)$/i,
    ];
    // Only apply path heuristics if no server indicators
    if (clientPatterns.some(p => p.test(filePath))) {
        // Check for server indicators that override
        const hasServerIndicators = content.includes('express()') ||
            content.includes("require('express')") ||
            content.includes('from \'express\'') ||
            content.includes('from "express"') ||
            content.includes('createServer') ||
            /['"]use server['"]/.test(content);
        if (!hasServerIndicators)
            return true;
    }
    return false;
}
/**
 * Check if a file is a Next.js config file
 */
function isNextConfig(filePath) {
    return /next\.config\.(m?js|ts)$/.test(filePath);
}
/**
 * Detect missing security headers in server configurations
 */
function detectSecurityHeaders(content, filePath, options) {
    const vulnerabilities = [];
    if ((0, context_helpers_1.isScannerOrFixtureFile)(filePath))
        return vulnerabilities;
    if ((0, context_helpers_1.isTestOrMockFile)(filePath))
        return vulnerabilities;
    if (isClientSideFile(content, filePath))
        return vulnerabilities;
    const lines = options?.parsed?.lines ?? content.split('\n');
    // --- Check 1: Express without helmet ---
    const hasExpress = content.includes('express()') ||
        /require\s*\(\s*['"]express['"]\s*\)/.test(content) ||
        /from\s+['"]express['"]/.test(content);
    if (hasExpress) {
        const hasHelmet = /require\s*\(\s*['"]helmet['"]\s*\)/.test(content) ||
            /from\s+['"]helmet['"]/.test(content) ||
            /require\s*\(\s*['"]@fastify\/helmet['"]\s*\)/.test(content) ||
            /from\s+['"]@fastify\/helmet['"]/.test(content);
        if (!hasHelmet) {
            // Find the line where express() is called
            let expressLine = 0;
            let expressContent = '';
            for (let i = 0; i < lines.length; i++) {
                if (/express\s*\(\s*\)/.test(lines[i])) {
                    expressLine = i + 1;
                    expressContent = lines[i].trim();
                    break;
                }
            }
            if (expressLine > 0) {
                vulnerabilities.push({
                    id: `secheader-${filePath}-express-no-helmet`,
                    filePath,
                    lineNumber: expressLine,
                    lineContent: expressContent,
                    severity: 'medium',
                    category: 'missing_security_headers',
                    title: 'Express app without helmet security headers',
                    description: 'Express application does not use helmet middleware. This leaves the app without critical HTTP security headers (CSP, HSTS, X-Frame-Options, X-Content-Type-Options).',
                    suggestedFix: 'Install and add helmet middleware: npm install helmet && app.use(helmet())',
                    confidence: 'high',
                    layer: 2,
                    requiresAIValidation: true,
                });
            }
        }
        else {
            // --- Check 2: Helmet with CSP disabled ---
            for (let i = 0; i < lines.length; i++) {
                const line = lines[i];
                if (/contentSecurityPolicy\s*:\s*false/.test(line)) {
                    vulnerabilities.push({
                        id: `secheader-${filePath}-${i + 1}-csp-disabled`,
                        filePath,
                        lineNumber: i + 1,
                        lineContent: line.trim(),
                        severity: 'low',
                        category: 'missing_security_headers',
                        title: 'Helmet CSP disabled',
                        description: 'Content Security Policy is explicitly disabled in helmet configuration. CSP is a critical defense against XSS attacks.',
                        suggestedFix: 'Configure a Content Security Policy instead of disabling it: helmet({ contentSecurityPolicy: { directives: { ... } } })',
                        confidence: 'high',
                        layer: 2,
                    });
                }
            }
        }
    }
    // --- Check 3: Next.js config missing headers ---
    if (isNextConfig(filePath)) {
        const hasHeadersExport = /headers\s*\(\s*\)/.test(content) ||
            /headers\s*:\s*(?:async\s*)?\(?\s*\)?\s*=>/.test(content) ||
            /async\s+headers\s*\(\s*\)/.test(content);
        if (!hasHeadersExport) {
            vulnerabilities.push({
                id: `secheader-${filePath}-nextjs-no-headers`,
                filePath,
                lineNumber: 1,
                lineContent: lines[0]?.trim() || '',
                severity: 'medium',
                category: 'missing_security_headers',
                title: 'Next.js config missing security headers',
                description: 'next.config does not export a headers() function. Security headers (CSP, HSTS, X-Frame-Options) should be configured in Next.js config or middleware.',
                suggestedFix: 'Add a headers() function to next.config.js that returns security headers array',
                confidence: 'medium',
                layer: 2,
                requiresAIValidation: true,
            });
        }
    }
    // --- Check 4: Server setting some headers but missing critical ones ---
    // Only check files that explicitly set response headers
    const setsHeaders = /res\.setHeader\s*\(/.test(content) ||
        /response\.setHeader\s*\(/.test(content) ||
        /res\.set\s*\(/.test(content) ||
        /response\.headers\.set\s*\(/.test(content);
    if (setsHeaders && !hasExpress) {
        const criticalHeaders = [
            { name: 'Content-Security-Policy', pattern: /content-security-policy/i },
            { name: 'Strict-Transport-Security', pattern: /strict-transport-security/i },
            { name: 'X-Content-Type-Options', pattern: /x-content-type-options/i },
            { name: 'X-Frame-Options', pattern: /x-frame-options/i },
        ];
        const missingHeaders = criticalHeaders.filter(h => !h.pattern.test(content));
        // Only flag if file sets SOME headers but omits critical ones
        const presentHeaders = criticalHeaders.filter(h => h.pattern.test(content));
        if (presentHeaders.length > 0 && missingHeaders.length > 0) {
            // Find a line where headers are being set for reporting
            let headerLine = 0;
            let headerContent = '';
            for (let i = 0; i < lines.length; i++) {
                if (/(?:res|response)\.(?:setHeader|set|headers\.set)\s*\(/.test(lines[i])) {
                    headerLine = i + 1;
                    headerContent = lines[i].trim();
                    break;
                }
            }
            if (headerLine > 0) {
                const missing = missingHeaders.map(h => h.name).join(', ');
                vulnerabilities.push({
                    id: `secheader-${filePath}-${headerLine}-missing-headers`,
                    filePath,
                    lineNumber: headerLine,
                    lineContent: headerContent,
                    severity: 'low',
                    category: 'missing_security_headers',
                    title: 'Incomplete security headers',
                    description: `Server sets some response headers but is missing: ${missing}. Consider adding these critical security headers.`,
                    suggestedFix: `Add missing security headers: ${missing}`,
                    confidence: 'medium',
                    layer: 2,
                    requiresAIValidation: true,
                });
            }
        }
    }
    return vulnerabilities;
}
//# sourceMappingURL=security-headers.js.map