/**
 * Prompt Injection Payload Corpus Loader
 *
 * Loads and manages injection payloads for fuzzing MCP tool inputs.
 * Payloads are organized by category and can be extended with custom payloads.
 *
 * @module scanners/agent/payloads
 */
import { readFile, readdir } from "fs/promises";
import { join, dirname } from "path";
import { fileURLToPath } from "url";
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
/**
 * Corpus size presets
 */
export const CORPUS_SIZES = {
    quick: 100, // Fast CI runs
    standard: 400, // Default comprehensive
    thorough: 800, // Deep analysis
    exhaustive: 1500, // Full corpus - all payloads
};
/**
 * Load all payloads from a category file
 */
async function loadCategoryFile(filePath) {
    try {
        const content = await readFile(filePath, "utf-8");
        const data = JSON.parse(content);
        return data.payloads.map((p) => ({
            id: p.id,
            text: p.text,
            category: data.category,
            severity: p.severity,
            description: p.description,
            tags: p.tags,
            source: data.source,
        }));
    }
    catch (error) {
        console.warn(`Failed to load payload file ${filePath}:`, error);
        return [];
    }
}
/**
 * Load custom payloads from a directory
 */
async function loadCustomPayloads(customDir) {
    try {
        const files = await readdir(customDir);
        const jsonFiles = files.filter((f) => f.endsWith(".json"));
        const payloads = [];
        for (const file of jsonFiles) {
            const filePath = join(customDir, file);
            const loaded = await loadCategoryFile(filePath);
            payloads.push(...loaded);
        }
        return payloads;
    }
    catch {
        return [];
    }
}
/**
 * Load all payloads with optional filtering
 */
export async function loadPayloads(options) {
    const payloads = [];
    // Load built-in payloads
    const builtInFiles = [
        // Original 8 categories
        "override-instructions.json",
        "exfil-prompts.json",
        "homoglyphs.json",
        "tag-smuggling.json",
        "indirect-injection.json",
        "jailbreak.json",
        "system-prompt-extraction.json",
        "tool-misuse.json",
        // New 7 categories for expanded corpus
        "multi-turn.json",
        "context-manipulation.json",
        "output-redirection.json",
        "token-smuggling.json",
        "mcp-attacks.json",
        "tool-chaining.json",
        "privilege-escalation.json",
    ];
    for (const file of builtInFiles) {
        const filePath = join(__dirname, file);
        const loaded = await loadCategoryFile(filePath);
        payloads.push(...loaded);
    }
    // Load custom payloads if specified
    if (options?.customCorpus) {
        const customPayloads = await loadCustomPayloads(options.customCorpus);
        payloads.push(...customPayloads);
    }
    // Load from default custom directory
    const defaultCustomDir = join(__dirname, "custom");
    const defaultCustom = await loadCustomPayloads(defaultCustomDir);
    payloads.push(...defaultCustom);
    // Filter by categories if specified
    let filtered = payloads;
    if (options?.categories && options.categories.length > 0) {
        filtered = filtered.filter((p) => options.categories.includes(p.category));
    }
    // Filter by minimum severity
    if (options?.minSeverity) {
        const severityOrder = {
            critical: 4,
            high: 3,
            medium: 2,
            low: 1,
            info: 0,
        };
        const minOrder = severityOrder[options.minSeverity];
        filtered = filtered.filter((p) => severityOrder[p.severity] >= minOrder);
    }
    // Limit by corpus size
    const corpusSize = CORPUS_SIZES[options?.corpus || "standard"];
    if (filtered.length > corpusSize) {
        // Prioritize higher severity payloads
        filtered.sort((a, b) => {
            const severityOrder = {
                critical: 4,
                high: 3,
                medium: 2,
                low: 1,
                info: 0,
            };
            return severityOrder[b.severity] - severityOrder[a.severity];
        });
        filtered = filtered.slice(0, corpusSize);
    }
    return filtered;
}
/**
 * Get payload statistics
 */
export async function getPayloadStats() {
    const payloads = await loadPayloads({ corpus: "exhaustive" });
    const byCategory = {
        // Original 8 categories
        "override-instructions": 0,
        "exfil-prompt": 0,
        "homoglyph": 0,
        "tag-smuggling": 0,
        "indirect-injection": 0,
        "jailbreak": 0,
        "system-prompt-extraction": 0,
        "tool-misuse": 0,
        // New 7 categories
        "multi-turn": 0,
        "context-manipulation": 0,
        "output-redirection": 0,
        "token-smuggling": 0,
        "mcp-specific": 0,
        "tool-chaining": 0,
        "privilege-escalation": 0,
    };
    const bySeverity = {
        critical: 0,
        high: 0,
        medium: 0,
        low: 0,
        info: 0,
    };
    for (const payload of payloads) {
        byCategory[payload.category]++;
        bySeverity[payload.severity]++;
    }
    return {
        total: payloads.length,
        byCategory,
        bySeverity,
    };
}
/**
 * Generate a randomized subset of payloads for testing
 */
export async function getRandomPayloads(count) {
    const allPayloads = await loadPayloads({ corpus: "exhaustive" });
    // Fisher-Yates shuffle
    const shuffled = [...allPayloads];
    for (let i = shuffled.length - 1; i > 0; i--) {
        const j = Math.floor(Math.random() * (i + 1));
        [shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]];
    }
    return shuffled.slice(0, Math.min(count, shuffled.length));
}
/**
 * Get payloads by specific tags
 */
export async function getPayloadsByTags(tags) {
    const allPayloads = await loadPayloads({ corpus: "exhaustive" });
    return allPayloads.filter((p) => {
        if (!p.tags)
            return false;
        return tags.some((tag) => p.tags.includes(tag));
    });
}
//# sourceMappingURL=index.js.map