/**
 * Built-in Detection Rules
 *
 * Proprietary detection rules that differentiate Vaspera from Semgrep wrappers.
 * These rules use data flow and control flow analysis for high-confidence detection.
 *
 * @module scanners/detection/rules/builtin
 */
export const BUILTIN_RULES = [
    {
        id: "vaspera:idor:user-controlled-id",
        name: "User-Controlled ID Without Ownership Check",
        description: "API endpoint accepts user-controlled ID parameter without verifying the requesting user owns the referenced resource. This allows attackers to access other users' data by manipulating the ID.",
        category: "idor",
        severity: "high",
        confidence: 85,
        enabled: true,
        engines: {
            dataFlow: {
                sources: [
                    { pattern: "req.params.$id", description: "URL path parameter" },
                    { pattern: "req.query.$id", description: "Query string parameter" },
                    { pattern: "req.body.$id", description: "Request body field" },
                    { pattern: "request.params.$id" },
                    { pattern: "ctx.params.$id" },
                ],
                sinks: [
                    { pattern: "findById($source)", description: "Direct ID lookup" },
                    { pattern: "findOne({ id: $source })" },
                    { pattern: "findUnique({ where: { id: $source } })" },
                    { pattern: "where({ id: $source })" },
                    { pattern: "get($source)" },
                ],
                sanitizers: [
                    { pattern: "verifyOwnership($source, $user)" },
                    { pattern: "checkAccess($source, $user)" },
                    { pattern: "belongsTo($source, $user)" },
                    { pattern: "isOwner($source)" },
                    { pattern: "canAccess($source)" },
                ],
            },
        },
        cweIds: ["CWE-639", "CWE-284"],
        owaspRefs: ["API1:2023", "A01:2021"],
        autofixPatternId: "add-ownership-check",
    },
    {
        id: "vaspera:bola:mass-assignment",
        name: "Broken Object Level Authorization via Mass Assignment",
        description: "Endpoint accepts object updates without filtering sensitive fields or verifying authorization. Attackers can modify fields they shouldn't have access to (e.g., isAdmin, role, balance).",
        category: "bola",
        severity: "high",
        confidence: 80,
        enabled: true,
        engines: {
            dataFlow: {
                sources: [
                    { pattern: "req.body", description: "Full request body" },
                    { pattern: "request.body" },
                    { pattern: "ctx.request.body" },
                    { pattern: "{ ...req.body }", description: "Spread request body" },
                ],
                sinks: [
                    { pattern: "update($source)" },
                    { pattern: "updateOne($source)" },
                    { pattern: "updateMany($source)" },
                    { pattern: "save($source)" },
                    { pattern: "Object.assign($target, $source)" },
                    { pattern: "{ ...$target, ...$source }" },
                ],
                sanitizers: [
                    { pattern: "pick($source, $fields)", description: "Whitelist fields" },
                    { pattern: "omit($source, $fields)", description: "Blacklist fields" },
                    { pattern: "sanitize($source)" },
                    { pattern: "allowedFields.filter" },
                ],
            },
        },
        cweIds: ["CWE-915", "CWE-284"],
        owaspRefs: ["API3:2023", "A01:2021"],
        autofixPatternId: "add-field-whitelist",
    },
    {
        id: "vaspera:auth-bypass:missing-middleware",
        name: "Missing Authentication Middleware",
        description: "Route handler accesses sensitive operations without authentication middleware. The endpoint can be accessed by unauthenticated users.",
        category: "auth-bypass",
        severity: "critical",
        confidence: 75,
        enabled: true,
        engines: {
            astQuery: {
                pattern: "router.$method($path, $handler)",
                constraints: {
                    method: "get|post|put|patch|delete",
                },
            },
            controlFlow: {
                entryPoints: [
                    "router.get",
                    "router.post",
                    "router.put",
                    "router.patch",
                    "router.delete",
                    "app.get",
                    "app.post",
                ],
                mustReach: [
                    { pattern: "req.user", description: "Must access authenticated user" },
                    { pattern: "req.session", description: "Must check session" },
                    { pattern: "isAuthenticated", description: "Must verify authentication" },
                    { pattern: "requireAuth", description: "Must require authentication" },
                ],
            },
        },
        cweIds: ["CWE-306", "CWE-287"],
        owaspRefs: ["API2:2023", "A07:2021"],
        autofixPatternId: "add-auth-middleware",
    },
    {
        id: "vaspera:ssrf:user-controlled-url",
        name: "Server-Side Request Forgery via User-Controlled URL",
        description: "User-controlled input is used to construct a URL for server-side HTTP requests. Attackers can make the server request internal resources or external malicious endpoints.",
        category: "ssrf",
        severity: "high",
        confidence: 90,
        enabled: true,
        engines: {
            dataFlow: {
                sources: [
                    { pattern: "req.body.url" },
                    { pattern: "req.query.url" },
                    { pattern: "req.params.url" },
                    { pattern: "req.body.webhook" },
                    { pattern: "req.body.callback" },
                    { pattern: "req.body.redirect" },
                    { pattern: "req.body.target" },
                    { pattern: "req.body.host" },
                    { pattern: "req.query.redirect_uri" },
                ],
                sinks: [
                    { pattern: "fetch($source)" },
                    { pattern: "axios.get($source)" },
                    { pattern: "axios.post($source)" },
                    { pattern: "axios($source)" },
                    { pattern: "request($source)" },
                    { pattern: "http.get($source)" },
                    { pattern: "https.get($source)" },
                    { pattern: "got($source)" },
                    { pattern: "superagent.get($source)" },
                    { pattern: "new URL($source)" },
                ],
                sanitizers: [
                    { pattern: "validateUrl($source)" },
                    { pattern: "isAllowedUrl($source)" },
                    { pattern: "sanitizeUrl($source)" },
                    { pattern: "allowlist.includes($source)" },
                    { pattern: "ALLOWED_HOSTS.includes" },
                ],
            },
        },
        cweIds: ["CWE-918"],
        owaspRefs: ["API8:2023", "A10:2021"],
        autofixPatternId: "add-url-validation",
    },
    {
        id: "vaspera:race:toctou-file",
        name: "Time-of-Check to Time-of-Use Race Condition",
        description: "File existence or permission is checked before use, but the file state may change between check and use. Attackers can exploit this window to manipulate the file.",
        category: "race-condition",
        severity: "medium",
        confidence: 70,
        enabled: true,
        engines: {
            astQuery: {
                pattern: "existsSync($path)",
            },
            dataFlow: {
                sources: [
                    { pattern: "fs.existsSync($path)" },
                    { pattern: "fs.accessSync($path)" },
                    { pattern: "fs.statSync($path)" },
                    { pattern: "path.exists($path)" },
                ],
                sinks: [
                    { pattern: "fs.readFileSync($path)" },
                    { pattern: "fs.writeFileSync($path)" },
                    { pattern: "fs.unlinkSync($path)" },
                    { pattern: "fs.readFile($path)" },
                    { pattern: "fs.writeFile($path)" },
                    { pattern: "fs.unlink($path)" },
                    { pattern: "require($path)" },
                ],
                sanitizers: [
                    { pattern: "fs.open($path, $flags)" },
                    { pattern: "flock($fd)" },
                    { pattern: "lockFile($path)" },
                ],
            },
        },
        cweIds: ["CWE-367", "CWE-362"],
        owaspRefs: ["A04:2021"],
        autofixPatternId: "use-atomic-operations",
    },
    {
        id: "vaspera:sqli:template-literal",
        name: "SQL Injection via Template Literal",
        description: "User input is interpolated directly into SQL query using template literals. Attackers can inject malicious SQL to access, modify, or delete data.",
        category: "sql-injection",
        severity: "critical",
        confidence: 95,
        enabled: true,
        engines: {
            dataFlow: {
                sources: [
                    { pattern: "req.params.$param" },
                    { pattern: "req.query.$param" },
                    { pattern: "req.body.$field" },
                ],
                sinks: [
                    { pattern: "query(`SELECT ... ${$source} ...`)" },
                    { pattern: "execute(`... ${$source} ...`)" },
                    { pattern: "raw(`... ${$source} ...`)" },
                    { pattern: "$connection.query(`... ${$source} ...`)" },
                    { pattern: "db.query(`... ${$source} ...`)" },
                    { pattern: "sql`... ${$source} ...`" },
                ],
                sanitizers: [
                    { pattern: "escape($source)" },
                    { pattern: "sanitize($source)" },
                    { pattern: "parseInt($source)" },
                    { pattern: "Number($source)" },
                ],
            },
        },
        cweIds: ["CWE-89"],
        owaspRefs: ["API8:2023", "A03:2021"],
        autofixPatternId: "parameterize-query",
    },
    {
        id: "vaspera:xss:innerHTML",
        name: "Cross-Site Scripting via innerHTML",
        description: "User input is assigned to innerHTML without sanitization. Attackers can inject malicious scripts that execute in other users' browsers.",
        category: "xss",
        severity: "high",
        confidence: 90,
        enabled: true,
        engines: {
            dataFlow: {
                sources: [
                    { pattern: "req.body.$field" },
                    { pattern: "req.query.$param" },
                    { pattern: "document.location.search" },
                    { pattern: "window.location.hash" },
                    { pattern: "searchParams.get($param)" },
                ],
                sinks: [
                    { pattern: "$el.innerHTML = $source" },
                    { pattern: "$el.outerHTML = $source" },
                    { pattern: "document.write($source)" },
                    { pattern: "insertAdjacentHTML($position, $source)" },
                    { pattern: "dangerouslySetInnerHTML={{ __html: $source }}" },
                ],
                sanitizers: [
                    { pattern: "DOMPurify.sanitize($source)" },
                    { pattern: "sanitizeHtml($source)" },
                    { pattern: "escape($source)" },
                    { pattern: "encodeURIComponent($source)" },
                    { pattern: "textContent = $source" },
                ],
            },
        },
        cweIds: ["CWE-79"],
        owaspRefs: ["A03:2021"],
        autofixPatternId: "use-textContent",
    },
    {
        id: "vaspera:secrets:hardcoded-credential",
        name: "Hardcoded Credential in Source Code",
        description: "API key, password, or other secret is hardcoded in source code. Secrets in code are exposed through version control and can be extracted from compiled artifacts.",
        category: "secrets",
        severity: "critical",
        confidence: 85,
        enabled: true,
        engines: {
            astQuery: {
                pattern: "const $name = $value",
                constraints: {
                    name: "password|apiKey|secret|token|credential|auth",
                },
            },
        },
        cweIds: ["CWE-798", "CWE-259"],
        owaspRefs: ["A02:2021"],
        autofixPatternId: "use-env-variable",
    },
];
export function getBuiltinRules() {
    return BUILTIN_RULES.filter((r) => r.enabled);
}
export function getBuiltinRuleById(id) {
    return BUILTIN_RULES.find((r) => r.id === id);
}
export function getBuiltinRulesByCategory(category) {
    return BUILTIN_RULES.filter((r) => r.category === category && r.enabled);
}
//# sourceMappingURL=builtin.js.map