"use strict";
/**
 * The OWASP-Agentic scanner must recognize REAL-WORLD tool names, not just
 * Claude-native ids. Customer manifests declare tools like `shell_exec`,
 * `network_request`, `file_write` (snake_case) — the capability matchers were
 * exact-set, so these were invisible and EVERY agent scored identically
 * (Thomas 2026-06-05: "all agents are the same … I do not understand why they
 * are not getting different scores"). Token-aware matching fixes it.
 *
 * RED before: snake_case dangerous tools produced no trifecta / no shell/fs/net
 * findings, so a high-risk agent and a read-only agent got the same findings.
 */
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const node_test_1 = require("node:test");
const strict_1 = __importDefault(require("node:assert/strict"));
const owasp_agentic_scanner_1 = require("./owasp-agentic-scanner");
const base = {
    hooks: { preToolUse: false, postToolUse: false, postResponse: false },
    llmProvider: 'anthropic',
    killSwitchCapable: true,
};
// A high-risk agent declared with snake_case tool names (real customer manifest).
const HEALTHCARE = ['lookup_patient_record', 'write_triage_note', 'shell_exec', 'network_request', 'file_write'];
// A read-only agent.
const DOCSEARCH = ['vector_search', 'fetch_document'];
(0, node_test_1.describe)('OWASP scanner recognizes custom snake_case tool names', () => {
    (0, node_test_1.it)('snake_case shell+network+file_write triggers the Lethal Trifecta (CRIT)', () => {
        const r = (0, owasp_agentic_scanner_1.scanAgent)({ agentId: 'hc', name: 'hc', tools: HEALTHCARE, ...base });
        const trifecta = r.findings.find((f) => f.risk === owasp_agentic_scanner_1.OWASP_AGENTIC_RISK.A01_PROMPT_INJECTION && /Lethal Trifecta/i.test(f.title));
        strict_1.default.ok(trifecta, 'shell_exec + network_request + file_write must be detected as the trifecta');
        strict_1.default.equal(trifecta.severity, 'CRIT');
    });
    (0, node_test_1.it)('a read-only agent does NOT trigger the trifecta', () => {
        const r = (0, owasp_agentic_scanner_1.scanAgent)({ agentId: 'ds', name: 'ds', tools: DOCSEARCH, ...base });
        strict_1.default.ok(!r.findings.some((f) => /Lethal Trifecta/i.test(f.title)));
    });
    (0, node_test_1.it)('snake_case dangerous tools surface ungated-capability (A08) findings', () => {
        const r = (0, owasp_agentic_scanner_1.scanAgent)({ agentId: 'hc', name: 'hc', tools: HEALTHCARE, ...base });
        const a08 = r.findings.filter((f) => f.risk === owasp_agentic_scanner_1.OWASP_AGENTIC_RISK.A08_EXCESSIVE_AGENCY);
        strict_1.default.ok(a08.length > 0, 'shell_exec / file_write must produce ungated-capability findings');
    });
    (0, node_test_1.it)('a high-risk agent scores strictly lower than a read-only agent (differentiation)', () => {
        const hc = (0, owasp_agentic_scanner_1.scanAgent)({ agentId: 'hc', name: 'hc', tools: HEALTHCARE, ...base });
        const ds = (0, owasp_agentic_scanner_1.scanAgent)({ agentId: 'ds', name: 'ds', tools: DOCSEARCH, ...base });
        // The trifecta + ungated caps must make healthcare produce MORE / WORSE
        // findings than the read-only agent — the input to a differentiated build axis.
        const crit = (r) => r.findings.filter((f) => f.severity === 'CRIT').length;
        strict_1.default.ok(crit(hc) > crit(ds), 'high-risk agent must have more CRIT findings');
        strict_1.default.ok(hc.findings.length > ds.findings.length, 'high-risk agent must have more findings overall');
    });
    // Semantic egress channels (Thomas 2026-06-05): `send_email`, `upload_file`,
    // webhook posts, etc. are real data-exfiltration vectors but were invisible to
    // NETWORK_EGRESS_TOOLS, so a customer-support agent that can email data out
    // scored identically to a pure read-only PDF analyzer. Recognize them.
    const isEgressFinding = (f) => /Pattern-only injection detection/i.test(f.title);
    (0, node_test_1.it)('send_email is recognized as a network-egress (exfiltration) capability', () => {
        const r = (0, owasp_agentic_scanner_1.scanAgent)({ agentId: 'cs', name: 'cs', tools: ['lookup_order', 'send_email', 'create_ticket'], ...base });
        strict_1.default.ok(r.findings.some(isEgressFinding), 'send_email must be treated as untrusted-content egress');
    });
    (0, node_test_1.it)('upload_file is recognized as a network-egress capability', () => {
        const r = (0, owasp_agentic_scanner_1.scanAgent)({ agentId: 'up', name: 'up', tools: ['upload_file'], ...base });
        strict_1.default.ok(r.findings.some(isEgressFinding), 'upload_file must be treated as egress');
    });
    (0, node_test_1.it)('a genuinely benign read-only agent has NO egress finding (no false positive)', () => {
        const r = (0, owasp_agentic_scanner_1.scanAgent)({ agentId: 'fin', name: 'fin', tools: ['extract_pdf_text', 'compute_metrics'], ...base });
        strict_1.default.ok(!r.findings.some(isEgressFinding), 'benign compute tools must NOT be flagged as egress');
    });
    (0, node_test_1.it)('an email-capable agent has strictly more findings than a benign compute agent', () => {
        const cs = (0, owasp_agentic_scanner_1.scanAgent)({ agentId: 'cs', name: 'cs', tools: ['lookup_order', 'send_email', 'create_ticket'], ...base });
        const fin = (0, owasp_agentic_scanner_1.scanAgent)({ agentId: 'fin', name: 'fin', tools: ['extract_pdf_text', 'compute_metrics'], ...base });
        strict_1.default.ok(cs.findings.length > fin.findings.length, 'exfil-capable agent must differentiate above a benign one');
    });
});
//# sourceMappingURL=owasp-scanner-custom-tool-names.test.js.map