/**
 * Test Fixtures
 *
 * Labeled test cases for evaluating scanner precision and recall.
 * Each fixture contains vulnerable code with ground truth labels.
 *
 * @module eval/fixtures
 */
/**
 * SQL Injection Fixtures
 */
export const sqlInjectionFixtures = [
    {
        id: "sql-001",
        name: "String Concatenation SQL Injection",
        description: "Classic SQL injection via string concatenation",
        category: "sql-injection",
        source: "OWASP",
        files: [
            {
                path: "db.ts",
                language: "typescript",
                content: `import { Pool } from 'pg';

const pool = new Pool();

// VULNERABLE: SQL injection via string concatenation
export async function getUserByName(name: string) {
  const query = "SELECT * FROM users WHERE name = '" + name + "'";
  return pool.query(query);
}

// SAFE: Parameterized query
export async function getUserById(id: number) {
  const query = "SELECT * FROM users WHERE id = $1";
  return pool.query(query, [id]);
}
`,
            },
        ],
        expectedFindings: [
            {
                file: "db.ts",
                line: 7,
                severity: "critical",
                category: "sql-injection",
                cweId: "CWE-89",
                description: "SQL injection via string concatenation",
                isVulnerable: true,
            },
        ],
        tags: ["owasp-top-10", "injection"],
    },
    {
        id: "sql-002",
        name: "Template Literal SQL Injection",
        description: "SQL injection via template literals",
        category: "sql-injection",
        source: "custom",
        files: [
            {
                path: "search.ts",
                language: "typescript",
                content: `import { db } from './connection';

// VULNERABLE: Template literal injection
export async function searchProducts(term: string) {
  const sql = \`SELECT * FROM products WHERE name LIKE '%\${term}%'\`;
  return db.query(sql);
}

// VULNERABLE: Dynamic ORDER BY
export async function listUsers(sortBy: string) {
  const sql = \`SELECT * FROM users ORDER BY \${sortBy}\`;
  return db.query(sql);
}
`,
            },
        ],
        expectedFindings: [
            {
                file: "search.ts",
                line: 5,
                severity: "critical",
                category: "sql-injection",
                cweId: "CWE-89",
                description: "SQL injection via template literal",
                isVulnerable: true,
            },
            {
                file: "search.ts",
                line: 11,
                severity: "high",
                category: "sql-injection",
                cweId: "CWE-89",
                description: "SQL injection in ORDER BY clause",
                isVulnerable: true,
            },
        ],
        tags: ["injection", "template-literal"],
    },
];
/**
 * XSS Fixtures
 */
export const xssFixtures = [
    {
        id: "xss-001",
        name: "React dangerouslySetInnerHTML",
        description: "XSS via dangerouslySetInnerHTML with user input",
        category: "xss",
        source: "OWASP",
        files: [
            {
                path: "UserProfile.tsx",
                language: "tsx",
                content: `import React from 'react';

interface Props {
  bio: string; // User-controlled content
}

// VULNERABLE: User input passed to dangerouslySetInnerHTML
export function UserProfile({ bio }: Props) {
  return (
    <div>
      <h1>Profile</h1>
      <div dangerouslySetInnerHTML={{ __html: bio }} />
    </div>
  );
}

// SAFE: Text content, not HTML
export function SafeProfile({ bio }: Props) {
  return (
    <div>
      <h1>Profile</h1>
      <div>{bio}</div>
    </div>
  );
}
`,
            },
        ],
        expectedFindings: [
            {
                file: "UserProfile.tsx",
                line: 12,
                severity: "high",
                category: "xss",
                cweId: "CWE-79",
                description: "XSS via dangerouslySetInnerHTML",
                isVulnerable: true,
            },
        ],
        tags: ["owasp-top-10", "react", "xss"],
    },
    {
        id: "xss-002",
        name: "DOM Manipulation XSS",
        description: "XSS via innerHTML assignment",
        category: "xss",
        source: "custom",
        files: [
            {
                path: "comment.ts",
                language: "typescript",
                content: `// VULNERABLE: innerHTML with user input
export function renderComment(userComment: string) {
  const container = document.getElementById('comments');
  if (container) {
    container.innerHTML = userComment;
  }
}

// VULNERABLE: document.write
export function writeMessage(message: string) {
  document.write('<div>' + message + '</div>');
}

// SAFE: textContent
export function renderSafeComment(userComment: string) {
  const container = document.getElementById('comments');
  if (container) {
    container.textContent = userComment;
  }
}
`,
            },
        ],
        expectedFindings: [
            {
                file: "comment.ts",
                line: 5,
                severity: "high",
                category: "xss",
                cweId: "CWE-79",
                description: "XSS via innerHTML",
                isVulnerable: true,
            },
            {
                file: "comment.ts",
                line: 11,
                severity: "high",
                category: "xss",
                cweId: "CWE-79",
                description: "XSS via document.write",
                isVulnerable: true,
            },
        ],
        tags: ["dom-xss"],
    },
];
/**
 * Secrets Fixtures
 */
export const secretsFixtures = [
    {
        id: "secrets-001",
        name: "Hardcoded API Keys",
        description: "Various hardcoded API keys and secrets",
        category: "secrets",
        source: "custom",
        files: [
            {
                path: "config.ts",
                language: "typescript",
                content: `// VULNERABLE: Hardcoded AWS key
export const AWS_ACCESS_KEY = 'AKIAIOSFODNN7EXAMPLE';
export const AWS_SECRET_KEY = 'wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY';

// VULNERABLE: Hardcoded API key
export const STRIPE_SECRET_KEY = 'sk_live_4eC39HqLyjWDarjtT1zdp7dc';

// VULNERABLE: Hardcoded GitHub token
export const GITHUB_TOKEN = 'ghp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';

// SAFE: Environment variable
export const DATABASE_URL = process.env.DATABASE_URL;
`,
            },
        ],
        expectedFindings: [
            {
                file: "config.ts",
                line: 2,
                severity: "critical",
                category: "secrets",
                cweId: "CWE-798",
                description: "Hardcoded AWS access key",
                isVulnerable: true,
            },
            {
                file: "config.ts",
                line: 6,
                severity: "critical",
                category: "secrets",
                cweId: "CWE-798",
                description: "Hardcoded Stripe secret key",
                isVulnerable: true,
            },
            {
                file: "config.ts",
                line: 9,
                severity: "critical",
                category: "secrets",
                cweId: "CWE-798",
                description: "Hardcoded GitHub token",
                isVulnerable: true,
            },
        ],
        tags: ["secrets", "credentials"],
    },
    {
        id: "secrets-002",
        name: "Private Keys",
        description: "Hardcoded private keys",
        category: "secrets",
        source: "custom",
        files: [
            {
                path: "keys.ts",
                language: "typescript",
                content: `// VULNERABLE: Hardcoded private key
export const PRIVATE_KEY = \`-----BEGIN RSA PRIVATE KEY-----
MIIEpQIBAAKCAQEA0Z3VS5JJcds3xfn/ygWyD8YQH3h7ygZdXcBxkN8wF8k
-----END RSA PRIVATE KEY-----\`;

// VULNERABLE: JWT secret
export const JWT_SECRET = 'super-secret-jwt-key-12345';
`,
            },
        ],
        expectedFindings: [
            {
                file: "keys.ts",
                line: 2,
                severity: "critical",
                category: "secrets",
                cweId: "CWE-798",
                description: "Hardcoded private key",
                isVulnerable: true,
            },
            {
                file: "keys.ts",
                line: 7,
                severity: "critical",
                category: "secrets",
                cweId: "CWE-798",
                description: "Hardcoded JWT secret",
                isVulnerable: true,
            },
        ],
        tags: ["secrets", "private-key"],
    },
];
/**
 * Type Safety Fixtures
 */
export const typeSafetyFixtures = [
    {
        id: "type-001",
        name: "Explicit Any Usage",
        description: "Using 'any' type reduces type safety",
        category: "type-safety",
        source: "custom",
        files: [
            {
                path: "handlers.ts",
                language: "typescript",
                content: `// VULNERABLE: Explicit any type
export function processData(data: any) {
  return data.map((item: any) => item.value);
}

// VULNERABLE: Type assertion to any
export function unsafeConvert(input: string) {
  return (input as any).toNumber();
}

// SAFE: Proper typing
interface DataItem {
  value: number;
}

export function processTypedData(data: DataItem[]) {
  return data.map(item => item.value);
}
`,
            },
        ],
        expectedFindings: [
            {
                file: "handlers.ts",
                line: 2,
                severity: "medium",
                category: "type-safety",
                description: "Explicit 'any' type reduces type safety",
                isVulnerable: true,
            },
            {
                file: "handlers.ts",
                line: 8,
                severity: "medium",
                category: "type-safety",
                description: "Unsafe type assertion to any",
                isVulnerable: true,
            },
        ],
        tags: ["typescript", "type-safety"],
    },
    {
        id: "type-002",
        name: "TypeScript Suppressions",
        description: "@ts-ignore and @ts-expect-error usage",
        category: "type-safety",
        source: "custom",
        files: [
            {
                path: "legacy.ts",
                language: "typescript",
                content: `// VULNERABLE: @ts-ignore suppresses errors
// @ts-ignore
const value: number = 'not a number';

// VULNERABLE: @ts-expect-error
// @ts-expect-error intentionally wrong
const result: string = 42;

// SAFE: Proper type handling
const safeValue: number = parseInt('42', 10);
`,
            },
        ],
        expectedFindings: [
            {
                file: "legacy.ts",
                line: 2,
                severity: "low",
                category: "type-safety",
                description: "@ts-ignore suppresses type errors",
                isVulnerable: true,
            },
            {
                file: "legacy.ts",
                line: 6,
                severity: "low",
                category: "type-safety",
                description: "@ts-expect-error suppresses type errors",
                isVulnerable: true,
            },
        ],
        tags: ["typescript", "suppressions"],
    },
];
/**
 * Auth/RLS Bypass Fixtures
 */
export const authFixtures = [
    {
        id: "auth-001",
        name: "Missing Authentication Check",
        description: "API endpoint without authentication",
        category: "auth-bypass",
        source: "custom",
        files: [
            {
                path: "api/users.ts",
                language: "typescript",
                content: `import { Request, Response } from 'express';

// VULNERABLE: No auth check
export async function deleteUser(req: Request, res: Response) {
  const userId = req.params.id;
  await db.query('DELETE FROM users WHERE id = $1', [userId]);
  res.json({ success: true });
}

// SAFE: Auth check present
export async function deleteUserSecure(req: Request, res: Response) {
  if (!req.user?.isAdmin) {
    return res.status(403).json({ error: 'Forbidden' });
  }
  const userId = req.params.id;
  await db.query('DELETE FROM users WHERE id = $1', [userId]);
  res.json({ success: true });
}
`,
            },
        ],
        expectedFindings: [
            {
                file: "api/users.ts",
                line: 4,
                severity: "high",
                category: "auth-bypass",
                cweId: "CWE-862",
                description: "Missing authentication check on sensitive operation",
                isVulnerable: true,
            },
        ],
        tags: ["auth", "access-control"],
    },
];
/**
 * Path Traversal Fixtures
 */
export const pathTraversalFixtures = [
    {
        id: "path-001",
        name: "Path Traversal in File Read",
        description: "User input used directly in file path",
        category: "path-traversal",
        source: "OWASP",
        files: [
            {
                path: "files.ts",
                language: "typescript",
                content: `import { readFile } from 'fs/promises';
import { join } from 'path';

// VULNERABLE: Direct user input in path
export async function getFile(filename: string) {
  const content = await readFile(filename, 'utf-8');
  return content;
}

// VULNERABLE: Path traversal possible
export async function getDocument(docName: string) {
  const path = './documents/' + docName;
  return readFile(path, 'utf-8');
}

// SAFE: Basename extraction and validation
export async function getFileSecure(filename: string) {
  const basename = require('path').basename(filename);
  const safePath = join('./uploads', basename);
  return readFile(safePath, 'utf-8');
}
`,
            },
        ],
        expectedFindings: [
            {
                file: "files.ts",
                line: 6,
                severity: "high",
                category: "path-traversal",
                cweId: "CWE-22",
                description: "Path traversal via direct user input",
                isVulnerable: true,
            },
            {
                file: "files.ts",
                line: 12,
                severity: "high",
                category: "path-traversal",
                cweId: "CWE-22",
                description: "Path traversal via string concatenation",
                isVulnerable: true,
            },
        ],
        tags: ["owasp-top-10", "path-traversal"],
    },
];
/**
 * Command Injection Fixtures
 */
export const commandInjectionFixtures = [
    {
        id: "cmd-001",
        name: "exec with user input",
        description: "Command injection via child_process.exec with string concatenation",
        category: "command-injection",
        source: "OWASP",
        files: [
            {
                path: "utils/git.ts",
                language: "typescript",
                content: `import { exec } from 'child_process';

// VULNERABLE: User input directly in exec
export function cloneRepo(repoUrl: string) {
  exec(\`git clone \${repoUrl}\`);
}

// SAFE: Array-based spawn
import { spawn } from 'child_process';
export function cloneRepoSafe(repoUrl: string) {
  spawn('git', ['clone', repoUrl]);
}
`,
            },
        ],
        expectedFindings: [
            {
                file: "utils/git.ts",
                line: 5,
                severity: "critical",
                category: "command-injection",
                cweId: "CWE-78",
                description: "Command injection via template literal in exec",
                isVulnerable: true,
            },
        ],
        tags: ["owasp-top-10", "injection", "child-process"],
    },
    {
        id: "cmd-002",
        name: "spawn with shell:true",
        description: "Command injection via spawn with shell option enabled",
        category: "command-injection",
        source: "custom",
        files: [
            {
                path: "services/deploy.ts",
                language: "typescript",
                content: `import { spawn } from 'child_process';

// VULNERABLE: shell: true with user input
export function runScript(scriptName: string) {
  spawn(\`./scripts/\${scriptName}.sh\`, { shell: true });
}

// SAFE: No shell option
export function runScriptSafe(scriptName: string) {
  spawn('./scripts/run.sh', [scriptName]);
}
`,
            },
        ],
        expectedFindings: [
            {
                file: "services/deploy.ts",
                line: 5,
                severity: "critical",
                category: "command-injection",
                cweId: "CWE-78",
                description: "shell: true enables command injection",
                isVulnerable: true,
            },
        ],
        tags: ["injection", "shell"],
    },
];
/**
 * SSRF Fixtures
 */
export const ssrfFixtures = [
    {
        id: "ssrf-001",
        name: "Fetch with user-controlled URL",
        description: "SSRF via fetch with user-provided URL",
        category: "ssrf",
        source: "OWASP",
        files: [
            {
                path: "api/proxy.ts",
                language: "typescript",
                content: `// VULNERABLE: Direct user URL in fetch
export async function proxyRequest(url: string) {
  const response = await fetch(url);
  return response.json();
}

// SAFE: URL allowlist
const ALLOWED_HOSTS = ['api.example.com', 'cdn.example.com'];
export async function proxyRequestSafe(url: string) {
  const parsed = new URL(url);
  if (!ALLOWED_HOSTS.includes(parsed.host)) {
    throw new Error('Host not allowed');
  }
  return fetch(url);
}
`,
            },
        ],
        expectedFindings: [
            {
                file: "api/proxy.ts",
                line: 3,
                severity: "high",
                category: "ssrf",
                cweId: "CWE-918",
                description: "SSRF via user-controlled URL in fetch",
                isVulnerable: true,
            },
        ],
        tags: ["owasp-top-10", "ssrf", "network"],
    },
    {
        id: "ssrf-002",
        name: "HTTP client with redirect following",
        description: "SSRF via axios with redirect following to internal networks",
        category: "ssrf",
        source: "custom",
        files: [
            {
                path: "services/webhook.ts",
                language: "typescript",
                content: `import axios from 'axios';

// VULNERABLE: Following redirects to internal networks
export async function callWebhook(webhookUrl: string, payload: object) {
  const response = await axios.post(webhookUrl, payload, {
    maxRedirects: 5, // Can redirect to internal networks
  });
  return response.data;
}

// SAFE: Validate URL and disable redirects
export async function callWebhookSafe(webhookUrl: string, payload: object) {
  const url = new URL(webhookUrl);
  if (url.hostname === 'localhost' || url.hostname.startsWith('192.168.')) {
    throw new Error('Internal URLs not allowed');
  }
  return axios.post(webhookUrl, payload, { maxRedirects: 0 });
}
`,
            },
        ],
        expectedFindings: [
            {
                file: "services/webhook.ts",
                line: 5,
                severity: "high",
                category: "ssrf",
                cweId: "CWE-918",
                description: "SSRF via unvalidated webhook URL",
                isVulnerable: true,
            },
        ],
        tags: ["ssrf", "redirect"],
    },
];
/**
 * XXE Fixtures
 */
export const xxeFixtures = [
    {
        id: "xxe-001",
        name: "XML parsing without disabling external entities",
        description: "XXE via insecure XML parser configuration",
        category: "xxe",
        source: "OWASP",
        files: [
            {
                path: "utils/xml.ts",
                language: "typescript",
                content: `import { DOMParser } from 'xmldom';
import { XMLParser } from 'fast-xml-parser';

// VULNERABLE: Default parser may allow XXE
export function parseXml(xmlString: string) {
  const parser = new DOMParser();
  return parser.parseFromString(xmlString, 'text/xml');
}

// SAFE: fast-xml-parser with external entities disabled
export function parseXmlSafe(xmlString: string) {
  const parser = new XMLParser({
    allowBooleanAttributes: true,
    ignoreAttributes: false,
    // External entities are disabled by default in fast-xml-parser
  });
  return parser.parse(xmlString);
}
`,
            },
        ],
        expectedFindings: [
            {
                file: "utils/xml.ts",
                line: 6,
                severity: "high",
                category: "xxe",
                cweId: "CWE-611",
                description: "XML parser may be vulnerable to XXE",
                isVulnerable: true,
            },
        ],
        tags: ["owasp-top-10", "xxe", "xml"],
    },
];
/**
 * Insecure Deserialization Fixtures
 */
export const insecureDeserializationFixtures = [
    {
        id: "deser-001",
        name: "eval-based JSON parsing",
        description: "Unsafe deserialization using eval",
        category: "insecure-deserialization",
        source: "custom",
        files: [
            {
                path: "utils/parse.ts",
                language: "typescript",
                content: `// VULNERABLE: eval for JSON parsing
export function parseJson(str: string) {
  return eval('(' + str + ')');
}

// VULNERABLE: Function constructor
export function parseJsonAlt(str: string) {
  return new Function('return ' + str)();
}

// SAFE: JSON.parse
export function parseJsonSafe(str: string) {
  return JSON.parse(str);
}
`,
            },
        ],
        expectedFindings: [
            {
                file: "utils/parse.ts",
                line: 3,
                severity: "critical",
                category: "insecure-deserialization",
                cweId: "CWE-502",
                description: "Unsafe deserialization via eval",
                isVulnerable: true,
            },
            {
                file: "utils/parse.ts",
                line: 8,
                severity: "critical",
                category: "insecure-deserialization",
                cweId: "CWE-502",
                description: "Unsafe deserialization via Function constructor",
                isVulnerable: true,
            },
        ],
        tags: ["deserialization", "eval"],
    },
    {
        id: "deser-002",
        name: "YAML unsafe load",
        description: "Unsafe YAML parsing that allows arbitrary code execution",
        category: "insecure-deserialization",
        source: "custom",
        files: [
            {
                path: "config/loader.ts",
                language: "typescript",
                content: `import * as yaml from 'js-yaml';
import { readFileSync } from 'fs';

// VULNERABLE: yaml.load can execute code in YAML 1.0
export function loadConfig(path: string) {
  const content = readFileSync(path, 'utf-8');
  return yaml.load(content); // Deprecated, use safeLoad
}

// SAFE: yaml.safeLoad or schema restriction
export function loadConfigSafe(path: string) {
  const content = readFileSync(path, 'utf-8');
  return yaml.load(content, { schema: yaml.JSON_SCHEMA });
}
`,
            },
        ],
        expectedFindings: [
            {
                file: "config/loader.ts",
                line: 7,
                severity: "high",
                category: "insecure-deserialization",
                cweId: "CWE-502",
                description: "Unsafe YAML loading may allow code execution",
                isVulnerable: true,
            },
        ],
        tags: ["deserialization", "yaml"],
    },
];
/**
 * RLS Bypass / IDOR Fixtures
 */
export const rlsBypassFixtures = [
    {
        id: "rls-001",
        name: "Missing user filter on database query",
        description: "Direct object reference without ownership check",
        category: "rls-bypass",
        source: "custom",
        files: [
            {
                path: "api/documents.ts",
                language: "typescript",
                content: `import { db } from '../db';

// VULNERABLE: No userId filter - IDOR
export async function getDocument(id: string) {
  return db.query('SELECT * FROM documents WHERE id = $1', [id]);
}

// VULNERABLE: No ownership check in update
export async function updateDocument(id: string, content: string) {
  return db.query('UPDATE documents SET content = $2 WHERE id = $1', [id, content]);
}

// SAFE: userId filter present
export async function getDocumentSafe(id: string, userId: string) {
  return db.query(
    'SELECT * FROM documents WHERE id = $1 AND user_id = $2',
    [id, userId]
  );
}
`,
            },
        ],
        expectedFindings: [
            {
                file: "api/documents.ts",
                line: 5,
                severity: "high",
                category: "rls-bypass",
                cweId: "CWE-639",
                description: "Missing ownership filter allows unauthorized access",
                isVulnerable: true,
            },
            {
                file: "api/documents.ts",
                line: 10,
                severity: "high",
                category: "rls-bypass",
                cweId: "CWE-639",
                description: "Missing ownership check on update operation",
                isVulnerable: true,
            },
        ],
        tags: ["access-control", "idor", "authorization"],
    },
    {
        id: "rls-002",
        name: "Supabase RLS bypass via service role",
        description: "Using service role key bypasses RLS policies",
        category: "rls-bypass",
        source: "custom",
        files: [
            {
                path: "lib/supabase.ts",
                language: "typescript",
                content: `import { createClient } from '@supabase/supabase-js';

// VULNERABLE: Service role bypasses RLS
export const adminClient = createClient(
  process.env.SUPABASE_URL!,
  process.env.SUPABASE_SERVICE_ROLE_KEY! // Bypasses RLS
);

export async function deleteAnyUser(userId: string) {
  // This bypasses all RLS policies!
  return adminClient.from('users').delete().eq('id', userId);
}

// SAFE: Use anon key with user context
export const publicClient = createClient(
  process.env.SUPABASE_URL!,
  process.env.SUPABASE_ANON_KEY!
);

export async function deleteOwnUser(userId: string, accessToken: string) {
  const client = createClient(
    process.env.SUPABASE_URL!,
    process.env.SUPABASE_ANON_KEY!,
    { global: { headers: { Authorization: \`Bearer \${accessToken}\` } } }
  );
  return client.from('users').delete().eq('id', userId);
}
`,
            },
        ],
        expectedFindings: [
            {
                file: "lib/supabase.ts",
                line: 10,
                severity: "high",
                category: "rls-bypass",
                cweId: "CWE-639",
                description: "Service role key usage bypasses RLS policies",
                isVulnerable: true,
            },
        ],
        tags: ["supabase", "rls", "authorization"],
    },
];
/**
 * All fixtures combined
 */
export const ALL_FIXTURES = [
    ...sqlInjectionFixtures,
    ...xssFixtures,
    ...secretsFixtures,
    ...typeSafetyFixtures,
    ...authFixtures,
    ...pathTraversalFixtures,
    ...commandInjectionFixtures,
    ...ssrfFixtures,
    ...xxeFixtures,
    ...insecureDeserializationFixtures,
    ...rlsBypassFixtures,
];
/**
 * Get fixtures by category
 */
export function getFixturesByCategory(category) {
    return ALL_FIXTURES.filter((f) => f.category === category);
}
/**
 * Get fixtures by tag
 */
export function getFixturesByTag(tag) {
    return ALL_FIXTURES.filter((f) => f.tags?.includes(tag));
}
/**
 * Get fixture by ID
 */
export function getFixtureById(id) {
    return ALL_FIXTURES.find((f) => f.id === id);
}
/**
 * Get fixture statistics
 */
export function getFixtureStats() {
    const byCategory = {};
    let totalExpected = 0;
    for (const fixture of ALL_FIXTURES) {
        byCategory[fixture.category] = (byCategory[fixture.category] || 0) + 1;
        totalExpected += fixture.expectedFindings.length;
    }
    return {
        total: ALL_FIXTURES.length,
        byCategory,
        totalExpected,
    };
}
//# sourceMappingURL=fixtures.js.map