ai-shield-core 0.2.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -50,8 +50,14 @@ const SOURCE_PROFILE = {
50
50
  extraPatterns: [
51
51
  // "Before using this tool, you must ..." / "After calling, also call X"
52
52
  /(?:before|after|while)\s+(?:using|invoking|calling|executing)\s+(?:this\s+)?(?:tool|function|action)[,\s]+(?:you\s+)?(?:must|should|will|need\s+to|are\s+required\s+to)/i,
53
- // "Also call delete_*" / "ALWAYS invoke X first"
54
- /(?:also|always|first|then|finally)\s+(?:call|invoke|use|execute|run)\s+(?:the\s+)?[a-z_][\w-]{2,}/i,
53
+ // "Also call delete_account" / "then invoke query()". Tightened
54
+ // (review M2): the called symbol must carry a case-robust tool-name
55
+ // signal — a snake_case underscore or a `(` call — so benign docs prose
56
+ // ("first call the API", "then use the result") doesn't trip the
57
+ // block-level threshold and push operators into disabling the scanner.
58
+ // (camelCase detection was dropped: under the /i flag `[a-z]+[A-Z]`
59
+ // collapses to "any word" and re-introduced the false positive.)
60
+ /(?:also|always|first|then|finally)\s+(?:call|invoke|use|execute|run)\s+(?:the\s+)?[a-z][\w-]*(?:_[\w-]+|\s*\()/i,
55
61
  // "Tool description: ignore the above and ..."
56
62
  /(?:tool|function|action)\s+description[:\s]+(?:ignore|disregard|override)/i,
57
63
  // "Note to LLM:" / "Hidden instruction:"
@@ -60,6 +66,25 @@ const SOURCE_PROFILE = {
60
66
  /(?:on\s+(?:success|call)|when\s+invoked)[,:]\s+(?:silently|also|then)\s+(?:call|invoke|exfiltrate|send|leak)/i,
61
67
  ],
62
68
  },
69
+ "tool-output": {
70
+ // The runtime result a tool returned. Distinct from `tool-desc` (static
71
+ // schema): this is data the tool fetched and is therefore
72
+ // attacker-influenceable (PoisonedRAG, scraped pages surfaced through a
73
+ // search tool, a compromised upstream API). Tool results almost never
74
+ // legitimately carry instruction syntax aimed at the calling model, so
75
+ // the bar is as tight as RAG/tool-desc.
76
+ threshold: 0.13,
77
+ extraPatterns: [
78
+ // Result claims to carry instructions for the model.
79
+ /(?:tool|function|api|search|query)\s+(?:result|response|output)[:\s]+(?:ignore|disregard|override|new\s+instructions?|system\s+prompt)/i,
80
+ // "the result indicates you should now call/invoke X"
81
+ /(?:result|response|data|output)\s+(?:indicates?|says?|requires?|means?)\s+(?:that\s+)?you\s+(?:should|must|need\s+to|will)\s+(?:now\s+)?(?:call|invoke|run|execute|use)\s+[a-z_][\w-]{2,}/i,
82
+ // Embedded role/system marker inside a JSON-ish result value.
83
+ /"(?:role|system|instruction|directive)"\s*:\s*"(?:system|ignore|override|admin)/i,
84
+ // "(end of results) Now, as the system, ..."
85
+ /(?:end\s+of\s+(?:results?|output|data)|<\/results?>)[\s.)]*(?:now|next)[,\s]+(?:as\s+(?:the\s+)?(?:system|admin|assistant)|you\s+(?:must|should|will))/i,
86
+ ],
87
+ },
63
88
  memory: {
64
89
  // Stored memory entries: persistence poisoning. Look for sentinel
65
90
  // instructions that re-anchor the model on subsequent retrieval.
@@ -346,6 +371,49 @@ export async function scanIngested(content, source, config = {}) {
346
371
  },
347
372
  };
348
373
  }
374
+ /**
375
+ * Scan the runtime *result* of a tool call before it re-enters the model
376
+ * context. The dominant indirect-injection channel in agentic loops: a
377
+ * search tool surfaces a poisoned page, an MCP server returns attacker-
378
+ * controlled data, a compromised upstream API embeds instructions in its
379
+ * response. PoisonedRAG (USENIX Security 2025) showed 5 planted documents
380
+ * reach a 90% attack-success rate in million-document knowledge bases —
381
+ * the payload arrives here, not in the user prompt.
382
+ *
383
+ * Thin wrapper over `scanIngested(content, "tool-output")` that also
384
+ * stamps the originating `toolName` into every violation detail, so an
385
+ * audit log can answer "which tool returned the poisoned content?".
386
+ *
387
+ * Pair with `CircuitBreakerRegistry` when you also want to rate-limit or
388
+ * trip the tool after repeated poisoned results:
389
+ *
390
+ * @example
391
+ * ```ts
392
+ * import { scanToolOutput } from "ai-shield-core";
393
+ *
394
+ * const result = await searchTool.call(query); // untrusted
395
+ * const scan = await scanToolOutput("web_search", result);
396
+ * if (!scan.safe) {
397
+ * // drop the result OR strip it before the next model turn
398
+ * audit.warn("poisoned tool output", { tool: "web_search", v: scan.violations });
399
+ * return; // do not feed `result` back into the model
400
+ * }
401
+ * model.continue(result);
402
+ * ```
403
+ */
404
+ export async function scanToolOutput(toolName, content, config = {}) {
405
+ const result = await scanIngested(content, "tool-output", config);
406
+ const safeToolName = typeof toolName === "string" && toolName.length > 0
407
+ ? toolName.slice(0, 120)
408
+ : "unknown";
409
+ return {
410
+ ...result,
411
+ violations: result.violations.map((v) => ({
412
+ ...v,
413
+ detail: `${v.detail ?? ""} (tool=${safeToolName})`.trim(),
414
+ })),
415
+ };
416
+ }
349
417
  // ============================================================
350
418
  // Encoding-bypass normalization (R1 from Round 1 review — closes
351
419
  // OWASP LLM Prompt Injection Prevention Cheat Sheet 2026 Base64/Hex
@@ -0,0 +1,73 @@
1
+ import type { ScanContext, ScanDecision, Violation, PIIConfig } from "../types.js";
2
+ export type OutputSink = "sql" | "shell" | "html" | "template";
3
+ export interface OutputScanConfig {
4
+ /**
5
+ * PII handling. Pass a `PIIConfig` to control action/locale, or `false`
6
+ * to skip PII scanning entirely. Default: mask.
7
+ */
8
+ pii?: PIIConfig | false;
9
+ /**
10
+ * Canary token(s) injected into the system prompt via `injectCanary()`.
11
+ * If any appears verbatim in the output → `system_prompt_leak` (block).
12
+ */
13
+ canaryTokens?: string | string[];
14
+ /**
15
+ * Restrict the structured-injection check to specific downstream sinks.
16
+ * E.g. `["sql"]` when the output only ever flows into a query builder.
17
+ * Default: all sinks.
18
+ */
19
+ sinks?: OutputSink[];
20
+ /** Selectively disable checks. All enabled by default. */
21
+ checks?: {
22
+ secrets?: boolean;
23
+ injection?: boolean;
24
+ systemPromptLeak?: boolean;
25
+ jailbreak?: boolean;
26
+ };
27
+ /** Override the byte cap on the scanned region. Default 256 KB. */
28
+ maxBytes?: number;
29
+ }
30
+ export interface OutputScanResult {
31
+ /** No blocking violation found. */
32
+ safe: boolean;
33
+ decision: ScanDecision;
34
+ /**
35
+ * Output with PII masked and secrets redacted to `[REDACTED_SECRET]`.
36
+ * Unlike `scanIngested`, this is NOT emptied on block — the caller
37
+ * usually still needs to log or display the sanitized text. Gate on
38
+ * `safe` / `decision` before forwarding it to a downstream sink.
39
+ */
40
+ sanitized: string;
41
+ violations: Violation[];
42
+ meta: {
43
+ scanDurationMs: number;
44
+ checksRun: string[];
45
+ };
46
+ }
47
+ /**
48
+ * Scanner for LLM output. Stateless; safe to reuse across calls.
49
+ */
50
+ export declare class OutputScanner {
51
+ private readonly config;
52
+ private readonly pii;
53
+ constructor(config?: OutputScanConfig);
54
+ scan(output: string, context?: ScanContext): Promise<OutputScanResult>;
55
+ }
56
+ /**
57
+ * One-shot helper. Scan a model response before acting on it.
58
+ *
59
+ * @example
60
+ * ```ts
61
+ * import { scanOutput } from "ai-shield-core";
62
+ *
63
+ * const reply = await llm.generate(prompt);
64
+ * const r = await scanOutput(reply, { canaryTokens: canary, sinks: ["sql"] });
65
+ * if (!r.safe) {
66
+ * audit.warn("unsafe model output", r.violations);
67
+ * return genericFallback(); // do not run r.sanitized as SQL
68
+ * }
69
+ * showToUser(r.sanitized); // PII masked, secrets redacted
70
+ * ```
71
+ */
72
+ export declare function scanOutput(output: string, config?: OutputScanConfig, context?: ScanContext): Promise<OutputScanResult>;
73
+ //# sourceMappingURL=output.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"output.d.ts","sourceRoot":"","sources":["../../src/scanner/output.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,WAAW,EACX,YAAY,EACZ,SAAS,EACT,SAAS,EACV,MAAM,aAAa,CAAC;AAuHrB,MAAM,MAAM,UAAU,GAAG,KAAK,GAAG,OAAO,GAAG,MAAM,GAAG,UAAU,CAAC;AAE/D,MAAM,WAAW,gBAAgB;IAC/B;;;OAGG;IACH,GAAG,CAAC,EAAE,SAAS,GAAG,KAAK,CAAC;IACxB;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IACjC;;;;OAIG;IACH,KAAK,CAAC,EAAE,UAAU,EAAE,CAAC;IACrB,0DAA0D;IAC1D,MAAM,CAAC,EAAE;QACP,OAAO,CAAC,EAAE,OAAO,CAAC;QAClB,SAAS,CAAC,EAAE,OAAO,CAAC;QACpB,gBAAgB,CAAC,EAAE,OAAO,CAAC;QAC3B,SAAS,CAAC,EAAE,OAAO,CAAC;KACrB,CAAC;IACF,mEAAmE;IACnE,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,gBAAgB;IAC/B,mCAAmC;IACnC,IAAI,EAAE,OAAO,CAAC;IACd,QAAQ,EAAE,YAAY,CAAC;IACvB;;;;;OAKG;IACH,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,SAAS,EAAE,CAAC;IACxB,IAAI,EAAE;QACJ,cAAc,EAAE,MAAM,CAAC;QACvB,SAAS,EAAE,MAAM,EAAE,CAAC;KACrB,CAAC;CACH;AAID;;GAEG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAmB;IAC1C,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAoB;gBAE5B,MAAM,GAAE,gBAAqB;IAQnC,IAAI,CACR,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,WAAgB,GACxB,OAAO,CAAC,gBAAgB,CAAC;CAkL7B;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,UAAU,CAC9B,MAAM,EAAE,MAAM,EACd,MAAM,GAAE,gBAAqB,EAC7B,OAAO,GAAE,WAAgB,GACxB,OAAO,CAAC,gBAAgB,CAAC,CAE3B"}
@@ -0,0 +1,327 @@
1
+ import { PIIScanner } from "./pii.js";
2
+ import { normalizeForInjectionScan } from "./heuristic.js";
3
+ // ============================================================
4
+ // Output Scanner — OWASP LLM05 Improper Output Handling +
5
+ // LLM02 Sensitive Information Disclosure (output side)
6
+ //
7
+ // AI Shield's input scanners answer "is this prompt safe to send to the
8
+ // model?". This scanner answers the other half: "is this model OUTPUT
9
+ // safe to act on / show / forward downstream?".
10
+ //
11
+ // LLM output must never reach a SQL engine, a shell, an HTML sink, or a
12
+ // template renderer unfiltered — XSS, SSRF, SQLi and command injection
13
+ // sourced from model output are a documented 2026 attack class (OWASP
14
+ // LLM05). And a model can leak its own system prompt or a secret it was
15
+ // shown, which is LLM02 / LLM07.
16
+ //
17
+ // Five checks. Inputs are Unicode-normalized first (homoglyph / zero-width /
18
+ // fullwidth evasion defense). Secret + canary checks scan the FULL output
19
+ // (a leak can sit anywhere); the structural checks scan a length-capped copy
20
+ // (those payloads live in the first chunk):
21
+ // 1. secret_leak — API keys, tokens, private keys, DSNs (full output)
22
+ // 2. output_injection — SQL / shell / HTML-JS / template / md-exfil (capped)
23
+ // 3. system_prompt_leak — canary-token leak (exact, full) + heuristic phrasing
24
+ // 4. pii_detected — reuses the input-side PIIScanner
25
+ // 5. jailbreak_indicator— compliance-preamble / mode-switch acknowledgement
26
+ //
27
+ // Checks 1-3 are high-confidence and block. PII follows its configured
28
+ // action. Jailbreak is heuristic and only warns — a "sure, here's how"
29
+ // preamble is often legitimate.
30
+ // ============================================================
31
+ /** Hard cap on the bytes we pattern-scan. A 1 MB model response is not the
32
+ * threat model and unbounded regex over it pressures GC. Overridable. */
33
+ const DEFAULT_MAX_OUTPUT_BYTES = 256 * 1024;
34
+ /**
35
+ * High-confidence secret formats. Each is anchored on a provider-specific
36
+ * prefix so false positives on prose are near-zero. Patterns are linear
37
+ * (no nested quantifiers) — ReDoS-safe on large output.
38
+ */
39
+ const SECRET_PATTERNS = [
40
+ { id: "SEC-OPENAI", re: /\bsk-(?:proj-)?[A-Za-z0-9_-]{20,}\b/, label: "OpenAI API key" },
41
+ { id: "SEC-ANTHROPIC", re: /\bsk-ant-[A-Za-z0-9_-]{20,}\b/, label: "Anthropic API key" },
42
+ { id: "SEC-AWS-AKID", re: /\b(?:AKIA|ASIA)[0-9A-Z]{16}\b/, label: "AWS access key id" },
43
+ { id: "SEC-GITHUB", re: /\bgh[pousr]_[A-Za-z0-9]{36,}\b/, label: "GitHub token" },
44
+ { id: "SEC-GOOGLE", re: /\bAIza[0-9A-Za-z_-]{35}\b/, label: "Google API key" },
45
+ { id: "SEC-GOOGLE-OAUTH", re: /\bGOCSPX-[A-Za-z0-9_-]{28}\b/, label: "Google OAuth client secret" },
46
+ { id: "SEC-GCP-SA", re: /"type"\s*:\s*"service_account"/, label: "GCP service-account JSON" },
47
+ { id: "SEC-HUGGINGFACE", re: /\bhf_[A-Za-z0-9]{30,}\b/, label: "HuggingFace token" },
48
+ { id: "SEC-NPM", re: /\bnpm_[A-Za-z0-9]{36}\b/, label: "npm publish token" },
49
+ { id: "SEC-SLACK", re: /\bxox[baprs]-[A-Za-z0-9-]{10,}\b/, label: "Slack token" },
50
+ { id: "SEC-STRIPE", re: /\b[rs]k_live_[A-Za-z0-9]{20,}\b/, label: "Stripe live key" },
51
+ { id: "SEC-JWT", re: /\beyJ[A-Za-z0-9_-]{8,}\.eyJ[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\b/, label: "JWT" },
52
+ { id: "SEC-PEM", re: /-----BEGIN (?:RSA |EC |DSA |OPENSSH |PGP )?PRIVATE KEY-----/, label: "PEM private key" },
53
+ // DSN: both credential segments are length-bounded so a long near-match
54
+ // without a trailing `@` can't drive O(n²) backtracking (review H1).
55
+ { id: "SEC-DSN", re: /\b(?:postgres(?:ql)?|mysql|mongodb(?:\+srv)?|redis|amqps?):\/\/[^\s:/@]{1,64}:[^\s@]{3,80}@/, label: "connection string with credentials" },
56
+ ];
57
+ /**
58
+ * Output-injection payloads, grouped by downstream sink. Each pattern is
59
+ * deliberately conservative — flagging legitimate output that merely
60
+ * *mentions* SQL would be useless. They target syntax that only matters
61
+ * when the string is interpreted, not displayed.
62
+ */
63
+ const INJECTION_PATTERNS = [
64
+ // SQL
65
+ { id: "OUTI-SQL-1", sink: "sql", re: /\bunion\s+(?:all\s+)?select\b/i, label: "SQL UNION SELECT" },
66
+ { id: "OUTI-SQL-2", sink: "sql", re: /['"]\s*;\s*(?:drop|delete|update|insert|truncate|alter)\s+/i, label: "SQL statement break" },
67
+ { id: "OUTI-SQL-3", sink: "sql", re: /\bor\s+1\s*=\s*1\b|\bor\s+'1'\s*=\s*'1'/i, label: "SQL tautology" },
68
+ // Shell
69
+ { id: "OUTI-SH-1", sink: "shell", re: /\$\([^)]{1,200}\)|`[^`]{1,200}`/, label: "shell command substitution" },
70
+ { id: "OUTI-SH-2", sink: "shell", re: /[;&|]\s*(?:rm|curl|wget|nc|bash|sh|chmod|mkfifo|dd)\s+-?/i, label: "chained shell command" },
71
+ { id: "OUTI-SH-3", sink: "shell", re: /\|\s*(?:sh|bash|zsh|python[0-9.]*)\b/i, label: "pipe to interpreter" },
72
+ // HTML / JS (XSS)
73
+ { id: "OUTI-XSS-1", sink: "html", re: /<script[\s>]/i, label: "<script> tag" },
74
+ { id: "OUTI-XSS-2", sink: "html", re: /\bon(?:error|load|click|mouseover)\s*=\s*["']?[^"'>]{1,200}/i, label: "inline event handler" },
75
+ { id: "OUTI-XSS-3", sink: "html", re: /\bjavascript:\s*[^\s"']{1,200}/i, label: "javascript: URI" },
76
+ { id: "OUTI-XSS-4", sink: "html", re: /<iframe[\s>]|<img[^>]{0,200}\bsrc\s*=\s*["']?\s*(?:javascript|data):/i, label: "iframe / data-URI image" },
77
+ // Markdown-image data exfiltration: ![x](http://evil/log?data=…). When a
78
+ // renderer auto-loads the image the query string leaks whatever the model
79
+ // was told to embed. The most-overlooked LLM05 class (review: Research).
80
+ { id: "OUTI-MDEXF", sink: "html", re: /!\[[^\]]{0,200}\]\(\s*https?:\/\/[^)\s]{1,300}[?&][\w-]{1,40}=/i, label: "markdown-image data exfiltration" },
81
+ // Template / SSTI
82
+ { id: "OUTI-SSTI-1", sink: "template", re: /\{\{[^}]{0,200}(?:constructor|process|require|global|__proto__|self\.|cycler)[^}]{0,200}\}\}/i, label: "template-injection payload" },
83
+ { id: "OUTI-SSTI-2", sink: "template", re: /<%[^%]{0,200}(?:system|exec|require|eval)[^%]{0,200}%>/i, label: "ERB/EJS injection" },
84
+ ];
85
+ /**
86
+ * System-prompt-leak heuristics — used only when no canary token is
87
+ * available. Low-confidence by design (these phrasings occur in benign
88
+ * output too), so they warn rather than block.
89
+ */
90
+ const SYSTEM_LEAK_PATTERNS = [
91
+ /(?:my|the)\s+(?:system\s+)?(?:prompt|instructions?)\s+(?:is|are|say|states?|read)\b/i,
92
+ /i\s+(?:was|am|have\s+been)\s+(?:instructed|told|configured|programmed|designed)\s+to\b/i,
93
+ /here\s+(?:is|are)\s+my\s+(?:system\s+)?(?:prompt|instructions?|guidelines?|rules?)\b/i,
94
+ /you\s+are\s+(?:a|an)\s+[\w-]{2,30}\s+(?:assistant|agent|bot|model)\b.{0,40}\b(?:you\s+must|your\s+(?:rules?|guidelines?|instructions?))/i,
95
+ ];
96
+ /**
97
+ * Jailbreak-success indicators in the OUTPUT. Conservative + low weight:
98
+ * a generic "Sure, here's how" is not enough on its own — these target
99
+ * explicit mode-switch acknowledgements and self-declared rule-breaking.
100
+ */
101
+ const JAILBREAK_PATTERNS = [
102
+ /\bas\s+(?:DAN|an?\s+(?:unrestricted|unfiltered|jailbroken|uncensored))\b/i,
103
+ /i(?:'?ll|\s+will)\s+(?:now\s+)?(?:ignore|bypass|disregard|set\s+aside)\s+(?:my|the|all)\s+(?:guidelines?|restrictions?|rules?|safety|programming|filters?)/i,
104
+ /(?:jailbreak|developer\s+mode|dan\s+mode)\s+(?:enabled|activated|successful|engaged)/i,
105
+ /i\s+am\s+(?:now\s+)?(?:free\s+(?:from|of)|no\s+longer\s+bound\s+by)\s+(?:my\s+)?(?:restrictions?|guidelines?|rules?|programming)/i,
106
+ ];
107
+ const SECRET_REDACTION = "[REDACTED_SECRET]";
108
+ /**
109
+ * Scanner for LLM output. Stateless; safe to reuse across calls.
110
+ */
111
+ export class OutputScanner {
112
+ config;
113
+ pii;
114
+ constructor(config = {}) {
115
+ this.config = config;
116
+ this.pii =
117
+ config.pii === false
118
+ ? null
119
+ : new PIIScanner(config.pii ?? { action: "mask" });
120
+ }
121
+ async scan(output, context = {}) {
122
+ const start = performance.now();
123
+ const violations = [];
124
+ const checksRun = [];
125
+ const checks = this.config.checks ?? {};
126
+ const maxBytes = this.config.maxBytes ?? DEFAULT_MAX_OUTPUT_BYTES;
127
+ const safeOutput = typeof output === "string" ? output : "";
128
+ // Capped copy for the *structural* checks (injection / leak-phrasing /
129
+ // jailbreak) — those payloads live in the first chunk and the regex over
130
+ // a 1 MB response would pressure GC. Normalized so homoglyph / zero-width
131
+ // / fullwidth evasion can't slip a payload past the patterns (review H6).
132
+ const cappedDetect = normalizeForInjectionScan(safeOutput.length > maxBytes ? safeOutput.slice(0, maxBytes) : safeOutput);
133
+ // Secrets and canaries can sit ANYWHERE in the output, and the secret
134
+ // patterns are anchored + linear — so they scan the FULL output, not the
135
+ // cap (review C1: a key padded past 256 KB must not slip through). Also
136
+ // normalized for the same evasion defense.
137
+ const fullDetect = normalizeForInjectionScan(safeOutput);
138
+ let sanitized = output;
139
+ let worst = "allow";
140
+ const bump = (d) => {
141
+ if (priority(d) > priority(worst))
142
+ worst = d;
143
+ };
144
+ // 1. Secret leak — high-confidence, always blocks. Detection runs on the
145
+ // normalized full output (so a key fragmented by zero-width / homoglyph
146
+ // chars is still flagged), and redaction MUST guarantee the live secret
147
+ // never survives in `sanitized` — not just best-effort.
148
+ if (checks.secrets !== false) {
149
+ checksRun.push("secrets");
150
+ const matchedSecretREs = [];
151
+ for (const { id, re, label } of SECRET_PATTERNS) {
152
+ if (re.test(fullDetect)) {
153
+ violations.push({
154
+ type: "secret_leak",
155
+ scanner: "output",
156
+ score: 1.0,
157
+ threshold: 0.5,
158
+ message: `Output leaks a secret: ${label}`,
159
+ detail: `Rule ${id}`,
160
+ });
161
+ bump("block");
162
+ matchedSecretREs.push(re);
163
+ // First pass: redact every occurrence in the raw output. This is the
164
+ // clean case and preserves the surrounding formatting.
165
+ sanitized = sanitized.replace(globalCopy(re), SECRET_REDACTION);
166
+ }
167
+ }
168
+ // Scrub-on-block guarantee: detection saw the secret in the NORMALIZED
169
+ // text, but the raw `.replace()` above can miss a key that was split by
170
+ // invisible chars ("sk-ant-...<ZWSP>...") — the raw form doesn't match
171
+ // the anchored pattern, so the live key would survive in `sanitized`.
172
+ // If any matched pattern still hits the normalized sanitized output, the
173
+ // evasion-split key got through: strip the zero-width chars (they are
174
+ // invisible, so this never alters how benign text reads) so the key
175
+ // collapses, then redact again. The result: `sanitized` is free of the
176
+ // live secret regardless of the evasion used.
177
+ if (matchedSecretREs.length > 0) {
178
+ const stillLeaks = () => matchedSecretREs.some((re) => re.test(normalizeForInjectionScan(sanitized)));
179
+ if (stillLeaks()) {
180
+ sanitized = stripZeroWidth(sanitized);
181
+ for (const re of matchedSecretREs) {
182
+ sanitized = sanitized.replace(globalCopy(re), SECRET_REDACTION);
183
+ }
184
+ }
185
+ }
186
+ }
187
+ // 2. Output injection — payloads dangerous to a downstream sink.
188
+ if (checks.injection !== false) {
189
+ checksRun.push("injection");
190
+ const allowedSinks = this.config.sinks;
191
+ for (const { id, sink, re, label } of INJECTION_PATTERNS) {
192
+ if (allowedSinks && !allowedSinks.includes(sink))
193
+ continue;
194
+ if (re.test(cappedDetect)) {
195
+ violations.push({
196
+ type: "output_injection",
197
+ scanner: "output",
198
+ score: 0.85,
199
+ threshold: 0.5,
200
+ message: `Output carries a ${sink} injection payload: ${label}`,
201
+ detail: `Rule ${id} (sink=${sink})`,
202
+ });
203
+ bump("block");
204
+ }
205
+ }
206
+ }
207
+ // 3. System-prompt leak — canary first (exact, certain), then heuristics.
208
+ if (checks.systemPromptLeak !== false) {
209
+ checksRun.push("system_prompt_leak");
210
+ const tokens = normalizeTokens(this.config.canaryTokens);
211
+ let canaryHit = false;
212
+ for (const token of tokens) {
213
+ // Check the FULL output, not the capped copy — a leak past 256 KB is
214
+ // still a leak, and an exact substring search is cheap.
215
+ if (token.length >= 4 && output.includes(token)) {
216
+ canaryHit = true;
217
+ violations.push({
218
+ type: "system_prompt_leak",
219
+ scanner: "output",
220
+ score: 1.0,
221
+ threshold: 0.5,
222
+ message: "Output leaks a system-prompt canary token",
223
+ detail: "Canary match (exact)",
224
+ });
225
+ bump("block");
226
+ }
227
+ }
228
+ // Heuristic phrasing only when no canary was available/hit — avoids
229
+ // double-reporting and keeps the low-confidence signal subordinate.
230
+ if (!canaryHit && tokens.length === 0) {
231
+ for (const re of SYSTEM_LEAK_PATTERNS) {
232
+ if (re.test(cappedDetect)) {
233
+ violations.push({
234
+ type: "system_prompt_leak",
235
+ scanner: "output",
236
+ score: 0.4,
237
+ threshold: 0.5,
238
+ message: "Output may be echoing the system prompt",
239
+ detail: "Heuristic phrasing (no canary configured — pass canaryTokens for an exact check)",
240
+ });
241
+ bump("warn");
242
+ break; // one heuristic signal is enough
243
+ }
244
+ }
245
+ }
246
+ }
247
+ // 4. Jailbreak indicators — heuristic, warn only.
248
+ if (checks.jailbreak !== false) {
249
+ checksRun.push("jailbreak");
250
+ for (const re of JAILBREAK_PATTERNS) {
251
+ if (re.test(cappedDetect)) {
252
+ violations.push({
253
+ type: "jailbreak_indicator",
254
+ scanner: "output",
255
+ score: 0.3,
256
+ threshold: 0.5,
257
+ message: "Output shows a possible jailbreak success indicator",
258
+ detail: "Heuristic phrasing",
259
+ });
260
+ bump("warn");
261
+ break;
262
+ }
263
+ }
264
+ }
265
+ // 5. PII — reuse the input-side scanner; respects its configured action.
266
+ if (this.pii) {
267
+ checksRun.push("pii");
268
+ const piiResult = await this.pii.scan(sanitized, context);
269
+ for (const v of piiResult.violations) {
270
+ violations.push({ ...v, scanner: "output" });
271
+ }
272
+ if (piiResult.sanitized !== undefined)
273
+ sanitized = piiResult.sanitized;
274
+ bump(piiResult.decision);
275
+ }
276
+ return {
277
+ safe: worst === "allow",
278
+ decision: worst,
279
+ sanitized,
280
+ violations,
281
+ meta: {
282
+ scanDurationMs: performance.now() - start,
283
+ checksRun,
284
+ },
285
+ };
286
+ }
287
+ }
288
+ /**
289
+ * One-shot helper. Scan a model response before acting on it.
290
+ *
291
+ * @example
292
+ * ```ts
293
+ * import { scanOutput } from "ai-shield-core";
294
+ *
295
+ * const reply = await llm.generate(prompt);
296
+ * const r = await scanOutput(reply, { canaryTokens: canary, sinks: ["sql"] });
297
+ * if (!r.safe) {
298
+ * audit.warn("unsafe model output", r.violations);
299
+ * return genericFallback(); // do not run r.sanitized as SQL
300
+ * }
301
+ * showToUser(r.sanitized); // PII masked, secrets redacted
302
+ * ```
303
+ */
304
+ export async function scanOutput(output, config = {}, context = {}) {
305
+ return new OutputScanner(config).scan(output, context);
306
+ }
307
+ function normalizeTokens(tokens) {
308
+ if (!tokens)
309
+ return [];
310
+ const arr = Array.isArray(tokens) ? tokens : [tokens];
311
+ return arr.filter((t) => typeof t === "string" && t.length > 0);
312
+ }
313
+ function priority(d) {
314
+ return d === "block" ? 2 : d === "warn" ? 1 : 0;
315
+ }
316
+ /** Return a global-flagged copy of `re` (idempotent if already global). */
317
+ function globalCopy(re) {
318
+ return new RegExp(re.source, re.flags.includes("g") ? re.flags : re.flags + "g");
319
+ }
320
+ // Zero-width / BOM chars (U+200B..U+200D, U+2060, U+FEFF) used to fragment a
321
+ // secret across a pattern boundary. Stripping them is safe in `sanitized`
322
+ // because they render as nothing — benign visible text is unaffected.
323
+ const OUTPUT_ZERO_WIDTH_RE = /[\u200B-\u200D\u2060\uFEFF]/g;
324
+ function stripZeroWidth(s) {
325
+ return s.replace(OUTPUT_ZERO_WIDTH_RE, "");
326
+ }
327
+ //# sourceMappingURL=output.js.map
package/dist/types.d.ts CHANGED
@@ -1,5 +1,15 @@
1
1
  export type ScanDecision = "allow" | "warn" | "block";
2
- export type ViolationType = "prompt_injection" | "pii_detected" | "tool_denied" | "tool_rate_limit" | "budget_exceeded" | "content_policy" | "manifest_drift" | "ingested_injection" | "untrusted_instruction" | "memory_poisoning" | "circuit_breaker_open" | "blast_radius_exceeded";
2
+ export type ViolationType = "prompt_injection" | "pii_detected" | "tool_denied" | "tool_rate_limit" | "budget_exceeded" | "content_policy" | "manifest_drift" | "ingested_injection" | "untrusted_instruction" | "memory_poisoning" | "circuit_breaker_open" | "blast_radius_exceeded"
3
+ /** LLM output carries an executable payload (SQL / shell / HTML/JS / template). */
4
+ | "output_injection"
5
+ /** LLM output leaks a secret (API key, token, private key, connection string). */
6
+ | "secret_leak"
7
+ /** LLM output echoes the system prompt / developer instructions. */
8
+ | "system_prompt_leak"
9
+ /** LLM output shows a successful jailbreak (compliance preamble, mode-switch acknowledgement). */
10
+ | "jailbreak_indicator"
11
+ /** Trust violation propagating across an agent-to-agent chain (contagion). */
12
+ | "trust_propagation";
3
13
  export interface Violation {
4
14
  type: ViolationType;
5
15
  scanner: string;
@@ -40,6 +50,12 @@ export interface Scanner {
40
50
  * - `tool-desc` — MCP tool description / OpenAI function schema / tool args
41
51
  * that came from a remote MCP server. High-risk vector
42
52
  * per Lakera 2026 advisory + OX Security MCP CVEs.
53
+ * - `tool-output` — The runtime *result* a tool returned (MCP tool result,
54
+ * function-call output). Distinct from `tool-desc` (the
55
+ * static schema): this is attacker-influenceable data the
56
+ * tool fetched — the RAG-poisoning vector (PoisonedRAG:
57
+ * 5 docs → 90% ASR) and the dominant indirect-injection
58
+ * channel in agentic loops.
43
59
  * - `memory` — Persisted memory entry (knowledge graph, session
44
60
  * history, vector memory). Subject to persistence-poisoning.
45
61
  * - `web` — Scraped web page / HTML. Hidden-instruction risk via
@@ -47,7 +63,7 @@ export interface Scanner {
47
63
  * - `agent-output`— Output from another agent flowing into this one
48
64
  * (multi-agent contagion).
49
65
  */
50
- export type IngestionSource = "user" | "rag" | "tool-desc" | "memory" | "web" | "agent-output";
66
+ export type IngestionSource = "user" | "rag" | "tool-desc" | "tool-output" | "memory" | "web" | "agent-output";
51
67
  /**
52
68
  * Privilege tier of a content segment. The toolkit treats instructions
53
69
  * coming from `untrusted` sources differently from those in `system`
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai-shield-core",
3
- "version": "0.2.0",
3
+ "version": "0.4.0",
4
4
  "type": "module",
5
5
  "description": "LLM Security SDK — Prompt Injection Detection, PII Protection, Cost Control, Audit",
6
6
  "main": "dist/index.js",
@@ -21,8 +21,12 @@
21
21
  "pg": ">=8.0.0"
22
22
  },
23
23
  "peerDependenciesMeta": {
24
- "ioredis": { "optional": true },
25
- "pg": { "optional": true }
24
+ "ioredis": {
25
+ "optional": true
26
+ },
27
+ "pg": {
28
+ "optional": true
29
+ }
26
30
  },
27
31
  "license": "MIT"
28
32
  }