/**
 * Business Logic Scanner Module
 *
 * Detects BOLA, IDOR, BFLA, and other authorization vulnerabilities
 * through static analysis of API endpoints.
 *
 * @module scanners/logic
 */
import { logger } from "../../logger.js";
import { LOGIC_VULN_CWE_MAP, LOGIC_VULN_OWASP_MAP, LOGIC_VULN_SEVERITY_MAP, } from "./types.js";
import { extractEndpoints, detectFramework, } from "./endpoint-analyzer.js";
import { analyzeEndpoints, } from "./auth-flow-analyzer.js";
// Re-export types
export * from "./types.js";
// Re-export analyzer functions
export { extractEndpoints, detectFramework, extractPathParams, inferResourceType, } from "./endpoint-analyzer.js";
export { analyzeAuthorizationFlow, analyzeEndpoints, } from "./auth-flow-analyzer.js";
/**
 * Convert logic vulnerability to finding format
 */
function vulnerabilityToFinding(vuln) {
    return {
        scanner: "logic",
        ruleId: `logic-${vuln.vulnType}`,
        file: vuln.file,
        line: vuln.line,
        message: vuln.description,
        severity: vuln.severity,
        confidence: vuln.confidence,
        category: vuln.vulnType,
        vulnType: vuln.vulnType,
        affectedEndpoint: vuln.endpoint,
        httpMethod: vuln.method,
        authCheck: vuln.authCheck,
        resourceAccess: vuln.resourceAccess,
        cweIds: vuln.cweIds,
        owaspRefs: vuln.owaspRefs,
        remediation: vuln.remediation,
    };
}
/**
 * Run logic vulnerability scan
 */
export async function runLogicScan(projectPath, options = {}) {
    const startTime = Date.now();
    logger.info("logic_scan.start", {
        projectPath,
        framework: options.framework || "auto",
        focusAreas: options.focusAreas,
    });
    try {
        // Detect framework if not specified
        const framework = options.framework || (await detectFramework(projectPath));
        // Extract endpoints
        const endpoints = await extractEndpoints(projectPath, {
            framework,
            include: options.include,
            exclude: options.exclude,
        });
        // Limit files if specified
        const limitedEndpoints = options.maxFiles
            ? endpoints.slice(0, options.maxFiles)
            : endpoints;
        // Analyze authorization flows
        const analyses = await analyzeEndpoints(limitedEndpoints, projectPath);
        // Collect all vulnerabilities
        let allVulnerabilities = [];
        for (const analysis of analyses) {
            allVulnerabilities.push(...analysis.vulnerabilities);
        }
        // Filter by focus areas if specified
        if (options.focusAreas && options.focusAreas.length > 0) {
            allVulnerabilities = allVulnerabilities.filter((v) => options.focusAreas.includes(v.vulnType));
        }
        // Convert to findings
        const findings = allVulnerabilities.map(vulnerabilityToFinding);
        // Calculate stats
        const bySeverity = {};
        const byVulnType = {};
        for (const vuln of allVulnerabilities) {
            bySeverity[vuln.severity] = (bySeverity[vuln.severity] || 0) + 1;
            byVulnType[vuln.vulnType] = (byVulnType[vuln.vulnType] || 0) + 1;
        }
        const duration = Date.now() - startTime;
        logger.info("logic_scan.complete", {
            endpoints: endpoints.length,
            vulnerabilities: allVulnerabilities.length,
            duration,
        });
        return {
            projectPath,
            framework,
            endpoints: limitedEndpoints,
            vulnerabilities: allVulnerabilities,
            findings,
            stats: {
                filesAnalyzed: new Set(endpoints.map((e) => e.file)).size,
                endpointsFound: endpoints.length,
                vulnerabilitiesFound: allVulnerabilities.length,
                bySeverity,
                byVulnType,
            },
            duration,
            success: true,
        };
    }
    catch (error) {
        const duration = Date.now() - startTime;
        logger.error("logic_scan.failed", { error: String(error) });
        return {
            projectPath,
            framework: options.framework || "auto",
            endpoints: [],
            vulnerabilities: [],
            findings: [],
            stats: {
                filesAnalyzed: 0,
                endpointsFound: 0,
                vulnerabilitiesFound: 0,
                bySeverity: {},
                byVulnType: {},
            },
            duration,
            success: false,
            error: String(error),
        };
    }
}
/**
 * Format logic scan results for display
 */
export function formatLogicResults(result) {
    const lines = [
        "# Business Logic Security Scan",
        "",
        `**Framework**: ${result.framework}`,
        `**Endpoints Analyzed**: ${result.stats.endpointsFound}`,
        `**Vulnerabilities Found**: ${result.stats.vulnerabilitiesFound}`,
        `**Duration**: ${Math.round(result.duration / 1000)}s`,
        "",
    ];
    if (!result.success) {
        lines.push(`**Error**: ${result.error}`);
        return lines.join("\n");
    }
    if (result.vulnerabilities.length === 0) {
        lines.push("✅ No authorization vulnerabilities detected.");
        return lines.join("\n");
    }
    // Group by severity
    const severityOrder = ["critical", "high", "medium", "low", "info"];
    const grouped = new Map();
    for (const vuln of result.vulnerabilities) {
        const existing = grouped.get(vuln.severity) || [];
        existing.push(vuln);
        grouped.set(vuln.severity, existing);
    }
    for (const severity of severityOrder) {
        const vulns = grouped.get(severity);
        if (!vulns || vulns.length === 0)
            continue;
        const emoji = {
            critical: "🔴",
            high: "🟠",
            medium: "🟡",
            low: "🔵",
            info: "⚪",
        }[severity];
        lines.push(`## ${emoji} ${severity.toUpperCase()} (${vulns.length})`, "");
        for (const vuln of vulns) {
            lines.push(`### ${vuln.name}`);
            lines.push(`- **Endpoint**: \`${Array.isArray(vuln.method) ? vuln.method.join("/") : vuln.method} ${vuln.endpoint}\``);
            lines.push(`- **File**: ${vuln.file}:${vuln.line}`);
            lines.push(`- **Description**: ${vuln.description}`);
            if (vuln.cweIds.length > 0) {
                lines.push(`- **CWE**: ${vuln.cweIds.join(", ")}`);
            }
            if (vuln.owaspRefs.length > 0) {
                lines.push(`- **OWASP**: ${vuln.owaspRefs.join(", ")}`);
            }
            lines.push(`- **Remediation**: ${vuln.remediation}`);
            lines.push("");
        }
    }
    // Summary by type
    if (Object.keys(result.stats.byVulnType).length > 0) {
        lines.push("## Summary by Vulnerability Type", "");
        lines.push("| Type | Count |");
        lines.push("|------|-------|");
        for (const [type, count] of Object.entries(result.stats.byVulnType)) {
            if (count && count > 0) {
                lines.push(`| ${type} | ${count} |`);
            }
        }
    }
    return lines.join("\n");
}
/**
 * Get vulnerability description
 */
export function getVulnerabilityDescription(vulnType) {
    const descriptions = {
        "bola": "Broken Object Level Authorization occurs when an API does not properly validate that a user has permission to access a specific object.",
        "idor": "Insecure Direct Object Reference allows attackers to access objects directly by manipulating input parameters containing object IDs.",
        "bfla": "Broken Function Level Authorization occurs when users can access administrative or privileged functions without proper permission checks.",
        "mass-assignment": "Mass Assignment allows attackers to modify object properties they shouldn't have access to by manipulating request parameters.",
        "race-condition-auth": "Race Condition in Authorization occurs when concurrent requests can bypass authorization checks.",
        "privilege-escalation": "Privilege Escalation allows users to gain elevated access rights beyond what was intended.",
        "missing-auth": "Missing Authentication occurs when sensitive endpoints do not require user authentication.",
        "missing-authz": "Missing Authorization occurs when authenticated users can perform actions without proper permission checks.",
        "direct-db-access": "Direct Database Access without Authorization allows unvalidated access to data through unprotected database queries.",
        "horizontal-priv-esc": "Horizontal Privilege Escalation allows users to access resources belonging to other users at the same privilege level.",
        "vertical-priv-esc": "Vertical Privilege Escalation allows users to elevate their privileges to a higher access level.",
    };
    const names = {
        "bola": "Broken Object Level Authorization",
        "idor": "Insecure Direct Object Reference",
        "bfla": "Broken Function Level Authorization",
        "mass-assignment": "Mass Assignment",
        "race-condition-auth": "Race Condition in Authorization",
        "privilege-escalation": "Privilege Escalation",
        "missing-auth": "Missing Authentication",
        "missing-authz": "Missing Authorization",
        "direct-db-access": "Direct Database Access",
        "horizontal-priv-esc": "Horizontal Privilege Escalation",
        "vertical-priv-esc": "Vertical Privilege Escalation",
    };
    return {
        name: names[vulnType],
        description: descriptions[vulnType],
        cweIds: LOGIC_VULN_CWE_MAP[vulnType],
        owaspRefs: LOGIC_VULN_OWASP_MAP[vulnType],
        severity: LOGIC_VULN_SEVERITY_MAP[vulnType],
    };
}
/**
 * Quick check for common authorization issues
 */
export async function quickAuthCheck(projectPath) {
    const endpoints = await extractEndpoints(projectPath);
    const analyses = await analyzeEndpoints(endpoints, projectPath);
    let hasAuthMiddleware = false;
    let hasOwnershipChecks = false;
    let hasRoleChecks = false;
    const potentialIssues = [];
    for (const analysis of analyses) {
        if (analysis.requiresAuth)
            hasAuthMiddleware = true;
        for (const check of analysis.authzChecks) {
            if (check.type === "ownership")
                hasOwnershipChecks = true;
            if (check.type === "role" || check.type === "admin")
                hasRoleChecks = true;
        }
        for (const vuln of analysis.vulnerabilities) {
            if (!potentialIssues.includes(vuln.vulnType)) {
                potentialIssues.push(vuln.vulnType);
            }
        }
    }
    return {
        hasAuthMiddleware,
        hasOwnershipChecks,
        hasRoleChecks,
        potentialIssues,
    };
}
//# sourceMappingURL=index.js.map