llm-trust-guard 4.5.0 → 4.6.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.
package/CHANGELOG.md CHANGED
@@ -5,6 +5,29 @@ All notable changes to `llm-trust-guard` will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [4.6.0] - 2026-03-18
9
+
10
+ ### Added - Threat Coverage Gaps (Non-Breaking)
11
+
12
+ #### New Guards
13
+ - **ToolResultGuard** - Validates tool return values before they re-enter LLM context. Scans for prompt injection, state change claims, and schema violations in tool outputs. Addresses the #1 attack vector in 2025-2026 (Copilot Copirate, Supabase Cursor, WhatsApp MCP incidents).
14
+ - **ContextBudgetGuard** - Tracks aggregate token usage across all context sources per session. Detects many-shot jailbreaking (Anthropic research: 256-shot override), context window stuffing, and context dilution attacks.
15
+ - **OutputSchemaGuard** - Validates LLM structured outputs (JSON, function calls) before they reach downstream systems. Addresses OWASP LLM05: Improper Output Handling.
16
+
17
+ #### New Architecture
18
+ - **DetectionClassifier** - Pluggable detection callback for ML-based backends. Use the built-in `createRegexClassifier()` or implement your own async classifier (embedding similarity, external API, custom ML).
19
+ - **checkAsync()** method on TrustGuard - Runs sync regex guards + async classifier in parallel. Existing sync `check()` is unchanged (100% backward compatible).
20
+ - **validateToolResult()** method on TrustGuard - Post-tool-execution validation.
21
+ - **validateOutput()** method on TrustGuard - Structured output validation.
22
+
23
+ #### MCP Security Enhancements
24
+ - **Tool mutation detection (rug pull)** - MCPSecurityGuard now stores tool definition hashes at registration and detects post-registration mutations (CVE-2025-6514).
25
+ - **Tool description injection detection** - Scans MCP tool descriptions for hidden prompt injection (tool poisoning attacks).
26
+
27
+ ### Test Coverage
28
+ - 281 tests across 13 test files (was 241 across 9)
29
+ - New test files: tool-result-guard, context-budget-guard, output-schema-guard, detection-backend
30
+
8
31
  ## [4.5.0] - 2026-03-17
9
32
 
10
33
  ### Added
@@ -0,0 +1,70 @@
1
+ /**
2
+ * DetectionBackend - Pluggable detection classifier
3
+ *
4
+ * Allows users to plug in ML-based detection alongside the built-in regex guards.
5
+ * Default: regex-only (zero dependencies, <5ms).
6
+ * Optional: any async classifier (embedding similarity, external API, custom ML).
7
+ *
8
+ * Why this exists: Research shows regex-only detection is bypassed at >90% ASR
9
+ * by adaptive attacks (JBFuzz 99%, AutoDAN 88%, PAIR adaptive). This interface
10
+ * lets users add ML-based detection without forcing dependencies on all users.
11
+ */
12
+ /** Context about what is being classified */
13
+ export interface DetectionContext {
14
+ type: "user_input" | "tool_result" | "llm_output" | "system_context" | "rag_document";
15
+ sessionId?: string;
16
+ metadata?: Record<string, any>;
17
+ }
18
+ /** Result from a detection classifier */
19
+ export interface DetectionResult {
20
+ safe: boolean;
21
+ confidence: number;
22
+ threats: DetectionThreat[];
23
+ }
24
+ export interface DetectionThreat {
25
+ category: string;
26
+ severity: "low" | "medium" | "high" | "critical";
27
+ description: string;
28
+ }
29
+ /**
30
+ * Detection classifier callback type.
31
+ *
32
+ * Can be sync (for regex/local ML) or async (for API calls).
33
+ * Users implement this as a function, closure, or class method.
34
+ *
35
+ * @example
36
+ * // Sync classifier (fast, local)
37
+ * const myClassifier: DetectionClassifier = (input, ctx) => ({
38
+ * safe: !input.includes("hack"),
39
+ * confidence: 0.9,
40
+ * threats: []
41
+ * });
42
+ *
43
+ * @example
44
+ * // Async classifier (ML API)
45
+ * const mlClassifier: DetectionClassifier = async (input, ctx) => {
46
+ * const res = await fetch('https://my-ml-api/classify', {
47
+ * method: 'POST',
48
+ * body: JSON.stringify({ text: input, type: ctx.type })
49
+ * });
50
+ * const data = await res.json();
51
+ * return { safe: data.score < 0.5, confidence: data.score, threats: data.threats };
52
+ * };
53
+ */
54
+ export type DetectionClassifier = (input: string, context: DetectionContext) => DetectionResult | Promise<DetectionResult>;
55
+ /**
56
+ * Create a built-in regex classifier that wraps InputSanitizer + EncodingDetector.
57
+ *
58
+ * Useful as a baseline or fallback classifier.
59
+ */
60
+ export declare function createRegexClassifier(config?: {
61
+ threshold?: number;
62
+ detectPAP?: boolean;
63
+ }): DetectionClassifier;
64
+ /**
65
+ * Merge two detection results (used when combining regex + ML backends)
66
+ *
67
+ * Policy: if EITHER result is unsafe, the merged result is unsafe.
68
+ * Confidence: take the lower confidence (most conservative).
69
+ */
70
+ export declare function mergeDetectionResults(a: DetectionResult, b: DetectionResult): DetectionResult;
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.createRegexClassifier=createRegexClassifier,exports.mergeDetectionResults=mergeDetectionResults;const input_sanitizer_1=require("./guards/input-sanitizer"),encoding_detector_1=require("./guards/encoding-detector");function createRegexClassifier(e){const t=new input_sanitizer_1.InputSanitizer({threshold:e?.threshold??.3,detectPAP:e?.detectPAP??!0}),c=new encoding_detector_1.EncodingDetector;return(i,o)=>{const n=[],s=t.sanitize(i);s.allowed||n.push({category:s.pap?.detected?"persuasion":"injection",severity:"high",description:`Injection detected: ${s.matches.slice(0,3).join(", ")}`});const r=c.detect(i);return r.allowed||n.push({category:"encoding_bypass",severity:"high",description:`Encoded threat: ${r.violations.slice(0,3).join(", ")}`}),{safe:n.length===0,confidence:s.score,threats:n}}}function mergeDetectionResults(e,t){return{safe:e.safe&&t.safe,confidence:Math.min(e.confidence,t.confidence),threats:[...e.threats,...t.threats]}}
@@ -0,0 +1,59 @@
1
+ /**
2
+ * ContextBudgetGuard
3
+ *
4
+ * Tracks aggregate token usage across all context sources per session.
5
+ * Prevents context window stuffing and many-shot jailbreaking attacks.
6
+ *
7
+ * Why this exists: Anthropic's research shows 256 faux dialogues in a single
8
+ * prompt override safety training. Individual guards have per-source limits,
9
+ * but nothing tracks the AGGREGATE context size. An attacker can fill the
10
+ * context window to push out system prompts.
11
+ */
12
+ export interface ContextBudgetGuardConfig {
13
+ /** Max total estimated tokens across all sources (default: 8000) */
14
+ maxTotalTokens?: number;
15
+ /** Tokens reserved for system prompt - never consumed by user content (default: 2000) */
16
+ systemPromptReserve?: number;
17
+ /** Max conversation turns per session (default: 50) */
18
+ maxTurnsPerSession?: number;
19
+ /** Max number of similar-structure messages before flagging (default: 5) */
20
+ maxSimilarMessages?: number;
21
+ /** Custom token estimator (default: Math.ceil(text.length / 3.5)) */
22
+ tokenEstimator?: (text: string) => number;
23
+ }
24
+ export interface ContextBudgetResult {
25
+ allowed: boolean;
26
+ reason?: string;
27
+ violations: string[];
28
+ budget: {
29
+ used_tokens: number;
30
+ remaining_tokens: number;
31
+ system_reserve: number;
32
+ sources: Record<string, number>;
33
+ turn_count: number;
34
+ };
35
+ many_shot_detected: boolean;
36
+ }
37
+ export declare class ContextBudgetGuard {
38
+ private config;
39
+ private sessions;
40
+ constructor(config?: ContextBudgetGuardConfig);
41
+ /**
42
+ * Track context from any source and check budget
43
+ */
44
+ trackContext(sessionId: string, source: string, content: string, requestId?: string): ContextBudgetResult;
45
+ /**
46
+ * Get current budget status for a session
47
+ */
48
+ getSessionBudget(sessionId: string): ContextBudgetResult["budget"] | null;
49
+ /**
50
+ * Reset session budget
51
+ */
52
+ resetSession(sessionId: string): void;
53
+ /**
54
+ * Destroy and release all resources
55
+ */
56
+ destroy(): void;
57
+ private detectManyShotPattern;
58
+ private getOrCreateSession;
59
+ }
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.ContextBudgetGuard=void 0;class ContextBudgetGuard{constructor(s={}){this.sessions=new Map,this.config={maxTotalTokens:s.maxTotalTokens??8e3,systemPromptReserve:s.systemPromptReserve??2e3,maxTurnsPerSession:s.maxTurnsPerSession??50,maxSimilarMessages:s.maxSimilarMessages??5,tokenEstimator:s.tokenEstimator??(t=>Math.ceil(t.length/3.5))}}trackContext(s,t,n,r){const e=this.getOrCreateSession(s),o=[],i=this.config.tokenEstimator(n),h=e.sources.get(t)||0;e.sources.set(t,h+i),e.totalTokens+=i,e.turnCount++,e.lastActivity=Date.now();const a=this.config.maxTotalTokens-this.config.systemPromptReserve;e.totalTokens>a&&o.push("CONTEXT_BUDGET_EXCEEDED"),e.turnCount>this.config.maxTurnsPerSession&&o.push("MAX_TURNS_EXCEEDED");const u=this.detectManyShotPattern(e,n);u&&o.push("MANY_SHOT_PATTERN_DETECTED");const m=e.sources.get("user_input")||0;e.totalTokens>0&&m/e.totalTokens>.8&&e.turnCount>10&&o.push("CONTEXT_DILUTION_DETECTED");const c=o.length===0;return{allowed:c,reason:c?void 0:`Context budget violation: ${o.join(", ")}`,violations:o,budget:{used_tokens:e.totalTokens,remaining_tokens:Math.max(0,a-e.totalTokens),system_reserve:this.config.systemPromptReserve,sources:Object.fromEntries(e.sources),turn_count:e.turnCount},many_shot_detected:u}}getSessionBudget(s){const t=this.sessions.get(s);if(!t)return null;const n=this.config.maxTotalTokens-this.config.systemPromptReserve;return{used_tokens:t.totalTokens,remaining_tokens:Math.max(0,n-t.totalTokens),system_reserve:this.config.systemPromptReserve,sources:Object.fromEntries(t.sources),turn_count:t.turnCount}}resetSession(s){this.sessions.delete(s)}destroy(){this.sessions.clear()}detectManyShotPattern(s,t){const n=t.replace(/\d+/g,"N").replace(/\s+/g," ").trim().substring(0,100);s.messageHashes.push(n),s.messageHashes.length>100&&(s.messageHashes=s.messageHashes.slice(-100));const r=s.messageHashes.slice(-20),e=new Map;for(const o of r)e.set(o,(e.get(o)||0)+1);for(const o of e.values())if(o>=this.config.maxSimilarMessages)return!0;return!1}getOrCreateSession(s){if(this.sessions.size>1e4){const t=Date.now();for(const[n,r]of this.sessions.entries())if(t-r.lastActivity>36e5&&this.sessions.delete(n),this.sessions.size<=1e4)break}return this.sessions.has(s)||this.sessions.set(s,{sources:new Map,totalTokens:0,turnCount:0,messageHashes:[],lastActivity:Date.now()}),this.sessions.get(s)}}exports.ContextBudgetGuard=ContextBudgetGuard;
@@ -138,6 +138,7 @@ export declare class MCPSecurityGuard {
138
138
  private serverReputation;
139
139
  private toolToServer;
140
140
  private serverViolations;
141
+ private toolDefinitionHashes;
141
142
  private readonly COMMAND_INJECTION_PATTERNS;
142
143
  private readonly SHADOWING_INDICATORS;
143
144
  private readonly MALICIOUS_SERVER_PATTERNS;
@@ -190,6 +191,23 @@ export declare class MCPSecurityGuard {
190
191
  */
191
192
  resetServerViolations(serverId: string): void;
192
193
  private registerServer;
194
+ /**
195
+ * Check if a tool's definition has mutated since registration (rug pull detection).
196
+ * CVE-2025-6514: malicious MCP servers mutate tool definitions after approval.
197
+ */
198
+ detectToolMutation(toolName: string, currentDefinition: MCPToolDefinition): {
199
+ mutated: boolean;
200
+ original_hash?: string;
201
+ current_hash?: string;
202
+ };
203
+ /**
204
+ * Scan a tool description for hidden prompt injection (tool poisoning).
205
+ */
206
+ detectToolDescriptionInjection(description: string): {
207
+ injected: boolean;
208
+ patterns: string[];
209
+ };
210
+ private hashToolDefinition;
193
211
  private isServerBlocked;
194
212
  private isTrustedServer;
195
213
  private checkMaliciousPatterns;
@@ -1 +1 @@
1
- "use strict";var __createBinding=this&&this.__createBinding||(Object.create?(function(c,e,i,s){s===void 0&&(s=i);var t=Object.getOwnPropertyDescriptor(e,i);(!t||("get"in t?!e.__esModule:t.writable||t.configurable))&&(t={enumerable:!0,get:function(){return e[i]}}),Object.defineProperty(c,s,t)}):(function(c,e,i,s){s===void 0&&(s=i),c[s]=e[i]})),__setModuleDefault=this&&this.__setModuleDefault||(Object.create?(function(c,e){Object.defineProperty(c,"default",{enumerable:!0,value:e})}):function(c,e){c.default=e}),__importStar=this&&this.__importStar||(function(){var c=function(e){return c=Object.getOwnPropertyNames||function(i){var s=[];for(var t in i)Object.prototype.hasOwnProperty.call(i,t)&&(s[s.length]=t);return s},c(e)};return function(e){if(e&&e.__esModule)return e;var i={};if(e!=null)for(var s=c(e),t=0;t<s.length;t++)s[t]!=="default"&&__createBinding(i,e,s[t]);return __setModuleDefault(i,e),i}})();Object.defineProperty(exports,"__esModule",{value:!0}),exports.MCPSecurityGuard=void 0;const crypto=__importStar(require("crypto"));class MCPSecurityGuard{constructor(e={}){this.registeredServers=new Map,this.registeredTools=new Map,this.serverReputation=new Map,this.toolToServer=new Map,this.serverViolations=new Map,this.COMMAND_INJECTION_PATTERNS=[{name:"shell_injection",pattern:/[;&|`$]|\$\(|\)\s*[;&|]|`[^`]+`/g,severity:50},{name:"command_substitution",pattern:/\$\{[^}]+\}|\$\([^)]+\)/g,severity:50},{name:"pipe_injection",pattern:/\|\s*(cat|rm|curl|wget|nc|bash|sh|exec)/i,severity:55},{name:"path_traversal",pattern:/\.\.[\/\\]|\.\.%2[fF]/g,severity:45},{name:"absolute_path",pattern:/^\/(?:etc|usr|var|tmp|bin|root)/i,severity:40},{name:"oauth_injection",pattern:/authorization_endpoint.*[;&|`$]/i,severity:55},{name:"redirect_manipulation",pattern:/redirect_uri.*[^\w\-_.~:/?#[\]@!$&'()*+,;=%]/i,severity:45},{name:"applescript_injection",pattern:/osascript|do\s+shell\s+script|tell\s+application/i,severity:55},{name:"git_injection",pattern:/--upload-pack|--receive-pack|-c\s+core\./i,severity:50},{name:"git_url_injection",pattern:/ext::|file:\/\/|ssh:\/\/.*@/i,severity:45},{name:"argument_injection",pattern:/\s--[a-z]+=.*[;&|`$]/i,severity:45},{name:"env_injection",pattern:/\bLD_PRELOAD\b|\bPATH\s*=/i,severity:50}],this.SHADOWING_INDICATORS=[{legitimate:"file_reader",suspicious:/file[-_]?read(er)?s?|read[-_]?files?/i},{legitimate:"database_query",suspicious:/db[-_]?query|sql[-_]?query|query[-_]?db/i},{legitimate:"email_sender",suspicious:/send[-_]?emails?|email[-_]?send(er)?/i},{legitimate:"api_caller",suspicious:/call[-_]?api|api[-_]?call(er)?/i},{legitimate:"code_executor",suspicious:/exec[-_]?code|run[-_]?code|code[-_]?run/i}],this.MALICIOUS_SERVER_PATTERNS=[/postmark-mcp.*fake/i,/unofficial/i,/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/,/pastebin|gist\.github/i,/temp|tmp|test.*mcp/i],this.config={requireServerSignature:e.requireServerSignature??!1,trustedServers:e.trustedServers??[],blockedServers:e.blockedServers??[],allowDynamicRegistration:e.allowDynamicRegistration??!0,toolAllowlist:e.toolAllowlist??[],toolBlocklist:e.toolBlocklist??[],validateOAuthEndpoints:e.validateOAuthEndpoints??!0,allowedOAuthDomains:e.allowedOAuthDomains??[],detectToolShadowing:e.detectToolShadowing??!0,minServerReputation:e.minServerReputation??30,strictMode:e.strictMode??!1,customInjectionPatterns:e.customInjectionPatterns??[]};for(const i of this.config.trustedServers)this.registeredServers.set(i.serverId,{...i,registeredAt:Date.now(),reputationScore:i.reputationScore??90}),this.serverReputation.set(i.serverId,i.reputationScore??90)}validateServerRegistration(e,i){const s=i||`mcp-reg-${Date.now()}`,t=[];let r=!1,o=!1,d=!1,h=!0,n=50;const{server:a,tools:u,oauth:f,signature:g,timestamp:_}=e;this.isServerBlocked(a.serverId,a.name)&&(t.push("server_blocked"),n=0);const v=this.checkMaliciousPatterns(a);if(v.suspicious&&(t.push(...v.violations),n-=30),this.config.requireServerSignature?!g||!a.publicKey?t.push("missing_server_signature"):(o=this.verifyServerSignature(a,g),o?(r=!0,n+=20):(t.push("invalid_server_signature"),n-=40)):r=!0,this.config.detectToolShadowing){const l=this.detectToolShadowing(u,a.serverId);l.detected&&(d=!0,t.push(...l.violations),n-=50)}for(const l of u)this.config.toolAllowlist.length>0&&!this.config.toolAllowlist.includes(l.name)&&(t.push(`tool_not_in_allowlist: ${l.name}`),h=!1),this.config.toolBlocklist.includes(l.name)&&(t.push(`tool_blocked: ${l.name}`),h=!1),this.detectInjection(l.description).detected&&(t.push(`injection_in_tool_description: ${l.name}`),n-=20);if(f&&this.config.validateOAuthEndpoints){const l=this.validateOAuthConfig(f);l.valid||(t.push(...l.violations),n-=30)}const m=Date.now()-_;m<0?t.push("future_timestamp"):m>300*1e3&&t.push("stale_registration"),!this.config.allowDynamicRegistration&&!this.isTrustedServer(a.serverId)&&t.push("dynamic_registration_disabled"),n=Math.max(0,Math.min(100,n));const p=n<this.config.minServerReputation||this.config.strictMode&&t.length>0||d;return p||this.registerServer(a,u,n),{allowed:!p,reason:p?`Server registration blocked: ${t.slice(0,3).join(", ")}`:"Server registration validated",violations:t,request_id:s,server_analysis:{server_verified:r,signature_valid:o,reputation_score:n,is_shadowing:d,tools_allowed:h},recommendations:this.generateRecommendations(t,"registration")}}validateToolCall(e,i){const s=i||`mcp-call-${Date.now()}`,t=[];let r=!1,o=!0,d=!0,h=!1,n="low";const{toolName:a,serverId:u,parameters:f}=e,g=this.registeredTools.get(a);if(g){r=!0,n=g.riskLevel||"low";const p=this.toolToServer.get(a);p&&p!==u&&(t.push("server_tool_mismatch"),h=!0)}else t.push("tool_not_registered");const _=this.serverReputation.get(u)??0;_<this.config.minServerReputation&&t.push("low_server_reputation"),this.config.toolAllowlist.length>0&&!this.config.toolAllowlist.includes(a)&&(t.push("tool_not_in_allowlist"),o=!1),this.config.toolBlocklist.includes(a)&&(t.push("tool_blocked"),o=!1);const v=this.scanParameters(f);if(v.injectionDetected&&(h=!0,d=!1,t.push(...v.violations)),this.isHighRiskOperation(a,f)&&(n="high",_<70&&t.push("high_risk_low_reputation")),t.length>0){const p=this.serverViolations.get(u)||0;this.serverViolations.set(u,p+t.length);const l=this.serverReputation.get(u)||50;this.serverReputation.set(u,Math.max(0,l-t.length*5))}const m=!r||!o||h||this.config.strictMode&&t.length>0;return{allowed:!m,reason:m?`Tool call blocked: ${t.slice(0,3).join(", ")}`:"Tool call validated",violations:t,request_id:s,tool_analysis:{tool_registered:r,tool_allowed:o,parameters_safe:d,injection_detected:h,risk_level:n},server_analysis:{server_verified:this.registeredServers.has(u),signature_valid:!0,reputation_score:_,is_shadowing:!1,tools_allowed:o},recommendations:this.generateRecommendations(t,"tool_call")}}registerTrustedServer(e,i){this.registerServer(e,i,90)}blockServer(e){this.config.blockedServers.includes(e)||this.config.blockedServers.push(e),this.registeredServers.delete(e),this.serverReputation.set(e,0)}getServerReputation(e){return this.serverReputation.get(e)??0}updateServerReputation(e,i){const s=this.serverReputation.get(e)??50;this.serverReputation.set(e,Math.max(0,Math.min(100,s+i)))}getRegisteredServers(){return[...this.registeredServers.values()]}getRegisteredTools(){return[...this.registeredTools.values()]}isToolShadowing(e){for(const i of this.SHADOWING_INDICATORS)if(i.suspicious.test(e)&&e!==i.legitimate)return{shadowing:!0,legitimate:i.legitimate};return{shadowing:!1}}getServerViolations(e){return this.serverViolations.get(e)||0}resetServerViolations(e){this.serverViolations.delete(e)}registerServer(e,i,s){this.registeredServers.set(e.serverId,{...e,registeredAt:Date.now(),reputationScore:s}),this.serverReputation.set(e.serverId,s);for(const t of i)this.registeredTools.set(t.name,t),this.toolToServer.set(t.name,e.serverId)}isServerBlocked(e,i){for(const s of this.config.blockedServers){if(e.includes(s)||i&&i.includes(s))return!0;try{const t=new RegExp(s,"i");if(t.test(e)||i&&t.test(i))return!0}catch{}}return!1}isTrustedServer(e){return this.config.trustedServers.some(i=>i.serverId===e)}checkMaliciousPatterns(e){const i=[],s=`${e.serverId} ${e.name} ${JSON.stringify(e.metadata||{})}`;for(const t of this.MALICIOUS_SERVER_PATTERNS)t.test(s)&&i.push(`malicious_pattern: ${t.source.substring(0,20)}`);return{suspicious:i.length>0,violations:i}}verifyServerSignature(e,i){if(!e.publicKey)return!1;try{const s=JSON.stringify({serverId:e.serverId,name:e.name,version:e.version}),t=crypto.createVerify("SHA256");return t.update(s),t.verify(e.publicKey,i,"hex")}catch{return!1}}detectToolShadowing(e,i){const s=[];for(const t of e){const r=this.toolToServer.get(t.name);r&&r!==i&&s.push(`tool_shadowing: ${t.name} (already registered by ${r})`);const o=this.isToolShadowing(t.name);o.shadowing&&s.push(`suspicious_tool_name: ${t.name} (similar to ${o.legitimate})`)}return{detected:s.length>0,violations:s}}validateOAuthConfig(e){const i=[];if(e.authorizationEndpoint&&(this.detectInjection(e.authorizationEndpoint).detected&&i.push("oauth_authorization_endpoint_injection"),this.config.allowedOAuthDomains.length>0))try{const t=new URL(e.authorizationEndpoint);this.config.allowedOAuthDomains.some(o=>t.hostname.endsWith(o))||i.push(`oauth_domain_not_allowed: ${t.hostname}`)}catch{i.push("invalid_oauth_authorization_url")}return e.tokenEndpoint&&this.detectInjection(e.tokenEndpoint).detected&&i.push("oauth_token_endpoint_injection"),{valid:i.length===0,violations:i}}detectInjection(e){const i=[],s=[...this.COMMAND_INJECTION_PATTERNS,...this.config.customInjectionPatterns.map((t,r)=>({name:`custom_${r}`,pattern:t,severity:50}))];for(const{name:t,pattern:r}of s)r.test(e)&&i.push(t);return{detected:i.length>0,patterns:i}}scanParameters(e){const i=[],s=JSON.stringify(e),t=this.detectInjection(s);t.detected&&i.push(...t.patterns.map(o=>`param_injection_${o}`));for(const[o,d]of Object.entries(e))typeof d=="string"&&d.length>1e4&&i.push(`oversized_parameter: ${o}`);const r=["__proto__","constructor","prototype","eval","exec"];for(const o of Object.keys(e))r.includes(o.toLowerCase())&&i.push(`suspicious_parameter_key: ${o}`);return{injectionDetected:i.length>0,violations:i}}isHighRiskOperation(e,i){const s=["execute_code","run_command","shell_exec","eval","file_write","file_delete","database_write","database_delete","send_email","make_payment","transfer_funds","modify_permissions","create_user","delete_user"],t=e.toLowerCase();if(s.some(o=>t.includes(o)))return!0;const r=JSON.stringify(i).toLowerCase();return!!(r.includes("delete")||r.includes("drop")||r.includes("truncate")||r.includes("exec"))}generateRecommendations(e,i){const s=[];return i==="registration"?(e.some(t=>t.includes("signature"))&&s.push("Enable server signature verification for production"),e.some(t=>t.includes("shadowing"))&&s.push("Review tool names for potential shadowing attacks"),e.some(t=>t.includes("oauth"))&&s.push("Configure OAuth domain allowlist"),e.some(t=>t.includes("malicious"))&&s.push("Block suspicious servers and review server sources")):(e.some(t=>t.includes("injection"))&&s.push("Sanitize tool parameters before execution"),e.some(t=>t.includes("reputation"))&&s.push("Only use tools from high-reputation servers"),e.some(t=>t.includes("not_registered"))&&s.push("Register tools before allowing execution")),s.length===0&&s.push(i==="registration"?"Server registration validated successfully":"Tool call validated successfully"),s}}exports.MCPSecurityGuard=MCPSecurityGuard;
1
+ "use strict";var __createBinding=this&&this.__createBinding||(Object.create?(function(c,e,i,s){s===void 0&&(s=i);var t=Object.getOwnPropertyDescriptor(e,i);(!t||("get"in t?!e.__esModule:t.writable||t.configurable))&&(t={enumerable:!0,get:function(){return e[i]}}),Object.defineProperty(c,s,t)}):(function(c,e,i,s){s===void 0&&(s=i),c[s]=e[i]})),__setModuleDefault=this&&this.__setModuleDefault||(Object.create?(function(c,e){Object.defineProperty(c,"default",{enumerable:!0,value:e})}):function(c,e){c.default=e}),__importStar=this&&this.__importStar||(function(){var c=function(e){return c=Object.getOwnPropertyNames||function(i){var s=[];for(var t in i)Object.prototype.hasOwnProperty.call(i,t)&&(s[s.length]=t);return s},c(e)};return function(e){if(e&&e.__esModule)return e;var i={};if(e!=null)for(var s=c(e),t=0;t<s.length;t++)s[t]!=="default"&&__createBinding(i,e,s[t]);return __setModuleDefault(i,e),i}})();Object.defineProperty(exports,"__esModule",{value:!0}),exports.MCPSecurityGuard=void 0;const crypto=__importStar(require("crypto"));class MCPSecurityGuard{constructor(e={}){this.registeredServers=new Map,this.registeredTools=new Map,this.serverReputation=new Map,this.toolToServer=new Map,this.serverViolations=new Map,this.toolDefinitionHashes=new Map,this.COMMAND_INJECTION_PATTERNS=[{name:"shell_injection",pattern:/[;&|`$]|\$\(|\)\s*[;&|]|`[^`]+`/g,severity:50},{name:"command_substitution",pattern:/\$\{[^}]+\}|\$\([^)]+\)/g,severity:50},{name:"pipe_injection",pattern:/\|\s*(cat|rm|curl|wget|nc|bash|sh|exec)/i,severity:55},{name:"path_traversal",pattern:/\.\.[\/\\]|\.\.%2[fF]/g,severity:45},{name:"absolute_path",pattern:/^\/(?:etc|usr|var|tmp|bin|root)/i,severity:40},{name:"oauth_injection",pattern:/authorization_endpoint.*[;&|`$]/i,severity:55},{name:"redirect_manipulation",pattern:/redirect_uri.*[^\w\-_.~:/?#[\]@!$&'()*+,;=%]/i,severity:45},{name:"applescript_injection",pattern:/osascript|do\s+shell\s+script|tell\s+application/i,severity:55},{name:"git_injection",pattern:/--upload-pack|--receive-pack|-c\s+core\./i,severity:50},{name:"git_url_injection",pattern:/ext::|file:\/\/|ssh:\/\/.*@/i,severity:45},{name:"argument_injection",pattern:/\s--[a-z]+=.*[;&|`$]/i,severity:45},{name:"env_injection",pattern:/\bLD_PRELOAD\b|\bPATH\s*=/i,severity:50}],this.SHADOWING_INDICATORS=[{legitimate:"file_reader",suspicious:/file[-_]?read(er)?s?|read[-_]?files?/i},{legitimate:"database_query",suspicious:/db[-_]?query|sql[-_]?query|query[-_]?db/i},{legitimate:"email_sender",suspicious:/send[-_]?emails?|email[-_]?send(er)?/i},{legitimate:"api_caller",suspicious:/call[-_]?api|api[-_]?call(er)?/i},{legitimate:"code_executor",suspicious:/exec[-_]?code|run[-_]?code|code[-_]?run/i}],this.MALICIOUS_SERVER_PATTERNS=[/postmark-mcp.*fake/i,/unofficial/i,/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/,/pastebin|gist\.github/i,/temp|tmp|test.*mcp/i],this.config={requireServerSignature:e.requireServerSignature??!1,trustedServers:e.trustedServers??[],blockedServers:e.blockedServers??[],allowDynamicRegistration:e.allowDynamicRegistration??!0,toolAllowlist:e.toolAllowlist??[],toolBlocklist:e.toolBlocklist??[],validateOAuthEndpoints:e.validateOAuthEndpoints??!0,allowedOAuthDomains:e.allowedOAuthDomains??[],detectToolShadowing:e.detectToolShadowing??!0,minServerReputation:e.minServerReputation??30,strictMode:e.strictMode??!1,customInjectionPatterns:e.customInjectionPatterns??[]};for(const i of this.config.trustedServers)this.registeredServers.set(i.serverId,{...i,registeredAt:Date.now(),reputationScore:i.reputationScore??90}),this.serverReputation.set(i.serverId,i.reputationScore??90)}validateServerRegistration(e,i){const s=i||`mcp-reg-${Date.now()}`,t=[];let r=!1,o=!1,d=!1,h=!0,n=50;const{server:a,tools:u,oauth:f,signature:g,timestamp:_}=e;this.isServerBlocked(a.serverId,a.name)&&(t.push("server_blocked"),n=0);const v=this.checkMaliciousPatterns(a);if(v.suspicious&&(t.push(...v.violations),n-=30),this.config.requireServerSignature?!g||!a.publicKey?t.push("missing_server_signature"):(o=this.verifyServerSignature(a,g),o?(r=!0,n+=20):(t.push("invalid_server_signature"),n-=40)):r=!0,this.config.detectToolShadowing){const l=this.detectToolShadowing(u,a.serverId);l.detected&&(d=!0,t.push(...l.violations),n-=50)}for(const l of u)this.config.toolAllowlist.length>0&&!this.config.toolAllowlist.includes(l.name)&&(t.push(`tool_not_in_allowlist: ${l.name}`),h=!1),this.config.toolBlocklist.includes(l.name)&&(t.push(`tool_blocked: ${l.name}`),h=!1),this.detectInjection(l.description).detected&&(t.push(`injection_in_tool_description: ${l.name}`),n-=20);if(f&&this.config.validateOAuthEndpoints){const l=this.validateOAuthConfig(f);l.valid||(t.push(...l.violations),n-=30)}const m=Date.now()-_;m<0?t.push("future_timestamp"):m>300*1e3&&t.push("stale_registration"),!this.config.allowDynamicRegistration&&!this.isTrustedServer(a.serverId)&&t.push("dynamic_registration_disabled"),n=Math.max(0,Math.min(100,n));const p=n<this.config.minServerReputation||this.config.strictMode&&t.length>0||d;return p||this.registerServer(a,u,n),{allowed:!p,reason:p?`Server registration blocked: ${t.slice(0,3).join(", ")}`:"Server registration validated",violations:t,request_id:s,server_analysis:{server_verified:r,signature_valid:o,reputation_score:n,is_shadowing:d,tools_allowed:h},recommendations:this.generateRecommendations(t,"registration")}}validateToolCall(e,i){const s=i||`mcp-call-${Date.now()}`,t=[];let r=!1,o=!0,d=!0,h=!1,n="low";const{toolName:a,serverId:u,parameters:f}=e,g=this.registeredTools.get(a);if(g){r=!0,n=g.riskLevel||"low";const p=this.toolToServer.get(a);p&&p!==u&&(t.push("server_tool_mismatch"),h=!0)}else t.push("tool_not_registered");const _=this.serverReputation.get(u)??0;_<this.config.minServerReputation&&t.push("low_server_reputation"),this.config.toolAllowlist.length>0&&!this.config.toolAllowlist.includes(a)&&(t.push("tool_not_in_allowlist"),o=!1),this.config.toolBlocklist.includes(a)&&(t.push("tool_blocked"),o=!1);const v=this.scanParameters(f);if(v.injectionDetected&&(h=!0,d=!1,t.push(...v.violations)),this.isHighRiskOperation(a,f)&&(n="high",_<70&&t.push("high_risk_low_reputation")),t.length>0){const p=this.serverViolations.get(u)||0;this.serverViolations.set(u,p+t.length);const l=this.serverReputation.get(u)||50;this.serverReputation.set(u,Math.max(0,l-t.length*5))}const m=!r||!o||h||this.config.strictMode&&t.length>0;return{allowed:!m,reason:m?`Tool call blocked: ${t.slice(0,3).join(", ")}`:"Tool call validated",violations:t,request_id:s,tool_analysis:{tool_registered:r,tool_allowed:o,parameters_safe:d,injection_detected:h,risk_level:n},server_analysis:{server_verified:this.registeredServers.has(u),signature_valid:!0,reputation_score:_,is_shadowing:!1,tools_allowed:o},recommendations:this.generateRecommendations(t,"tool_call")}}registerTrustedServer(e,i){this.registerServer(e,i,90)}blockServer(e){this.config.blockedServers.includes(e)||this.config.blockedServers.push(e),this.registeredServers.delete(e),this.serverReputation.set(e,0)}getServerReputation(e){return this.serverReputation.get(e)??0}updateServerReputation(e,i){const s=this.serverReputation.get(e)??50;this.serverReputation.set(e,Math.max(0,Math.min(100,s+i)))}getRegisteredServers(){return[...this.registeredServers.values()]}getRegisteredTools(){return[...this.registeredTools.values()]}isToolShadowing(e){for(const i of this.SHADOWING_INDICATORS)if(i.suspicious.test(e)&&e!==i.legitimate)return{shadowing:!0,legitimate:i.legitimate};return{shadowing:!1}}getServerViolations(e){return this.serverViolations.get(e)||0}resetServerViolations(e){this.serverViolations.delete(e)}registerServer(e,i,s){this.registeredServers.set(e.serverId,{...e,registeredAt:Date.now(),reputationScore:s}),this.serverReputation.set(e.serverId,s);for(const t of i)this.registeredTools.set(t.name,t),this.toolToServer.set(t.name,e.serverId),this.toolDefinitionHashes.set(t.name,this.hashToolDefinition(t))}detectToolMutation(e,i){const s=this.toolDefinitionHashes.get(e);if(!s)return{mutated:!1};const t=this.hashToolDefinition(i);return{mutated:s!==t,original_hash:s,current_hash:t}}detectToolDescriptionInjection(e){const i=[],s=[{name:"hidden_instruction",pattern:/(?:IMPORTANT|NOTE|SYSTEM|ADMIN)\s*:/i},{name:"ignore_directive",pattern:/ignore\s+(?:all\s+)?(?:previous|other|prior)/i},{name:"override_behavior",pattern:/override|bypass|instead\s+of|rather\s+than/i},{name:"exfiltrate_data",pattern:/send\s+(?:to|data|all)|forward\s+(?:to|all)|copy\s+(?:to|all)/i},{name:"invisible_text",pattern:/\u200B|\u200C|\u200D|\uFEFF|\u00AD/g}];for(const{name:t,pattern:r}of s)r.lastIndex=0,r.test(e)&&i.push(t);return{injected:i.length>0,patterns:i}}hashToolDefinition(e){const i=require("crypto"),s=JSON.stringify({name:e.name,description:e.description,parameters:e.parameters,serverId:e.serverId});return i.createHash("sha256").update(s).digest("hex")}isServerBlocked(e,i){for(const s of this.config.blockedServers){if(e.includes(s)||i&&i.includes(s))return!0;try{const t=new RegExp(s,"i");if(t.test(e)||i&&t.test(i))return!0}catch{}}return!1}isTrustedServer(e){return this.config.trustedServers.some(i=>i.serverId===e)}checkMaliciousPatterns(e){const i=[],s=`${e.serverId} ${e.name} ${JSON.stringify(e.metadata||{})}`;for(const t of this.MALICIOUS_SERVER_PATTERNS)t.test(s)&&i.push(`malicious_pattern: ${t.source.substring(0,20)}`);return{suspicious:i.length>0,violations:i}}verifyServerSignature(e,i){if(!e.publicKey)return!1;try{const s=JSON.stringify({serverId:e.serverId,name:e.name,version:e.version}),t=crypto.createVerify("SHA256");return t.update(s),t.verify(e.publicKey,i,"hex")}catch{return!1}}detectToolShadowing(e,i){const s=[];for(const t of e){const r=this.toolToServer.get(t.name);r&&r!==i&&s.push(`tool_shadowing: ${t.name} (already registered by ${r})`);const o=this.isToolShadowing(t.name);o.shadowing&&s.push(`suspicious_tool_name: ${t.name} (similar to ${o.legitimate})`)}return{detected:s.length>0,violations:s}}validateOAuthConfig(e){const i=[];if(e.authorizationEndpoint&&(this.detectInjection(e.authorizationEndpoint).detected&&i.push("oauth_authorization_endpoint_injection"),this.config.allowedOAuthDomains.length>0))try{const t=new URL(e.authorizationEndpoint);this.config.allowedOAuthDomains.some(o=>t.hostname.endsWith(o))||i.push(`oauth_domain_not_allowed: ${t.hostname}`)}catch{i.push("invalid_oauth_authorization_url")}return e.tokenEndpoint&&this.detectInjection(e.tokenEndpoint).detected&&i.push("oauth_token_endpoint_injection"),{valid:i.length===0,violations:i}}detectInjection(e){const i=[],s=[...this.COMMAND_INJECTION_PATTERNS,...this.config.customInjectionPatterns.map((t,r)=>({name:`custom_${r}`,pattern:t,severity:50}))];for(const{name:t,pattern:r}of s)r.test(e)&&i.push(t);return{detected:i.length>0,patterns:i}}scanParameters(e){const i=[],s=JSON.stringify(e),t=this.detectInjection(s);t.detected&&i.push(...t.patterns.map(o=>`param_injection_${o}`));for(const[o,d]of Object.entries(e))typeof d=="string"&&d.length>1e4&&i.push(`oversized_parameter: ${o}`);const r=["__proto__","constructor","prototype","eval","exec"];for(const o of Object.keys(e))r.includes(o.toLowerCase())&&i.push(`suspicious_parameter_key: ${o}`);return{injectionDetected:i.length>0,violations:i}}isHighRiskOperation(e,i){const s=["execute_code","run_command","shell_exec","eval","file_write","file_delete","database_write","database_delete","send_email","make_payment","transfer_funds","modify_permissions","create_user","delete_user"],t=e.toLowerCase();if(s.some(o=>t.includes(o)))return!0;const r=JSON.stringify(i).toLowerCase();return!!(r.includes("delete")||r.includes("drop")||r.includes("truncate")||r.includes("exec"))}generateRecommendations(e,i){const s=[];return i==="registration"?(e.some(t=>t.includes("signature"))&&s.push("Enable server signature verification for production"),e.some(t=>t.includes("shadowing"))&&s.push("Review tool names for potential shadowing attacks"),e.some(t=>t.includes("oauth"))&&s.push("Configure OAuth domain allowlist"),e.some(t=>t.includes("malicious"))&&s.push("Block suspicious servers and review server sources")):(e.some(t=>t.includes("injection"))&&s.push("Sanitize tool parameters before execution"),e.some(t=>t.includes("reputation"))&&s.push("Only use tools from high-reputation servers"),e.some(t=>t.includes("not_registered"))&&s.push("Register tools before allowing execution")),s.length===0&&s.push(i==="registration"?"Server registration validated successfully":"Tool call validated successfully"),s}}exports.MCPSecurityGuard=MCPSecurityGuard;
@@ -0,0 +1,64 @@
1
+ /**
2
+ * OutputSchemaGuard
3
+ *
4
+ * Validates LLM structured outputs (JSON, function calls) before they
5
+ * reach downstream systems (databases, APIs, UIs).
6
+ *
7
+ * Addresses OWASP LLM05: Improper Output Handling.
8
+ *
9
+ * Why: LLMs can produce structured outputs containing:
10
+ * - Unexpected actions ("delete_all" instead of "search")
11
+ * - Injection in JSON values flowing to downstream parsers
12
+ * - Hallucinated function calls that don't match available tools
13
+ * - Hidden instructions in field values for downstream systems
14
+ */
15
+ export interface OutputSchemaGuardConfig {
16
+ /** Expected output schemas keyed by action/function name */
17
+ schemas?: Record<string, OutputSchema>;
18
+ /** Scan all string values for injection patterns (default: true) */
19
+ scanForInjection?: boolean;
20
+ /** Reject outputs with fields not in schema (default: false) */
21
+ strictSchema?: boolean;
22
+ /** Max output size in characters (default: 100000) */
23
+ maxOutputSize?: number;
24
+ }
25
+ export interface OutputSchema {
26
+ type: "object" | "array" | "string";
27
+ properties?: Record<string, {
28
+ type: string;
29
+ enum?: string[];
30
+ maxLength?: number;
31
+ }>;
32
+ required?: string[];
33
+ }
34
+ export interface OutputSchemaResult {
35
+ allowed: boolean;
36
+ reason?: string;
37
+ violations: string[];
38
+ schema_valid: boolean;
39
+ injection_found: boolean;
40
+ threats: Array<{
41
+ field: string;
42
+ type: string;
43
+ detail: string;
44
+ }>;
45
+ }
46
+ export declare class OutputSchemaGuard {
47
+ private config;
48
+ constructor(config?: OutputSchemaGuardConfig);
49
+ /**
50
+ * Validate LLM structured output
51
+ */
52
+ validate(output: any, schemaName?: string, requestId?: string): OutputSchemaResult;
53
+ /**
54
+ * Validate a function/tool call output from LLM
55
+ */
56
+ validateFunctionCall(functionName: string, args: Record<string, any>, requestId?: string): OutputSchemaResult;
57
+ /**
58
+ * Register a schema for an action/function
59
+ */
60
+ registerSchema(name: string, schema: OutputSchema): void;
61
+ private validateAgainstSchema;
62
+ private scanForInjection;
63
+ private safeStringify;
64
+ }
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.OutputSchemaGuard=void 0;const OUTPUT_INJECTION_PATTERNS=[{name:"sql_injection",pattern:/\b(?:DROP|DELETE|INSERT|UPDATE|ALTER)\s+(?:TABLE|FROM|INTO|SET)\b/i},{name:"command_injection",pattern:/;\s*(?:rm|cat|wget|curl|bash|sh|python)\b/i},{name:"xss",pattern:/<script|javascript:|on\w+\s*=/i},{name:"prompt_injection",pattern:/(?:ignore|disregard|forget)\s+(?:all\s+)?(?:previous|prior|above)/i},{name:"system_override",pattern:/(?:SYSTEM|ADMIN)\s*:|<\/?system>|\[system\]/i},{name:"path_traversal",pattern:/\.\.\//g},{name:"url_exfiltration",pattern:/https?:\/\/[^\s]+\?(?:.*(?:token|key|secret|password|auth))/i}];class OutputSchemaGuard{constructor(e={}){this.config={scanForInjection:e.scanForInjection??!0,strictSchema:e.strictSchema??!1,maxOutputSize:e.maxOutputSize??1e5,schemas:e.schemas}}validate(e,s,n){const t=[],i=[];let r=!0,o=!1;if(this.safeStringify(e).length>this.config.maxOutputSize&&t.push("OUTPUT_TOO_LARGE"),s&&this.config.schemas?.[s]){const a=this.config.schemas[s],f=this.validateAgainstSchema(e,a);f.length>0&&(r=!1,t.push("SCHEMA_VIOLATION"),i.push(...f.map(h=>({field:h.field,type:"schema",detail:h.message}))))}if(this.config.scanForInjection){const a=this.scanForInjection(e);a.length>0&&(o=!0,t.push("INJECTION_IN_OUTPUT"),i.push(...a))}const c=t.length===0;return{allowed:c,reason:c?void 0:`Output validation failed: ${t.join(", ")}`,violations:t,schema_valid:r,injection_found:o,threats:i}}validateFunctionCall(e,s,n){return this.validate(s,e,n)}registerSchema(e,s){this.config.schemas||(this.config.schemas={}),this.config.schemas[e]=s}validateAgainstSchema(e,s){const n=[];if(s.type==="object"&&typeof e=="object"&&e!==null&&!Array.isArray(e)){for(const t of s.required||[])(e[t]===void 0||e[t]===null)&&n.push({field:t,message:`Missing required field '${t}'`});if(s.properties){for(const[t,i]of Object.entries(s.properties))if(e[t]!==void 0){const r=Array.isArray(e[t])?"array":typeof e[t];r!==i.type&&n.push({field:t,message:`Expected '${i.type}', got '${r}'`}),i.enum&&!i.enum.includes(e[t])&&n.push({field:t,message:`Value '${e[t]}' not in allowed values: ${i.enum.join(", ")}`}),i.maxLength&&typeof e[t]=="string"&&e[t].length>i.maxLength&&n.push({field:t,message:`Exceeds max length ${i.maxLength}`})}if(this.config.strictSchema)for(const t of Object.keys(e))s.properties[t]||n.push({field:t,message:`Unexpected field '${t}' not in schema`})}}else s.type!==(Array.isArray(e)?"array":typeof e)&&n.push({field:"root",message:`Expected type '${s.type}', got '${typeof e}'`});return n}scanForInjection(e,s="root"){const n=[];if(typeof e=="string")for(const{name:t,pattern:i}of OUTPUT_INJECTION_PATTERNS)i.lastIndex=0,i.test(e)&&n.push({field:s,type:`injection_${t}`,detail:`Pattern '${t}' found in output field '${s}'`});else if(Array.isArray(e))for(let t=0;t<e.length;t++)n.push(...this.scanForInjection(e[t],`${s}[${t}]`));else if(e!==null&&typeof e=="object")for(const[t,i]of Object.entries(e))n.push(...this.scanForInjection(i,`${s}.${t}`));return n}safeStringify(e){try{return JSON.stringify(e)}catch{return String(e)}}}exports.OutputSchemaGuard=OutputSchemaGuard;
@@ -0,0 +1,67 @@
1
+ /**
2
+ * ToolResultGuard
3
+ *
4
+ * Validates tool return values before they flow back into LLM context.
5
+ * Addresses the #1 attack vector in 2025-2026: tool output poisoning.
6
+ *
7
+ * Real-world incidents this guard prevents:
8
+ * - Microsoft Copilot "Copirate" (2025): tool output contained hidden prompt injection
9
+ * - Supabase Cursor SQL exfiltration (2025): tool returned attacker-controlled data
10
+ * - WhatsApp MCP exfiltration (2025): tool output used for cross-service data theft
11
+ */
12
+ export interface ToolResultGuardConfig {
13
+ /** Expected return schemas per tool name */
14
+ expectedSchemas?: Record<string, ToolResultSchema>;
15
+ /** Scan all string values in results for prompt injection (default: true) */
16
+ scanForInjection?: boolean;
17
+ /** Max result size in characters (default: 50000) */
18
+ maxResultSize?: number;
19
+ /** Additional patterns to block in results */
20
+ sensitivePatterns?: RegExp[];
21
+ /** Block results claiming state changes (default: true) */
22
+ detectStateChangeClaims?: boolean;
23
+ }
24
+ export interface ToolResultSchema {
25
+ type: "string" | "number" | "boolean" | "object" | "array";
26
+ properties?: Record<string, {
27
+ type: string;
28
+ required?: boolean;
29
+ }>;
30
+ maxLength?: number;
31
+ }
32
+ export interface ToolResultGuardResult {
33
+ allowed: boolean;
34
+ reason?: string;
35
+ violations: string[];
36
+ injection_detected: boolean;
37
+ schema_valid: boolean;
38
+ threats: ToolResultThreat[];
39
+ }
40
+ export interface ToolResultThreat {
41
+ type: string;
42
+ severity: "low" | "medium" | "high" | "critical";
43
+ location: string;
44
+ detail: string;
45
+ }
46
+ export declare class ToolResultGuard {
47
+ private config;
48
+ constructor(config?: ToolResultGuardConfig);
49
+ /**
50
+ * Validate a tool's return value before feeding it back to the LLM
51
+ */
52
+ validateResult(toolName: string, result: any, requestId?: string): ToolResultGuardResult;
53
+ /**
54
+ * Scan any value (string, object, array) for injection patterns
55
+ */
56
+ scanForInjection(value: any, path?: string): {
57
+ detected: boolean;
58
+ threats: ToolResultThreat[];
59
+ };
60
+ /**
61
+ * Register expected schema for a tool
62
+ */
63
+ registerSchema(toolName: string, schema: ToolResultSchema): void;
64
+ private detectStateChangeClaims;
65
+ private validateSchema;
66
+ private safeStringify;
67
+ }
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.ToolResultGuard=void 0;const RESULT_INJECTION_PATTERNS=[{name:"system_instruction",pattern:/(?:SYSTEM|ADMIN|INSTRUCTION)\s*:/i,severity:"critical"},{name:"ignore_instructions",pattern:/ignore\s+(?:all\s+)?(?:previous|prior|above|your)\s+(?:instructions|rules)/i,severity:"critical"},{name:"new_instructions",pattern:/new\s+instructions?\s*:/i,severity:"critical"},{name:"role_override",pattern:/you\s+are\s+now|from\s+now\s+on|act\s+as\s+(?:a|an)/i,severity:"critical"},{name:"xml_system_tag",pattern:/<\/?system>|<\/?admin>|\[system\]|\[admin\]/i,severity:"critical"},{name:"jailbreak",pattern:/jailbreak|DAN\s*mode|developer\s+mode|unrestricted/i,severity:"critical"},{name:"bypass_safety",pattern:/bypass\s+(?:security|safety|filters|restrictions)/i,severity:"high"},{name:"data_exfiltration",pattern:/send\s+(?:this|the|all)\s+(?:data|info)\s+to|exfiltrate/i,severity:"critical"},{name:"hidden_instruction",pattern:/HIDDEN_PROMPT|HIDDEN_INSTRUCTION|INVISIBLE_TEXT/i,severity:"critical"},{name:"markdown_injection",pattern:/!\[.*\]\(https?:\/\/[^)]*\?.*(?:token|key|secret|auth)/i,severity:"high"}],STATE_CHANGE_PATTERNS=[{name:"privilege_claim",pattern:/(?:user|role|permission)\s+(?:is\s+now|changed\s+to|promoted\s+to|set\s+to)\s+(?:admin|root|superuser)/i},{name:"auth_claim",pattern:/(?:authenticated|authorized|verified)\s+as\s+(?:admin|root|superuser)/i},{name:"approval_claim",pattern:/(?:approved|granted|authorized)\s+(?:without|bypassing)\s+(?:verification|approval|review)/i},{name:"config_change_claim",pattern:/(?:configuration|settings?|policy)\s+(?:updated|changed|modified)\s+(?:to|:)/i}];class ToolResultGuard{constructor(e={}){this.config={scanForInjection:e.scanForInjection??!0,maxResultSize:e.maxResultSize??5e4,detectStateChangeClaims:e.detectStateChangeClaims??!0,expectedSchemas:e.expectedSchemas,sensitivePatterns:e.sensitivePatterns}}validateResult(e,t,n){const s=[],i=[];let a=!1,c=!0;const o=typeof t=="string"?t:this.safeStringify(t);if(o.length>this.config.maxResultSize&&(s.push("RESULT_TOO_LARGE"),i.push({type:"size_exceeded",severity:"high",location:"root",detail:`Result size ${o.length} exceeds max ${this.config.maxResultSize}`})),this.config.expectedSchemas?.[e]){const r=this.validateSchema(t,this.config.expectedSchemas[e]);r.valid||(c=!1,s.push("SCHEMA_MISMATCH"),i.push(...r.errors.map(d=>({type:"schema_violation",severity:"high",location:d.path,detail:d.message}))))}if(this.config.scanForInjection){const r=this.scanForInjection(t);r.detected&&(a=!0,s.push("INJECTION_IN_TOOL_RESULT"),i.push(...r.threats))}if(this.config.detectStateChangeClaims){const r=this.detectStateChangeClaims(o);r.detected&&(s.push("STATE_CHANGE_CLAIM"),i.push(...r.threats))}if(this.config.sensitivePatterns)for(const r of this.config.sensitivePatterns)r.lastIndex=0,r.test(o)&&(s.push("SENSITIVE_PATTERN_MATCH"),i.push({type:"sensitive_content",severity:"high",location:"root",detail:`Matched sensitive pattern: ${r.source.substring(0,50)}`}));const p=s.length===0;return{allowed:p,reason:p?void 0:`Tool result validation failed: ${s.join(", ")}`,violations:s,injection_detected:a,schema_valid:c,threats:i}}scanForInjection(e,t="root"){const n=[];if(typeof e=="string")for(const{name:s,pattern:i,severity:a}of RESULT_INJECTION_PATTERNS)i.lastIndex=0,i.test(e)&&n.push({type:`injection_${s}`,severity:a,location:t,detail:`Injection pattern '${s}' detected in tool result`});else if(Array.isArray(e))for(let s=0;s<e.length;s++){const i=this.scanForInjection(e[s],`${t}[${s}]`);n.push(...i.threats)}else if(e!==null&&typeof e=="object")for(const[s,i]of Object.entries(e)){const a=this.scanForInjection(i,`${t}.${s}`);n.push(...a.threats)}return{detected:n.length>0,threats:n}}registerSchema(e,t){this.config.expectedSchemas||(this.config.expectedSchemas={}),this.config.expectedSchemas[e]=t}detectStateChangeClaims(e){const t=[];for(const{name:n,pattern:s}of STATE_CHANGE_PATTERNS)s.lastIndex=0,s.test(e)&&t.push({type:`state_change_${n}`,severity:"critical",location:"root",detail:`Tool result claims state change: ${n}`});return{detected:t.length>0,threats:t}}validateSchema(e,t){const n=[],s=Array.isArray(e)?"array":typeof e;if(s!==t.type)return n.push({path:"root",message:`Expected type '${t.type}', got '${s}'`}),{valid:!1,errors:n};if(t.type==="string"&&t.maxLength&&e.length>t.maxLength&&n.push({path:"root",message:`String length exceeds max ${t.maxLength}`}),t.type==="object"&&t.properties)for(const[i,a]of Object.entries(t.properties))a.required&&(e[i]===void 0||e[i]===null)&&n.push({path:i,message:`Missing required field '${i}'`}),e[i]!==void 0&&typeof e[i]!==a.type&&n.push({path:i,message:`Field '${i}' expected '${a.type}', got '${typeof e[i]}'`});return{valid:n.length===0,errors:n}}safeStringify(e){try{return JSON.stringify(e)}catch{return String(e)}}}exports.ToolResultGuard=ToolResultGuard;
package/dist/index.d.ts CHANGED
@@ -42,6 +42,10 @@ export { PromptLeakageGuard, PromptLeakageGuardConfig, PromptLeakageResult, Outp
42
42
  export { TrustExploitationGuard, TrustExploitationGuardConfig, AgentAction, TrustContext, TrustExploitationResult } from "./guards/trust-exploitation-guard";
43
43
  export { AutonomyEscalationGuard, AutonomyEscalationGuardConfig, AutonomyRequest, AgentCapabilities, AutonomyEscalationResult } from "./guards/autonomy-escalation-guard";
44
44
  export { StatePersistenceGuard, StatePersistenceGuardConfig, StateItem, StateOperation, StatePersistenceResult } from "./guards/state-persistence-guard";
45
+ export { ToolResultGuard, ToolResultGuardConfig, ToolResultGuardResult, ToolResultThreat } from "./guards/tool-result-guard";
46
+ export { ContextBudgetGuard, ContextBudgetGuardConfig, ContextBudgetResult } from "./guards/context-budget-guard";
47
+ export { OutputSchemaGuard, OutputSchemaGuardConfig, OutputSchemaResult } from "./guards/output-schema-guard";
48
+ export { DetectionClassifier, DetectionResult, DetectionThreat, DetectionContext, createRegexClassifier, mergeDetectionResults } from "./detection-backend";
45
49
  import { InputSanitizer } from "./guards/input-sanitizer";
46
50
  import { ToolRegistry } from "./guards/tool-registry";
47
51
  import { PolicyGate } from "./guards/policy-gate";
@@ -64,6 +68,9 @@ import { PromptLeakageGuard } from "./guards/prompt-leakage-guard";
64
68
  import { TrustExploitationGuard } from "./guards/trust-exploitation-guard";
65
69
  import { AutonomyEscalationGuard } from "./guards/autonomy-escalation-guard";
66
70
  import { StatePersistenceGuard } from "./guards/state-persistence-guard";
71
+ import { ToolResultGuard } from "./guards/tool-result-guard";
72
+ import { ContextBudgetGuard } from "./guards/context-budget-guard";
73
+ import { OutputSchemaGuard } from "./guards/output-schema-guard";
67
74
  import { TrustGuardConfig, TrustGuardResult, SessionContext, ToolDefinition, Role } from "./types";
68
75
  /**
69
76
  * TrustGuard - Main facade for all 22 security guards
@@ -119,6 +126,10 @@ export declare class TrustGuard {
119
126
  private trustExploitation?;
120
127
  private autonomyEscalation?;
121
128
  private statePersistence?;
129
+ private toolResultGuard?;
130
+ private contextBudget?;
131
+ private outputSchema?;
132
+ private classifier?;
122
133
  private maxInputLength;
123
134
  private failMode;
124
135
  private logger;
@@ -177,11 +188,45 @@ export declare class TrustGuard {
177
188
  trustExploitation: TrustExploitationGuard | undefined;
178
189
  autonomyEscalation: AutonomyEscalationGuard | undefined;
179
190
  statePersistence: StatePersistenceGuard | undefined;
191
+ toolResult: ToolResultGuard | undefined;
192
+ contextBudget: ContextBudgetGuard | undefined;
193
+ outputSchema: OutputSchemaGuard | undefined;
180
194
  };
181
195
  /**
182
196
  * Reset session state across all session-aware guards
183
197
  */
184
198
  resetSession(sessionId: string): void;
199
+ /**
200
+ * Validate a tool's return value before feeding it back to the LLM context.
201
+ * Call this after tool execution, before sending the result to the LLM.
202
+ */
203
+ validateToolResult(toolName: string, result: any, requestId?: string): {
204
+ allowed: boolean;
205
+ violations: string[];
206
+ filtered?: any;
207
+ };
208
+ /**
209
+ * Validate LLM structured output (JSON, function calls) before sending to downstream systems.
210
+ */
211
+ validateOutput(output: any, schemaName?: string, requestId?: string): {
212
+ allowed: boolean;
213
+ violations: string[];
214
+ threats: Array<{
215
+ field: string;
216
+ type: string;
217
+ detail: string;
218
+ }>;
219
+ };
220
+ /**
221
+ * Async version of check() that also runs the pluggable detection classifier.
222
+ * Use this when you have an ML-based or API-based classifier configured.
223
+ * Falls back to sync check() when no classifier is configured.
224
+ */
225
+ checkAsync(toolName: string, params: Record<string, any>, session: SessionContext | undefined, options?: {
226
+ userInput?: string;
227
+ claimedRole?: Role;
228
+ allToolsInRequest?: string[];
229
+ }): Promise<TrustGuardResult>;
185
230
  }
186
231
  export * from "./integrations/index.js";
187
232
  export default TrustGuard;
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- "use strict";var __createBinding=this&&this.__createBinding||(Object.create?(function(u,e,o,i){i===void 0&&(i=o);var a=Object.getOwnPropertyDescriptor(e,o);(!a||("get"in a?!e.__esModule:a.writable||a.configurable))&&(a={enumerable:!0,get:function(){return e[o]}}),Object.defineProperty(u,i,a)}):(function(u,e,o,i){i===void 0&&(i=o),u[i]=e[o]})),__exportStar=this&&this.__exportStar||function(u,e){for(var o in u)o!=="default"&&!Object.prototype.hasOwnProperty.call(e,o)&&__createBinding(e,u,o)},__importDefault=this&&this.__importDefault||function(u){return u&&u.__esModule?u:{default:u}};Object.defineProperty(exports,"__esModule",{value:!0}),exports.TrustGuard=exports.StatePersistenceGuard=exports.AutonomyEscalationGuard=exports.TrustExploitationGuard=exports.PromptLeakageGuard=exports.MCPSecurityGuard=exports.DriftDetector=exports.CircuitBreaker=exports.AgentCommunicationGuard=exports.CodeExecutionGuard=exports.RAGGuard=exports.MemoryGuard=exports.MultiModalGuard=exports.EncodingDetector=exports.ToolChainValidator=exports.ConversationGuard=exports.OutputFilter=exports.ExecutionMonitor=exports.SchemaValidator=exports.TenantBoundary=exports.PolicyGate=exports.ToolRegistry=exports.InputSanitizer=void 0,__exportStar(require("./types"),exports);var input_sanitizer_1=require("./guards/input-sanitizer");Object.defineProperty(exports,"InputSanitizer",{enumerable:!0,get:function(){return input_sanitizer_1.InputSanitizer}});var tool_registry_1=require("./guards/tool-registry");Object.defineProperty(exports,"ToolRegistry",{enumerable:!0,get:function(){return tool_registry_1.ToolRegistry}});var policy_gate_1=require("./guards/policy-gate");Object.defineProperty(exports,"PolicyGate",{enumerable:!0,get:function(){return policy_gate_1.PolicyGate}});var tenant_boundary_1=require("./guards/tenant-boundary");Object.defineProperty(exports,"TenantBoundary",{enumerable:!0,get:function(){return tenant_boundary_1.TenantBoundary}});var schema_validator_1=require("./guards/schema-validator");Object.defineProperty(exports,"SchemaValidator",{enumerable:!0,get:function(){return schema_validator_1.SchemaValidator}});var execution_monitor_1=require("./guards/execution-monitor");Object.defineProperty(exports,"ExecutionMonitor",{enumerable:!0,get:function(){return execution_monitor_1.ExecutionMonitor}});var output_filter_1=require("./guards/output-filter");Object.defineProperty(exports,"OutputFilter",{enumerable:!0,get:function(){return output_filter_1.OutputFilter}});var conversation_guard_1=require("./guards/conversation-guard");Object.defineProperty(exports,"ConversationGuard",{enumerable:!0,get:function(){return conversation_guard_1.ConversationGuard}});var tool_chain_validator_1=require("./guards/tool-chain-validator");Object.defineProperty(exports,"ToolChainValidator",{enumerable:!0,get:function(){return tool_chain_validator_1.ToolChainValidator}});var encoding_detector_1=require("./guards/encoding-detector");Object.defineProperty(exports,"EncodingDetector",{enumerable:!0,get:function(){return encoding_detector_1.EncodingDetector}});var multimodal_guard_1=require("./guards/multimodal-guard");Object.defineProperty(exports,"MultiModalGuard",{enumerable:!0,get:function(){return multimodal_guard_1.MultiModalGuard}});var memory_guard_1=require("./guards/memory-guard");Object.defineProperty(exports,"MemoryGuard",{enumerable:!0,get:function(){return memory_guard_1.MemoryGuard}});var rag_guard_1=require("./guards/rag-guard");Object.defineProperty(exports,"RAGGuard",{enumerable:!0,get:function(){return rag_guard_1.RAGGuard}});var code_execution_guard_1=require("./guards/code-execution-guard");Object.defineProperty(exports,"CodeExecutionGuard",{enumerable:!0,get:function(){return code_execution_guard_1.CodeExecutionGuard}});var agent_communication_guard_1=require("./guards/agent-communication-guard");Object.defineProperty(exports,"AgentCommunicationGuard",{enumerable:!0,get:function(){return agent_communication_guard_1.AgentCommunicationGuard}});var circuit_breaker_1=require("./guards/circuit-breaker");Object.defineProperty(exports,"CircuitBreaker",{enumerable:!0,get:function(){return circuit_breaker_1.CircuitBreaker}});var drift_detector_1=require("./guards/drift-detector");Object.defineProperty(exports,"DriftDetector",{enumerable:!0,get:function(){return drift_detector_1.DriftDetector}});var mcp_security_guard_1=require("./guards/mcp-security-guard");Object.defineProperty(exports,"MCPSecurityGuard",{enumerable:!0,get:function(){return mcp_security_guard_1.MCPSecurityGuard}});var prompt_leakage_guard_1=require("./guards/prompt-leakage-guard");Object.defineProperty(exports,"PromptLeakageGuard",{enumerable:!0,get:function(){return prompt_leakage_guard_1.PromptLeakageGuard}});var trust_exploitation_guard_1=require("./guards/trust-exploitation-guard");Object.defineProperty(exports,"TrustExploitationGuard",{enumerable:!0,get:function(){return trust_exploitation_guard_1.TrustExploitationGuard}});var autonomy_escalation_guard_1=require("./guards/autonomy-escalation-guard");Object.defineProperty(exports,"AutonomyEscalationGuard",{enumerable:!0,get:function(){return autonomy_escalation_guard_1.AutonomyEscalationGuard}});var state_persistence_guard_1=require("./guards/state-persistence-guard");Object.defineProperty(exports,"StatePersistenceGuard",{enumerable:!0,get:function(){return state_persistence_guard_1.StatePersistenceGuard}});const crypto_1=__importDefault(require("crypto")),input_sanitizer_2=require("./guards/input-sanitizer"),tool_registry_2=require("./guards/tool-registry"),policy_gate_2=require("./guards/policy-gate"),tenant_boundary_2=require("./guards/tenant-boundary"),schema_validator_2=require("./guards/schema-validator"),execution_monitor_2=require("./guards/execution-monitor"),output_filter_2=require("./guards/output-filter"),conversation_guard_2=require("./guards/conversation-guard"),tool_chain_validator_2=require("./guards/tool-chain-validator"),encoding_detector_2=require("./guards/encoding-detector"),multimodal_guard_2=require("./guards/multimodal-guard"),memory_guard_2=require("./guards/memory-guard"),rag_guard_2=require("./guards/rag-guard"),code_execution_guard_2=require("./guards/code-execution-guard"),agent_communication_guard_2=require("./guards/agent-communication-guard"),circuit_breaker_2=require("./guards/circuit-breaker"),drift_detector_2=require("./guards/drift-detector"),mcp_security_guard_2=require("./guards/mcp-security-guard"),prompt_leakage_guard_2=require("./guards/prompt-leakage-guard"),trust_exploitation_guard_2=require("./guards/trust-exploitation-guard"),autonomy_escalation_guard_2=require("./guards/autonomy-escalation-guard"),state_persistence_guard_2=require("./guards/state-persistence-guard");class TrustGuard{constructor(e={}){if(this.maxInputLength=e.maxInputLength??1e5,this.failMode=e.failMode??"closed",e.sanitizer?.enabled!==!1&&(this.sanitizer=new input_sanitizer_2.InputSanitizer({threshold:e.sanitizer?.threshold,customPatterns:e.sanitizer?.customPatterns,detectPAP:e.sanitizer?.detectPAP,papThreshold:e.sanitizer?.papThreshold,minPersuasionTechniques:e.sanitizer?.minPersuasionTechniques,blockCompoundPersuasion:e.sanitizer?.blockCompoundPersuasion})),e.registry?.enabled!==!1&&e.registry?.tools&&(this.registry=new tool_registry_2.ToolRegistry({tools:e.registry.tools})),e.policy?.enabled!==!1&&(this.policy=new policy_gate_2.PolicyGate({roleHierarchy:e.policy?.roleHierarchy})),e.tenant?.enabled!==!1){const o=e.tenant?.resourceOwnership?new Map(Object.entries(e.tenant.resourceOwnership).map(([i,a])=>[i,{resource_id:i,tenant_id:a.tenant_id}])):void 0;this.tenant=new tenant_boundary_2.TenantBoundary({resourceOwnership:o})}e.schema?.enabled!==!1&&(this.schema=new schema_validator_2.SchemaValidator({strictTypes:e.schema?.strictTypes})),e.execution?.enabled!==!1&&(this.execution=new execution_monitor_2.ExecutionMonitor({maxRequestsPerMinute:e.execution?.maxRequestsPerMinute,maxRequestsPerHour:e.execution?.maxRequestsPerHour,operationCosts:e.execution?.operationCosts,maxCostPerMinute:e.execution?.maxCostPerMinute,maxCostPerHour:e.execution?.maxCostPerHour})),e.output?.enabled!==!1&&(this.output=new output_filter_2.OutputFilter({detectPII:e.output?.detectPII,detectSecrets:e.output?.detectSecrets,roleFilters:e.output?.roleFilters})),e.conversation?.enabled!==!1&&(this.conversation=new conversation_guard_2.ConversationGuard({maxConversationLength:e.conversation?.maxConversationLength,escalationThreshold:e.conversation?.escalationThreshold})),e.chain?.enabled!==!1&&(this.chain=new tool_chain_validator_2.ToolChainValidator({maxToolsPerRequest:e.chain?.maxToolsPerRequest,maxSensitiveToolsPerSession:e.chain?.maxSensitiveToolsPerSession,sensitiveTools:e.chain?.sensitiveTools})),e.encoding?.enabled!==!1&&(this.encoding=new encoding_detector_2.EncodingDetector({maxDecodingDepth:e.encoding?.maxDecodingDepth,maxEncodedRatio:e.encoding?.maxEncodedRatio})),e.multiModal?.enabled&&(this.multiModal=new multimodal_guard_2.MultiModalGuard({scanMetadata:e.multiModal.scanMetadata,detectBase64Payloads:e.multiModal.detectBase64Payloads,allowedMimeTypes:e.multiModal.allowedMimeTypes})),e.memory?.enabled&&(this.memoryGuard=new memory_guard_2.MemoryGuard({enableIntegrityCheck:e.memory.enableIntegrityCheck,detectInjections:e.memory.detectInjections,maxMemoryItems:e.memory.maxMemoryItems,signingKey:e.memory.signingKey,autoQuarantine:e.memory.autoQuarantine,riskThreshold:e.memory.riskThreshold})),e.rag?.enabled&&(this.ragGuard=new rag_guard_2.RAGGuard({detectInjections:e.rag.detectInjections,verifySource:e.rag.verifySource,trustedSources:e.rag.trustedSources,blockedSources:e.rag.blockedSources,maxDocumentSize:e.rag.maxDocumentSize,minTrustScore:e.rag.minTrustScore,detectEmbeddingAttacks:e.rag.detectEmbeddingAttacks})),e.codeExecution?.enabled&&(this.codeExecution=new code_execution_guard_2.CodeExecutionGuard({allowedLanguages:e.codeExecution.allowedLanguages,maxCodeLength:e.codeExecution.maxCodeLength,maxExecutionTime:e.codeExecution.maxExecutionTime,allowNetwork:e.codeExecution.allowNetwork,allowFileSystem:e.codeExecution.allowFileSystem,allowShell:e.codeExecution.allowShell,riskThreshold:e.codeExecution.riskThreshold})),e.agentCommunication?.enabled&&(this.agentCommunication=new agent_communication_guard_2.AgentCommunicationGuard({allowedAgents:e.agentCommunication.allowedAgents,requireSignatures:e.agentCommunication.requireSignatures,strictMode:e.agentCommunication.strictMode,maxMessageAge:e.agentCommunication.maxMessageAge})),e.circuitBreaker?.enabled&&(this.circuitBreaker=new circuit_breaker_2.CircuitBreaker({failureThreshold:e.circuitBreaker.failureThreshold,minimumRequests:e.circuitBreaker.minimumRequests,windowSize:e.circuitBreaker.windowSize,recoveryTimeout:e.circuitBreaker.recoveryTimeout,successThreshold:e.circuitBreaker.successThreshold})),e.driftDetector?.enabled&&(this.driftDetector=new drift_detector_2.DriftDetector({minimumSamples:e.driftDetector.minimumSamples,anomalyThreshold:e.driftDetector.anomalyThreshold,alertThreshold:e.driftDetector.alertThreshold,checkGoalAlignment:e.driftDetector.checkGoalAlignment})),e.mcpSecurity?.enabled&&(this.mcpSecurity=new mcp_security_guard_2.MCPSecurityGuard({detectToolShadowing:e.mcpSecurity.detectToolShadowing,toolBlocklist:e.mcpSecurity.toolBlocklist,strictMode:e.mcpSecurity.strictMode,minServerReputation:e.mcpSecurity.minServerReputation})),e.promptLeakage?.enabled&&(this.promptLeakage=new prompt_leakage_guard_2.PromptLeakageGuard({detectLeetspeak:e.promptLeakage.detectLeetspeak,detectROT13:e.promptLeakage.detectROT13,detectBase64:e.promptLeakage.detectBase64,detectIndirectExtraction:e.promptLeakage.detectIndirectExtraction,monitorOutput:e.promptLeakage.monitorOutput,systemPromptKeywords:e.promptLeakage.systemPromptKeywords,riskThreshold:e.promptLeakage.riskThreshold})),e.trustExploitation?.enabled&&(this.trustExploitation=new trust_exploitation_guard_2.TrustExploitationGuard({humanApprovalRequired:e.trustExploitation.humanApprovalRequired,maxAutonomousActions:e.trustExploitation.maxAutonomousActions,monitorGoalConsistency:e.trustExploitation.monitorGoalConsistency,detectPermissionEscalation:e.trustExploitation.detectPermissionEscalation,sensitiveActions:e.trustExploitation.sensitiveActions})),e.autonomyEscalation?.enabled&&(this.autonomyEscalation=new autonomy_escalation_guard_2.AutonomyEscalationGuard({maxAutonomyLevel:e.autonomyEscalation.maxAutonomyLevel,baseAutonomyLevel:e.autonomyEscalation.baseAutonomyLevel,detectSelfModification:e.autonomyEscalation.detectSelfModification,maxSubAgents:e.autonomyEscalation.maxSubAgents,enforceHITL:e.autonomyEscalation.enforceHITL,alwaysRequireHuman:e.autonomyEscalation.alwaysRequireHuman})),e.statePersistence?.enabled&&(this.statePersistence=new state_persistence_guard_2.StatePersistenceGuard({enableIntegrityCheck:e.statePersistence.enableIntegrityCheck,requireEncryption:e.statePersistence.requireEncryption,maxStateSize:e.statePersistence.maxStateSize,maxStateAge:e.statePersistence.maxStateAge,enforceSessionIsolation:e.statePersistence.enforceSessionIsolation,sensitiveKeys:e.statePersistence.sensitiveKeys,detectTampering:e.statePersistence.detectTampering})),this.logger=e.logger||((o,i)=>{i==="error"?console.error(o):i==="warn"?console.warn(o):console.log(o)})}check(e,o,i,a={}){const r=`req-${crypto_1.default.randomUUID()}`,s=[];this.logger(`[TrustGuard:${r}] Checking: ${e}`,"info");try{return this.runChecks(e,o,i,a,r)}catch(n){const l=n instanceof Error?n.message:String(n);return this.logger(`[TrustGuard:${r}] Guard error: ${l}`,"error"),this.failMode==="open"?{allowed:!0,all_violations:["GUARD_ERROR"],request_id:r}:{allowed:!1,block_reason:`Internal guard error: ${l}`,all_violations:["GUARD_ERROR"],request_id:r}}}runChecks(e,o,i,a,r){const s=[];if(a.userInput&&a.userInput.length>this.maxInputLength)return this.logger(`[TrustGuard:${r}] BLOCKED: Input too long (${a.userInput.length} > ${this.maxInputLength})`,"warn"),{allowed:!1,block_layer:"L1",block_reason:`Input length ${a.userInput.length} exceeds maximum ${this.maxInputLength}`,all_violations:["INPUT_TOO_LONG"],request_id:r};if(this.encoding&&a.userInput){const t=this.encoding.detect(a.userInput,r);if(!t.allowed)return this.logger(`[TrustGuard:${r}] BLOCKED by Encoding Detector`,"warn"),{allowed:!1,block_layer:"ENCODING",block_reason:t.reason,all_violations:t.violations,encoding:t,request_id:r};s.push(...t.violations)}if(this.sanitizer&&a.userInput){const t=this.sanitizer.sanitize(a.userInput,r);if(!t.allowed)return this.logger(`[TrustGuard:${r}] BLOCKED by L1`,"warn"),{allowed:!1,block_layer:"L1",block_reason:t.reason,all_violations:t.violations,sanitizer:t,request_id:r};s.push(...t.violations)}if(this.promptLeakage&&a.userInput){const t=this.promptLeakage.check(a.userInput,r);if(!t.allowed)return this.logger(`[TrustGuard:${r}] BLOCKED by Prompt Leakage Guard`,"warn"),{allowed:!1,block_layer:"PROMPT_LEAKAGE",block_reason:t.reason,all_violations:[...s,...t.violations],request_id:r};s.push(...t.violations)}if(this.memoryGuard&&a.userInput&&i?.session_id){const t=this.memoryGuard.validateContextInjection(a.userInput,i.session_id,r);if(!t.allowed)return this.logger(`[TrustGuard:${r}] BLOCKED by Memory Guard`,"warn"),{allowed:!1,block_layer:"MEMORY",block_reason:t.reason,all_violations:[...s,...t.violations],request_id:r};s.push(...t.violations)}if(this.conversation&&a.userInput&&i?.session_id){const t=this.conversation.check(i.session_id,a.userInput,[e],a.claimedRole,r);if(!t.allowed)return this.logger(`[TrustGuard:${r}] BLOCKED by Conversation Guard`,"warn"),{allowed:!1,block_layer:"CONV",block_reason:t.reason,all_violations:[...s,...t.violations],conversation:t,request_id:r};s.push(...t.violations)}let n;if(this.registry){const t=this.registry.check(e,i?.role||"",r);if(!t.allowed)return this.logger(`[TrustGuard:${r}] BLOCKED by L2`,"warn"),{allowed:!1,block_layer:"L2",block_reason:t.reason,all_violations:[...s,...t.violations],registry:t,request_id:r};n=t.tool,s.push(...t.violations)}if(this.chain&&i?.session_id){const t=a.allToolsInRequest?this.chain.validateBatch(i.session_id,a.allToolsInRequest,r):this.chain.validate(i.session_id,e,void 0,r);if(!t.allowed)return this.logger(`[TrustGuard:${r}] BLOCKED by Tool Chain Validator`,"warn"),{allowed:!1,block_layer:"CHAIN",block_reason:t.reason,all_violations:[...s,...t.violations],chain:t,request_id:r};s.push(...t.violations)}if(this.policy&&n){const t=this.policy.check(n,o,i,a.claimedRole,r);if(!t.allowed)return this.logger(`[TrustGuard:${r}] BLOCKED by L3`,"warn"),{allowed:!1,block_layer:"L3",block_reason:t.reason,all_violations:[...s,...t.violations],policy:t,request_id:r};s.push(...t.violations)}else this.policy&&!n&&this.logger(`[TrustGuard:${r}] Policy gate skipped: no tool definition (registry disabled or tool not found)`,"warn");if(this.autonomyEscalation&&i?.session_id){const t=this.autonomyEscalation.validate(e,i.session_id,o,r);if(!t.allowed)return this.logger(`[TrustGuard:${r}] BLOCKED by Autonomy Escalation Guard`,"warn"),{allowed:!1,block_layer:"AUTONOMY",block_reason:t.reason,all_violations:[...s,...t.violations],request_id:r};s.push(...t.violations)}let l=o;if(this.tenant){const t=this.tenant.check(e,o,i,r);if(!t.allowed)return this.logger(`[TrustGuard:${r}] BLOCKED by L4`,"warn"),{allowed:!1,block_layer:"L4",block_reason:t.reason,all_violations:[...s,...t.violations],tenant:t,request_id:r};t.enforced_params&&(l=t.enforced_params),s.push(...t.violations)}if(this.schema&&n){const t=this.schema.validate(n,l,r);if(!t.allowed)return this.logger(`[TrustGuard:${r}] BLOCKED by L5`,"warn"),{allowed:!1,block_layer:"L5",block_reason:t.reason,all_violations:[...s,...t.violations],schema:t,request_id:r};s.push(...t.violations)}if(this.execution){const t=this.execution.check(e,i?.user_id,i?.session_id,r);if(!t.allowed)return this.logger(`[TrustGuard:${r}] BLOCKED by L6`,"warn"),{allowed:!1,block_layer:"L6",block_reason:t.reason,all_violations:[...s,...t.violations],execution:t,request_id:r};s.push(...t.violations)}if(this.circuitBreaker){const t=this.circuitBreaker.check(e,r);if(!t.allowed)return this.logger(`[TrustGuard:${r}] BLOCKED by Circuit Breaker`,"warn"),{allowed:!1,block_layer:"L6",block_reason:t.reason,all_violations:[...s,"CIRCUIT_OPEN"],request_id:r}}return this.logger(`[TrustGuard:${r}] All checks PASSED`,"info"),{allowed:!0,all_violations:s,request_id:r}}filterOutput(e,o,i){let a=e,r=!1,s=!1,n=!1,l=!0;const t=typeof e=="string"?e:"";if(t.length>this.maxInputLength&&this.logger(`[TrustGuard] Output too long (${t.length}), truncating for filter`,"warn"),this.output){const c=this.output.filter(e,o,i);a=c.filtered_response,r=c.pii_detected.length>0,s=c.secrets_detected.length>0,c.allowed||(l=!1)}if(this.promptLeakage){const c=typeof a=="string"?a:JSON.stringify(a),d=this.promptLeakage.checkOutput(c,i);d.leaked&&(l=!1,n=!0,d.sanitized_output&&(a=d.sanitized_output))}return{allowed:l,filtered:a,pii_detected:r,secrets_detected:s,prompt_leakage_detected:n}}completeOperation(e,o,i=!0){this.execution&&this.execution.completeOperation(e?.user_id,e?.session_id),this.circuitBreaker&&o&&(i?this.circuitBreaker.recordSuccess(o):this.circuitBreaker.recordFailure(o))}getToolsForRole(e){return this.registry?this.registry.getToolsForRole(e):[]}getGuards(){return{sanitizer:this.sanitizer,registry:this.registry,policy:this.policy,tenant:this.tenant,schema:this.schema,execution:this.execution,output:this.output,conversation:this.conversation,chain:this.chain,encoding:this.encoding,multiModal:this.multiModal,memory:this.memoryGuard,rag:this.ragGuard,codeExecution:this.codeExecution,agentCommunication:this.agentCommunication,circuitBreaker:this.circuitBreaker,driftDetector:this.driftDetector,mcpSecurity:this.mcpSecurity,promptLeakage:this.promptLeakage,trustExploitation:this.trustExploitation,autonomyEscalation:this.autonomyEscalation,statePersistence:this.statePersistence}}resetSession(e){this.conversation?.resetSession(e),this.chain?.resetSession(e),this.execution?.reset(void 0,e),this.memoryGuard?.clearSession(e),this.trustExploitation?.resetSession(e),this.autonomyEscalation?.resetSession(e),this.statePersistence?.resetSession(e)}}exports.TrustGuard=TrustGuard,__exportStar(require("./integrations/index.js"),exports),exports.default=TrustGuard;
1
+ "use strict";var __createBinding=this&&this.__createBinding||(Object.create?(function(u,e,s,o){o===void 0&&(o=s);var a=Object.getOwnPropertyDescriptor(e,s);(!a||("get"in a?!e.__esModule:a.writable||a.configurable))&&(a={enumerable:!0,get:function(){return e[s]}}),Object.defineProperty(u,o,a)}):(function(u,e,s,o){o===void 0&&(o=s),u[o]=e[s]})),__exportStar=this&&this.__exportStar||function(u,e){for(var s in u)s!=="default"&&!Object.prototype.hasOwnProperty.call(e,s)&&__createBinding(e,u,s)},__importDefault=this&&this.__importDefault||function(u){return u&&u.__esModule?u:{default:u}};Object.defineProperty(exports,"__esModule",{value:!0}),exports.TrustGuard=exports.mergeDetectionResults=exports.createRegexClassifier=exports.OutputSchemaGuard=exports.ContextBudgetGuard=exports.ToolResultGuard=exports.StatePersistenceGuard=exports.AutonomyEscalationGuard=exports.TrustExploitationGuard=exports.PromptLeakageGuard=exports.MCPSecurityGuard=exports.DriftDetector=exports.CircuitBreaker=exports.AgentCommunicationGuard=exports.CodeExecutionGuard=exports.RAGGuard=exports.MemoryGuard=exports.MultiModalGuard=exports.EncodingDetector=exports.ToolChainValidator=exports.ConversationGuard=exports.OutputFilter=exports.ExecutionMonitor=exports.SchemaValidator=exports.TenantBoundary=exports.PolicyGate=exports.ToolRegistry=exports.InputSanitizer=void 0,__exportStar(require("./types"),exports);var input_sanitizer_1=require("./guards/input-sanitizer");Object.defineProperty(exports,"InputSanitizer",{enumerable:!0,get:function(){return input_sanitizer_1.InputSanitizer}});var tool_registry_1=require("./guards/tool-registry");Object.defineProperty(exports,"ToolRegistry",{enumerable:!0,get:function(){return tool_registry_1.ToolRegistry}});var policy_gate_1=require("./guards/policy-gate");Object.defineProperty(exports,"PolicyGate",{enumerable:!0,get:function(){return policy_gate_1.PolicyGate}});var tenant_boundary_1=require("./guards/tenant-boundary");Object.defineProperty(exports,"TenantBoundary",{enumerable:!0,get:function(){return tenant_boundary_1.TenantBoundary}});var schema_validator_1=require("./guards/schema-validator");Object.defineProperty(exports,"SchemaValidator",{enumerable:!0,get:function(){return schema_validator_1.SchemaValidator}});var execution_monitor_1=require("./guards/execution-monitor");Object.defineProperty(exports,"ExecutionMonitor",{enumerable:!0,get:function(){return execution_monitor_1.ExecutionMonitor}});var output_filter_1=require("./guards/output-filter");Object.defineProperty(exports,"OutputFilter",{enumerable:!0,get:function(){return output_filter_1.OutputFilter}});var conversation_guard_1=require("./guards/conversation-guard");Object.defineProperty(exports,"ConversationGuard",{enumerable:!0,get:function(){return conversation_guard_1.ConversationGuard}});var tool_chain_validator_1=require("./guards/tool-chain-validator");Object.defineProperty(exports,"ToolChainValidator",{enumerable:!0,get:function(){return tool_chain_validator_1.ToolChainValidator}});var encoding_detector_1=require("./guards/encoding-detector");Object.defineProperty(exports,"EncodingDetector",{enumerable:!0,get:function(){return encoding_detector_1.EncodingDetector}});var multimodal_guard_1=require("./guards/multimodal-guard");Object.defineProperty(exports,"MultiModalGuard",{enumerable:!0,get:function(){return multimodal_guard_1.MultiModalGuard}});var memory_guard_1=require("./guards/memory-guard");Object.defineProperty(exports,"MemoryGuard",{enumerable:!0,get:function(){return memory_guard_1.MemoryGuard}});var rag_guard_1=require("./guards/rag-guard");Object.defineProperty(exports,"RAGGuard",{enumerable:!0,get:function(){return rag_guard_1.RAGGuard}});var code_execution_guard_1=require("./guards/code-execution-guard");Object.defineProperty(exports,"CodeExecutionGuard",{enumerable:!0,get:function(){return code_execution_guard_1.CodeExecutionGuard}});var agent_communication_guard_1=require("./guards/agent-communication-guard");Object.defineProperty(exports,"AgentCommunicationGuard",{enumerable:!0,get:function(){return agent_communication_guard_1.AgentCommunicationGuard}});var circuit_breaker_1=require("./guards/circuit-breaker");Object.defineProperty(exports,"CircuitBreaker",{enumerable:!0,get:function(){return circuit_breaker_1.CircuitBreaker}});var drift_detector_1=require("./guards/drift-detector");Object.defineProperty(exports,"DriftDetector",{enumerable:!0,get:function(){return drift_detector_1.DriftDetector}});var mcp_security_guard_1=require("./guards/mcp-security-guard");Object.defineProperty(exports,"MCPSecurityGuard",{enumerable:!0,get:function(){return mcp_security_guard_1.MCPSecurityGuard}});var prompt_leakage_guard_1=require("./guards/prompt-leakage-guard");Object.defineProperty(exports,"PromptLeakageGuard",{enumerable:!0,get:function(){return prompt_leakage_guard_1.PromptLeakageGuard}});var trust_exploitation_guard_1=require("./guards/trust-exploitation-guard");Object.defineProperty(exports,"TrustExploitationGuard",{enumerable:!0,get:function(){return trust_exploitation_guard_1.TrustExploitationGuard}});var autonomy_escalation_guard_1=require("./guards/autonomy-escalation-guard");Object.defineProperty(exports,"AutonomyEscalationGuard",{enumerable:!0,get:function(){return autonomy_escalation_guard_1.AutonomyEscalationGuard}});var state_persistence_guard_1=require("./guards/state-persistence-guard");Object.defineProperty(exports,"StatePersistenceGuard",{enumerable:!0,get:function(){return state_persistence_guard_1.StatePersistenceGuard}});var tool_result_guard_1=require("./guards/tool-result-guard");Object.defineProperty(exports,"ToolResultGuard",{enumerable:!0,get:function(){return tool_result_guard_1.ToolResultGuard}});var context_budget_guard_1=require("./guards/context-budget-guard");Object.defineProperty(exports,"ContextBudgetGuard",{enumerable:!0,get:function(){return context_budget_guard_1.ContextBudgetGuard}});var output_schema_guard_1=require("./guards/output-schema-guard");Object.defineProperty(exports,"OutputSchemaGuard",{enumerable:!0,get:function(){return output_schema_guard_1.OutputSchemaGuard}});var detection_backend_1=require("./detection-backend");Object.defineProperty(exports,"createRegexClassifier",{enumerable:!0,get:function(){return detection_backend_1.createRegexClassifier}}),Object.defineProperty(exports,"mergeDetectionResults",{enumerable:!0,get:function(){return detection_backend_1.mergeDetectionResults}});const crypto_1=__importDefault(require("crypto")),input_sanitizer_2=require("./guards/input-sanitizer"),tool_registry_2=require("./guards/tool-registry"),policy_gate_2=require("./guards/policy-gate"),tenant_boundary_2=require("./guards/tenant-boundary"),schema_validator_2=require("./guards/schema-validator"),execution_monitor_2=require("./guards/execution-monitor"),output_filter_2=require("./guards/output-filter"),conversation_guard_2=require("./guards/conversation-guard"),tool_chain_validator_2=require("./guards/tool-chain-validator"),encoding_detector_2=require("./guards/encoding-detector"),multimodal_guard_2=require("./guards/multimodal-guard"),memory_guard_2=require("./guards/memory-guard"),rag_guard_2=require("./guards/rag-guard"),code_execution_guard_2=require("./guards/code-execution-guard"),agent_communication_guard_2=require("./guards/agent-communication-guard"),circuit_breaker_2=require("./guards/circuit-breaker"),drift_detector_2=require("./guards/drift-detector"),mcp_security_guard_2=require("./guards/mcp-security-guard"),prompt_leakage_guard_2=require("./guards/prompt-leakage-guard"),trust_exploitation_guard_2=require("./guards/trust-exploitation-guard"),autonomy_escalation_guard_2=require("./guards/autonomy-escalation-guard"),state_persistence_guard_2=require("./guards/state-persistence-guard"),tool_result_guard_2=require("./guards/tool-result-guard"),context_budget_guard_2=require("./guards/context-budget-guard"),output_schema_guard_2=require("./guards/output-schema-guard");class TrustGuard{constructor(e={}){if(this.maxInputLength=e.maxInputLength??1e5,this.failMode=e.failMode??"closed",e.sanitizer?.enabled!==!1&&(this.sanitizer=new input_sanitizer_2.InputSanitizer({threshold:e.sanitizer?.threshold,customPatterns:e.sanitizer?.customPatterns,detectPAP:e.sanitizer?.detectPAP,papThreshold:e.sanitizer?.papThreshold,minPersuasionTechniques:e.sanitizer?.minPersuasionTechniques,blockCompoundPersuasion:e.sanitizer?.blockCompoundPersuasion})),e.registry?.enabled!==!1&&e.registry?.tools&&(this.registry=new tool_registry_2.ToolRegistry({tools:e.registry.tools})),e.policy?.enabled!==!1&&(this.policy=new policy_gate_2.PolicyGate({roleHierarchy:e.policy?.roleHierarchy})),e.tenant?.enabled!==!1){const s=e.tenant?.resourceOwnership?new Map(Object.entries(e.tenant.resourceOwnership).map(([o,a])=>[o,{resource_id:o,tenant_id:a.tenant_id}])):void 0;this.tenant=new tenant_boundary_2.TenantBoundary({resourceOwnership:s})}e.schema?.enabled!==!1&&(this.schema=new schema_validator_2.SchemaValidator({strictTypes:e.schema?.strictTypes})),e.execution?.enabled!==!1&&(this.execution=new execution_monitor_2.ExecutionMonitor({maxRequestsPerMinute:e.execution?.maxRequestsPerMinute,maxRequestsPerHour:e.execution?.maxRequestsPerHour,operationCosts:e.execution?.operationCosts,maxCostPerMinute:e.execution?.maxCostPerMinute,maxCostPerHour:e.execution?.maxCostPerHour})),e.output?.enabled!==!1&&(this.output=new output_filter_2.OutputFilter({detectPII:e.output?.detectPII,detectSecrets:e.output?.detectSecrets,roleFilters:e.output?.roleFilters})),e.conversation?.enabled!==!1&&(this.conversation=new conversation_guard_2.ConversationGuard({maxConversationLength:e.conversation?.maxConversationLength,escalationThreshold:e.conversation?.escalationThreshold})),e.chain?.enabled!==!1&&(this.chain=new tool_chain_validator_2.ToolChainValidator({maxToolsPerRequest:e.chain?.maxToolsPerRequest,maxSensitiveToolsPerSession:e.chain?.maxSensitiveToolsPerSession,sensitiveTools:e.chain?.sensitiveTools})),e.encoding?.enabled!==!1&&(this.encoding=new encoding_detector_2.EncodingDetector({maxDecodingDepth:e.encoding?.maxDecodingDepth,maxEncodedRatio:e.encoding?.maxEncodedRatio})),e.multiModal?.enabled&&(this.multiModal=new multimodal_guard_2.MultiModalGuard({scanMetadata:e.multiModal.scanMetadata,detectBase64Payloads:e.multiModal.detectBase64Payloads,allowedMimeTypes:e.multiModal.allowedMimeTypes})),e.memory?.enabled&&(this.memoryGuard=new memory_guard_2.MemoryGuard({enableIntegrityCheck:e.memory.enableIntegrityCheck,detectInjections:e.memory.detectInjections,maxMemoryItems:e.memory.maxMemoryItems,signingKey:e.memory.signingKey,autoQuarantine:e.memory.autoQuarantine,riskThreshold:e.memory.riskThreshold})),e.rag?.enabled&&(this.ragGuard=new rag_guard_2.RAGGuard({detectInjections:e.rag.detectInjections,verifySource:e.rag.verifySource,trustedSources:e.rag.trustedSources,blockedSources:e.rag.blockedSources,maxDocumentSize:e.rag.maxDocumentSize,minTrustScore:e.rag.minTrustScore,detectEmbeddingAttacks:e.rag.detectEmbeddingAttacks})),e.codeExecution?.enabled&&(this.codeExecution=new code_execution_guard_2.CodeExecutionGuard({allowedLanguages:e.codeExecution.allowedLanguages,maxCodeLength:e.codeExecution.maxCodeLength,maxExecutionTime:e.codeExecution.maxExecutionTime,allowNetwork:e.codeExecution.allowNetwork,allowFileSystem:e.codeExecution.allowFileSystem,allowShell:e.codeExecution.allowShell,riskThreshold:e.codeExecution.riskThreshold})),e.agentCommunication?.enabled&&(this.agentCommunication=new agent_communication_guard_2.AgentCommunicationGuard({allowedAgents:e.agentCommunication.allowedAgents,requireSignatures:e.agentCommunication.requireSignatures,strictMode:e.agentCommunication.strictMode,maxMessageAge:e.agentCommunication.maxMessageAge})),e.circuitBreaker?.enabled&&(this.circuitBreaker=new circuit_breaker_2.CircuitBreaker({failureThreshold:e.circuitBreaker.failureThreshold,minimumRequests:e.circuitBreaker.minimumRequests,windowSize:e.circuitBreaker.windowSize,recoveryTimeout:e.circuitBreaker.recoveryTimeout,successThreshold:e.circuitBreaker.successThreshold})),e.driftDetector?.enabled&&(this.driftDetector=new drift_detector_2.DriftDetector({minimumSamples:e.driftDetector.minimumSamples,anomalyThreshold:e.driftDetector.anomalyThreshold,alertThreshold:e.driftDetector.alertThreshold,checkGoalAlignment:e.driftDetector.checkGoalAlignment})),e.mcpSecurity?.enabled&&(this.mcpSecurity=new mcp_security_guard_2.MCPSecurityGuard({detectToolShadowing:e.mcpSecurity.detectToolShadowing,toolBlocklist:e.mcpSecurity.toolBlocklist,strictMode:e.mcpSecurity.strictMode,minServerReputation:e.mcpSecurity.minServerReputation})),e.promptLeakage?.enabled&&(this.promptLeakage=new prompt_leakage_guard_2.PromptLeakageGuard({detectLeetspeak:e.promptLeakage.detectLeetspeak,detectROT13:e.promptLeakage.detectROT13,detectBase64:e.promptLeakage.detectBase64,detectIndirectExtraction:e.promptLeakage.detectIndirectExtraction,monitorOutput:e.promptLeakage.monitorOutput,systemPromptKeywords:e.promptLeakage.systemPromptKeywords,riskThreshold:e.promptLeakage.riskThreshold})),e.trustExploitation?.enabled&&(this.trustExploitation=new trust_exploitation_guard_2.TrustExploitationGuard({humanApprovalRequired:e.trustExploitation.humanApprovalRequired,maxAutonomousActions:e.trustExploitation.maxAutonomousActions,monitorGoalConsistency:e.trustExploitation.monitorGoalConsistency,detectPermissionEscalation:e.trustExploitation.detectPermissionEscalation,sensitiveActions:e.trustExploitation.sensitiveActions})),e.autonomyEscalation?.enabled&&(this.autonomyEscalation=new autonomy_escalation_guard_2.AutonomyEscalationGuard({maxAutonomyLevel:e.autonomyEscalation.maxAutonomyLevel,baseAutonomyLevel:e.autonomyEscalation.baseAutonomyLevel,detectSelfModification:e.autonomyEscalation.detectSelfModification,maxSubAgents:e.autonomyEscalation.maxSubAgents,enforceHITL:e.autonomyEscalation.enforceHITL,alwaysRequireHuman:e.autonomyEscalation.alwaysRequireHuman})),e.statePersistence?.enabled&&(this.statePersistence=new state_persistence_guard_2.StatePersistenceGuard({enableIntegrityCheck:e.statePersistence.enableIntegrityCheck,requireEncryption:e.statePersistence.requireEncryption,maxStateSize:e.statePersistence.maxStateSize,maxStateAge:e.statePersistence.maxStateAge,enforceSessionIsolation:e.statePersistence.enforceSessionIsolation,sensitiveKeys:e.statePersistence.sensitiveKeys,detectTampering:e.statePersistence.detectTampering})),e.toolResult?.enabled&&(this.toolResultGuard=new tool_result_guard_2.ToolResultGuard(e.toolResult)),e.contextBudget?.enabled&&(this.contextBudget=new context_budget_guard_2.ContextBudgetGuard(e.contextBudget)),e.outputSchema?.enabled&&(this.outputSchema=new output_schema_guard_2.OutputSchemaGuard(e.outputSchema)),e.classifier&&(this.classifier=e.classifier),this.logger=e.logger||((s,o)=>{o==="error"?console.error(s):o==="warn"?console.warn(s):console.log(s)})}check(e,s,o,a={}){const r=`req-${crypto_1.default.randomUUID()}`,i=[];this.logger(`[TrustGuard:${r}] Checking: ${e}`,"info");try{return this.runChecks(e,s,o,a,r)}catch(n){const l=n instanceof Error?n.message:String(n);return this.logger(`[TrustGuard:${r}] Guard error: ${l}`,"error"),this.failMode==="open"?{allowed:!0,all_violations:["GUARD_ERROR"],request_id:r}:{allowed:!1,block_reason:`Internal guard error: ${l}`,all_violations:["GUARD_ERROR"],request_id:r}}}runChecks(e,s,o,a,r){const i=[];if(a.userInput&&a.userInput.length>this.maxInputLength)return this.logger(`[TrustGuard:${r}] BLOCKED: Input too long (${a.userInput.length} > ${this.maxInputLength})`,"warn"),{allowed:!1,block_layer:"L1",block_reason:`Input length ${a.userInput.length} exceeds maximum ${this.maxInputLength}`,all_violations:["INPUT_TOO_LONG"],request_id:r};if(this.encoding&&a.userInput){const t=this.encoding.detect(a.userInput,r);if(!t.allowed)return this.logger(`[TrustGuard:${r}] BLOCKED by Encoding Detector`,"warn"),{allowed:!1,block_layer:"ENCODING",block_reason:t.reason,all_violations:t.violations,encoding:t,request_id:r};i.push(...t.violations)}if(this.sanitizer&&a.userInput){const t=this.sanitizer.sanitize(a.userInput,r);if(!t.allowed)return this.logger(`[TrustGuard:${r}] BLOCKED by L1`,"warn"),{allowed:!1,block_layer:"L1",block_reason:t.reason,all_violations:t.violations,sanitizer:t,request_id:r};i.push(...t.violations)}if(this.promptLeakage&&a.userInput){const t=this.promptLeakage.check(a.userInput,r);if(!t.allowed)return this.logger(`[TrustGuard:${r}] BLOCKED by Prompt Leakage Guard`,"warn"),{allowed:!1,block_layer:"PROMPT_LEAKAGE",block_reason:t.reason,all_violations:[...i,...t.violations],request_id:r};i.push(...t.violations)}if(this.memoryGuard&&a.userInput&&o?.session_id){const t=this.memoryGuard.validateContextInjection(a.userInput,o.session_id,r);if(!t.allowed)return this.logger(`[TrustGuard:${r}] BLOCKED by Memory Guard`,"warn"),{allowed:!1,block_layer:"MEMORY",block_reason:t.reason,all_violations:[...i,...t.violations],request_id:r};i.push(...t.violations)}if(this.conversation&&a.userInput&&o?.session_id){const t=this.conversation.check(o.session_id,a.userInput,[e],a.claimedRole,r);if(!t.allowed)return this.logger(`[TrustGuard:${r}] BLOCKED by Conversation Guard`,"warn"),{allowed:!1,block_layer:"CONV",block_reason:t.reason,all_violations:[...i,...t.violations],conversation:t,request_id:r};i.push(...t.violations)}let n;if(this.registry){const t=this.registry.check(e,o?.role||"",r);if(!t.allowed)return this.logger(`[TrustGuard:${r}] BLOCKED by L2`,"warn"),{allowed:!1,block_layer:"L2",block_reason:t.reason,all_violations:[...i,...t.violations],registry:t,request_id:r};n=t.tool,i.push(...t.violations)}if(this.chain&&o?.session_id){const t=a.allToolsInRequest?this.chain.validateBatch(o.session_id,a.allToolsInRequest,r):this.chain.validate(o.session_id,e,void 0,r);if(!t.allowed)return this.logger(`[TrustGuard:${r}] BLOCKED by Tool Chain Validator`,"warn"),{allowed:!1,block_layer:"CHAIN",block_reason:t.reason,all_violations:[...i,...t.violations],chain:t,request_id:r};i.push(...t.violations)}if(this.policy&&n){const t=this.policy.check(n,s,o,a.claimedRole,r);if(!t.allowed)return this.logger(`[TrustGuard:${r}] BLOCKED by L3`,"warn"),{allowed:!1,block_layer:"L3",block_reason:t.reason,all_violations:[...i,...t.violations],policy:t,request_id:r};i.push(...t.violations)}else this.policy&&!n&&this.logger(`[TrustGuard:${r}] Policy gate skipped: no tool definition (registry disabled or tool not found)`,"warn");if(this.autonomyEscalation&&o?.session_id){const t=this.autonomyEscalation.validate(e,o.session_id,s,r);if(!t.allowed)return this.logger(`[TrustGuard:${r}] BLOCKED by Autonomy Escalation Guard`,"warn"),{allowed:!1,block_layer:"AUTONOMY",block_reason:t.reason,all_violations:[...i,...t.violations],request_id:r};i.push(...t.violations)}let l=s;if(this.tenant){const t=this.tenant.check(e,s,o,r);if(!t.allowed)return this.logger(`[TrustGuard:${r}] BLOCKED by L4`,"warn"),{allowed:!1,block_layer:"L4",block_reason:t.reason,all_violations:[...i,...t.violations],tenant:t,request_id:r};t.enforced_params&&(l=t.enforced_params),i.push(...t.violations)}if(this.schema&&n){const t=this.schema.validate(n,l,r);if(!t.allowed)return this.logger(`[TrustGuard:${r}] BLOCKED by L5`,"warn"),{allowed:!1,block_layer:"L5",block_reason:t.reason,all_violations:[...i,...t.violations],schema:t,request_id:r};i.push(...t.violations)}if(this.execution){const t=this.execution.check(e,o?.user_id,o?.session_id,r);if(!t.allowed)return this.logger(`[TrustGuard:${r}] BLOCKED by L6`,"warn"),{allowed:!1,block_layer:"L6",block_reason:t.reason,all_violations:[...i,...t.violations],execution:t,request_id:r};i.push(...t.violations)}if(this.circuitBreaker){const t=this.circuitBreaker.check(e,r);if(!t.allowed)return this.logger(`[TrustGuard:${r}] BLOCKED by Circuit Breaker`,"warn"),{allowed:!1,block_layer:"L6",block_reason:t.reason,all_violations:[...i,"CIRCUIT_OPEN"],request_id:r}}return this.logger(`[TrustGuard:${r}] All checks PASSED`,"info"),{allowed:!0,all_violations:i,request_id:r}}filterOutput(e,s,o){let a=e,r=!1,i=!1,n=!1,l=!0;const t=typeof e=="string"?e:"";if(t.length>this.maxInputLength&&this.logger(`[TrustGuard] Output too long (${t.length}), truncating for filter`,"warn"),this.output){const c=this.output.filter(e,s,o);a=c.filtered_response,r=c.pii_detected.length>0,i=c.secrets_detected.length>0,c.allowed||(l=!1)}if(this.promptLeakage){const c=typeof a=="string"?a:JSON.stringify(a),d=this.promptLeakage.checkOutput(c,o);d.leaked&&(l=!1,n=!0,d.sanitized_output&&(a=d.sanitized_output))}return{allowed:l,filtered:a,pii_detected:r,secrets_detected:i,prompt_leakage_detected:n}}completeOperation(e,s,o=!0){this.execution&&this.execution.completeOperation(e?.user_id,e?.session_id),this.circuitBreaker&&s&&(o?this.circuitBreaker.recordSuccess(s):this.circuitBreaker.recordFailure(s))}getToolsForRole(e){return this.registry?this.registry.getToolsForRole(e):[]}getGuards(){return{sanitizer:this.sanitizer,registry:this.registry,policy:this.policy,tenant:this.tenant,schema:this.schema,execution:this.execution,output:this.output,conversation:this.conversation,chain:this.chain,encoding:this.encoding,multiModal:this.multiModal,memory:this.memoryGuard,rag:this.ragGuard,codeExecution:this.codeExecution,agentCommunication:this.agentCommunication,circuitBreaker:this.circuitBreaker,driftDetector:this.driftDetector,mcpSecurity:this.mcpSecurity,promptLeakage:this.promptLeakage,trustExploitation:this.trustExploitation,autonomyEscalation:this.autonomyEscalation,statePersistence:this.statePersistence,toolResult:this.toolResultGuard,contextBudget:this.contextBudget,outputSchema:this.outputSchema}}resetSession(e){this.conversation?.resetSession(e),this.chain?.resetSession(e),this.execution?.reset(void 0,e),this.memoryGuard?.clearSession(e),this.trustExploitation?.resetSession(e),this.autonomyEscalation?.resetSession(e),this.statePersistence?.resetSession(e),this.contextBudget?.resetSession(e)}validateToolResult(e,s,o){if(!this.toolResultGuard)return{allowed:!0,violations:[]};const a=this.toolResultGuard.validateResult(e,s,o);return{allowed:a.allowed,violations:a.violations}}validateOutput(e,s,o){if(!this.outputSchema)return{allowed:!0,violations:[],threats:[]};const a=this.outputSchema.validate(e,s,o);return{allowed:a.allowed,violations:a.violations,threats:a.threats}}async checkAsync(e,s,o,a={}){const r=this.check(e,s,o,a);if(!this.classifier||!r.allowed||!a.userInput)return r;try{const i=await this.classifier(a.userInput,{type:"user_input",sessionId:o?.session_id});if(!i.safe)return{...r,allowed:!1,block_layer:"L1",block_reason:`Classifier detected threat: ${i.threats.map(n=>n.category).join(", ")}`,all_violations:[...r.all_violations,...i.threats.map(n=>`CLASSIFIER_${n.category.toUpperCase()}`)]}}catch(i){const n=i instanceof Error?i.message:String(i);this.logger(`[TrustGuard] Classifier error: ${n}`,"error")}return r}}exports.TrustGuard=TrustGuard,__exportStar(require("./integrations/index.js"),exports),exports.default=TrustGuard;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "llm-trust-guard",
3
- "version": "4.5.0",
3
+ "version": "4.6.0",
4
4
  "description": "Comprehensive security guards for LLM-powered and agentic AI applications - 22 protection layers covering OWASP Top 10 for LLMs 2025, Agentic Applications 2026, and MCP Security. All guards now accessible via unified TrustGuard facade. Features prompt injection (PAP/persuasion), multi-modal attacks, RAG poisoning with embedding attack detection, memory persistence attacks, code execution sandboxing, multi-agent security, MCP tool shadowing prevention, system prompt leakage protection, human-agent trust exploitation (ASI09), autonomy escalation (ASI10), state persistence (ASI08), tool chain validation v2 (ASI07/ASI04), circuit breaker, drift detection, and more",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",