"use strict";
/**
 * General Helper Utilities
 *
 * Small utility functions used across the dangerous functions detection module.
 */
Object.defineProperty(exports, "__esModule", { value: true });
exports.getLineContent = getLineContent;
exports.getLineRange = getLineRange;
exports.hasOnlyStaticInputs = hasOnlyStaticInputs;
exports.hasPathTraversalProtection = hasPathTraversalProtection;
exports.hasThrowingAuthHelper = hasThrowingAuthHelper;
/**
 * Get a specific line from content by line number (0-indexed)
 */
function getLineContent(content, lineNumber) {
    const lines = content.split('\n');
    return lines[lineNumber] || '';
}
/**
 * Get a range of lines from content
 */
function getLineRange(content, startLine, endLine) {
    const lines = content.split('\n');
    const start = Math.max(0, startLine);
    const end = Math.min(lines.length, endLine);
    return lines.slice(start, end).join('\n');
}
/**
 * Check if eval/exec/Function has only static literal inputs (no user data)
 * Static inputs like eval('({ mode: "production" })') are low risk
 *
 * Returns true ONLY if the argument is a string literal (not a variable)
 */
function hasOnlyStaticInputs(lineContent, content, lineNumber) {
    // Check if the argument to eval/exec/Function is a string literal ONLY
    // If it's a variable, it's NOT static (could come from anywhere)
    //
    // String literal patterns:
    // - Single quotes: 'content with "double quotes" inside' (no $ interpolation)
    // - Double quotes: "content" (no $ interpolation)
    // - Backticks without ${}: `content` (template literal but no interpolation)
    //
    // Note: We allow quotes INSIDE the string (e.g., 'text "with" quotes')
    // but NOT $ (which would indicate interpolation)
    const staticPatterns = [
        // Single-quoted string: eval('...') - can contain anything except single quotes and $
        /eval\s*\(\s*'[^'$]*'\s*\)/,
        // Double-quoted string: eval("...") - can contain anything except double quotes and $
        /eval\s*\(\s*"[^"$]*"\s*\)/,
        // Backtick without interpolation: eval(`...`) - must not have ${ inside
        /eval\s*\(\s*`[^`$]*`\s*\)/,
        // Function constructor with string literal
        /new\s+Function\s*\(\s*'[^'$]*'\s*\)/,
        /new\s+Function\s*\(\s*"[^"$]*"\s*\)/,
        // execSync with string literal
        /execSync\s*\(\s*'[^'$]*'\s*\)/,
        /execSync\s*\(\s*"[^"$]*"\s*\)/,
        // exec with string literal
        /exec\s*\(\s*'[^'$]*'/,
        /exec\s*\(\s*"[^"$]*"/,
    ];
    // Only return true if it matches a static pattern (string literal)
    // If it's a variable like eval(code), we can't assume it's static
    return staticPatterns.some(p => p.test(lineContent));
}
/**
 * Check if path traversal protection is in place
 * Looks for common sanitization patterns that prevent directory traversal attacks
 */
function hasPathTraversalProtection(context, lineContent) {
    const protectionPatterns = [
        // Path normalization with base directory check (same line)
        /path\.resolve\s*\([^)]+\).*\.startsWith\s*\(/i,
        // startsWith check with common safe directory variable names
        /\.startsWith\s*\([^)]*(?:baseDir|basePath|rootDir|uploadDir|allowedDir|safeDir|SAFE_)/i,
        // MULTI-LINE PATTERN: path.resolve followed by startsWith check in context
        // This handles the common case where resolve and startsWith are on separate lines:
        //   const resolved = path.resolve(baseDir, userPath)
        //   if (!resolved.startsWith(baseDir)) throw new Error()
        // We check for BOTH patterns being present in the context
        // (handled below as combined check)
        // Explicit ".." rejection
        /\.includes\s*\(\s*['"`]\.\.['"`]\s*\)/i,
        /\.indexOf\s*\(\s*['"`]\.\.['"`]\s*\)/i,
        /['"`]\.\.['"`].*(?:throw|reject|return|error)/i,
        // Replace ".." pattern (sanitization)
        /\.replace\s*\([^)]*\\?\.\\?\.\s*[^)]*,\s*['"`]['"`]\s*\)/i,
        // Path sanitization libraries
        /sanitizePath|sanitizeFilename|sanitize-filename/i,
        /path-sanitizer|secure-path/i,
        // Explicit path validation
        /validatePath|isValidPath|checkPath|verifyPath/i,
        /isPathAllowed|isAllowedPath|pathIsAllowed/i,
        // Normalize and check pattern
        /path\.normalize\s*\([^)]+\).*(?:startsWith|includes|indexOf)/i,
        // Regex validation for safe characters only
        /\/\^?\[a-zA-Z0-9_\-\.\\\/\]\+\$?\//, // Only alphanumeric, dash, underscore, dot
        // Allowlist/whitelist patterns
        /allowedExtensions|allowedTypes|whitelist/i,
        /\.endsWith\s*\(\s*['"`]\.\w+['"`]\s*\)/i, // Extension check
        // Path.basename to strip directory
        /path\.basename\s*\(/i,
        // Zod/validation for filename patterns
        /z\.string\s*\(\s*\)\.regex\s*\(/i,
    ];
    // Check single-line patterns
    if (protectionPatterns.some(p => p.test(context) || p.test(lineContent))) {
        return true;
    }
    // Multi-line pattern: path.resolve + startsWith check on separate lines
    // This is a very common secure pattern:
    //   const resolved = path.resolve(safeBaseDir, userInput)
    //   if (!resolved.startsWith(safeBaseDir)) { throw ... }
    const hasPathResolve = /path\.resolve\s*\(/i.test(context);
    const hasStartsWithCheck = /\.startsWith\s*\(/i.test(context);
    const hasThrowOnFailure = /(throw|return|reject)\s+.*(error|invalid|denied)/i.test(context);
    if (hasPathResolve && hasStartsWithCheck && hasThrowOnFailure) {
        return true;
    }
    return false;
}
/**
 * Check if route has throwing auth helper (getCurrentUserId, requireAuth, etc.)
 * Routes with throwing auth helpers are already protected
 */
function hasThrowingAuthHelper(content) {
    const throwingAuthPatterns = [
        /\bgetCurrentUserId\s*\(/i,
        /\brequireAuth\s*\(/i,
        /\bensureAuth\s*\(/i,
        /\bauth\s*\(\s*\)\s*\.protect\s*\(/i, // Clerk: auth().protect()
        /\bcurrentUser\s*\(\s*\)/i, // Clerk: currentUser()
        /\bgetServerSession\s*\([^)]*\)/i, // NextAuth
        /\bauth\s*\(\s*\)/i, // Generic auth() call
        /\bcheckAuth\s*\(/i,
        /\bverifyAuth\s*\(/i,
        /\bvalidateAuth\s*\(/i,
        /\bassertAuth\s*\(/i,
        /\bgetAuth\s*\(/i,
        /\brequireUser\s*\(/i,
        /\bgetUser\s*\(\s*\)/i, // supabase.auth.getUser()
        /const\s+\{\s*user\s*\}\s*=\s*await/i, // Destructuring pattern
    ];
    return throwingAuthPatterns.some(p => p.test(content));
}
//# sourceMappingURL=helpers.js.map