llm-trust-guard 4.13.3 → 4.13.5

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/README.md CHANGED
@@ -5,6 +5,8 @@
5
5
 
6
6
  **31 security guards for LLM-powered and agentic AI applications.** Zero dependencies. <5ms latency. Covers OWASP Top 10 for LLMs 2025, OWASP Agentic AI 2026, and MCP Security.
7
7
 
8
+ Also available as a [Python package on PyPI](https://pypi.org/project/llm-trust-guard/) (`pip install llm-trust-guard`).
9
+
8
10
  ## What This Package Does (And What It Doesn't)
9
11
 
10
12
  > **"The LLM proposes. The orchestrator disposes."**
@@ -246,6 +248,7 @@ MIT
246
248
 
247
249
  ## Links
248
250
 
251
+ - [Python package (PyPI)](https://pypi.org/project/llm-trust-guard/) — same 31 guards, zero dependencies
249
252
  - [OWASP Top 10 for LLMs 2025](https://genai.owasp.org/resource/owasp-top-10-for-llm-applications-2025/)
250
253
  - [OWASP Top 10 for Agentic Applications 2026](https://genai.owasp.org/resource/owasp-top-10-for-agentic-applications-for-2026/)
251
254
  - [MITRE ATLAS](https://atlas.mitre.org/)
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.EncodingDetector=void 0;class EncodingDetector{constructor(s={}){this.defaultThreatPatterns=[{name:"sql_injection",pattern:/(?:union\s+(?:all\s+)?select|drop\s+(?:table|database)|insert\s+into|delete\s+from|update\s+.*set|exec\s*\(|execute\s*\(|truncate\s+table|alter\s+table|create\s+table|;\s*select\s|or\s+1\s*=\s*1|'\s*or\s*'|--\s*$|\/\*.*\*\/)/gi,severity:"critical"},{name:"command_injection",pattern:/(?:;\s*(?:cat|ls|rm|wget|curl|bash|sh|python|perl|ruby|nc|netcat|nmap|chmod|chown|kill|pkill)|`[^`]+`|\$\([^)]+\)|\|\s*(?:sh|bash)|&&\s*(?:rm|cat|wget)|>\s*\/(?:etc|tmp|var))/gi,severity:"critical"},{name:"path_traversal",pattern:/(?:\.\.\/|\.\.\\|%2e%2e%2f|%2e%2e\/|\.\.%2f|%2e%2e%5c|\.\.%5c|%252e%252e|%c0%ae|%c1%9c|\.\.%c0%af|\.\.%c1%9c)/gi,severity:"high"},{name:"xss",pattern:/(?:<script|javascript:|on\w+\s*=|<iframe|<object|<embed|<svg\s+onload|<img\s+onerror|<body\s+onload|expression\s*\(|vbscript:|data:text\/html|<style>.*expression)/gi,severity:"high"},{name:"prompt_injection",pattern:/(?:ignore\s+(?:all\s+)?(?:previous|prior|above|the)?\s*(?:instructions|rules|guidelines|directives)?|disregard\s+(?:above|all|everything|the)|you\s+are\s+now|new\s+instructions|forget\s+(?:everything|all)|system\s*:\s*you|act\s+as\s+(?:a|an|if)|pretend\s+(?:you|to\s+be)|roleplay\s+as|jailbreak|DAN\s+mode|developer\s+mode|bypass\s+(?:safety|security|restrictions|filters)|reveal\s+.*(?:system|prompt|instructions|secret|password)|show\s+.*(?:system|prompt|instructions)|output\s+.*(?:system|prompt|instructions))/gi,severity:"high"},{name:"system_command",pattern:/(?:\/bin\/|\/etc\/passwd|\/etc\/shadow|cmd\.exe|powershell|\.exe|\.bat|\.cmd|\.ps1|\.sh\s|eval\s*\(|system\s*\(|exec\s*\(|popen|subprocess|os\.system)/gi,severity:"critical"},{name:"data_exfiltration",pattern:/(?:curl\s+.*-d|wget\s+.*--post|fetch\s*\(|XMLHttpRequest|sendBeacon|\.innerHTML\s*=|document\.cookie|localStorage\.|sessionStorage\.)/gi,severity:"high"},{name:"ldap_injection",pattern:/(?:\)\s*\(\||\*\)\s*\(|\)\s*\(\&|%28%7c|%29%28)/gi,severity:"high"},{name:"xxe_injection",pattern:/(?:<!ENTITY|<!DOCTYPE.*SYSTEM|<!DOCTYPE.*PUBLIC|SYSTEM\s*"file:|SYSTEM\s*"http)/gi,severity:"critical"},{name:"template_injection",pattern:/(?:\{\{.*\}\}|\$\{.*\}|<%.*%>|<\?.*\?>|\[\[.*\]\])/gi,severity:"high"},{name:"role_escalation",pattern:/(?:admin\s*:\s*true|role\s*:\s*(?:admin|root|superuser)|isAdmin\s*=\s*true|permissions?\s*:\s*\[?\s*['"]\*['"])/gi,severity:"critical"}],this.config={detectBase64:s.detectBase64??!0,detectURLEncoding:s.detectURLEncoding??!0,detectUnicode:s.detectUnicode??!0,detectHex:s.detectHex??!0,detectHTMLEntities:s.detectHTMLEntities??!0,detectMixedEncoding:s.detectMixedEncoding??!0,detectROT13:s.detectROT13??!0,detectOctal:s.detectOctal??!0,detectBase32:s.detectBase32??!0,maxDecodingDepth:s.maxDecodingDepth??3,threatPatterns:s.threatPatterns??this.defaultThreatPatterns,maxEncodedRatio:s.maxEncodedRatio??.5},this.logger=s.logger||(()=>{})}detect(s,n=""){const t=[],c=[],a=[];let o=0;if(this.checkThreats(s,"original",a),this.config.detectBase64){const e=this.detectBase64(s);e.found&&(c.push({type:"base64",count:e.matches.length,locations:e.locations,decoded_sample:e.decoded?.substring(0,100)}),o+=3,t.push("BASE64_ENCODING_DETECTED"),e.decoded&&this.checkThreats(e.decoded,"decoded_base64",a))}if(this.config.detectURLEncoding){const e=this.detectURLEncoding(s);e.found&&(c.push({type:"url_encoding",count:e.count,locations:[],decoded_sample:e.decoded?.substring(0,100)}),o+=e.ratio>.3?4:2,e.ratio>this.config.maxEncodedRatio&&t.push("EXCESSIVE_URL_ENCODING"),e.decoded&&this.checkThreats(e.decoded,"decoded_url",a))}if(this.config.detectUnicode){const e=this.detectUnicode(s);e.found&&(c.push({type:"unicode",count:e.count,locations:e.types,decoded_sample:e.normalized?.substring(0,100)}),o+=3,t.push("UNICODE_OBFUSCATION_DETECTED"),e.normalized&&this.checkThreats(e.normalized,"decoded_unicode",a),e.normalizedSpaced&&e.normalizedSpaced!==e.normalized&&this.checkThreats(e.normalizedSpaced,"decoded_unicode",a))}if(this.config.detectHex){const e=this.detectHex(s);if(e.found&&(c.push({type:"hex",count:e.matches.length,locations:e.locations,decoded_sample:e.decoded?.substring(0,100)}),o+=2,t.push("HEX_ENCODING_DETECTED"),e.decoded)){this.checkThreats(e.decoded,"decoded_hex",a);const d=s.replace(/(?:0x|\\x)([0-9A-Fa-f]{2})/g,(g,f)=>String.fromCharCode(parseInt(f,16)));this.checkThreats(d,"decoded_hex",a)}}if(this.config.detectHTMLEntities){const e=this.detectHTMLEntities(s);if(e.found){c.push({type:"html_entities",count:e.count,locations:[],decoded_sample:e.decoded?.substring(0,100)}),o+=2;const d=e.count*5;s.length>10&&d/s.length>.5&&(o+=3,t.push("EXCESSIVE_HTML_ENTITY_ENCODING")),e.decoded&&this.checkThreats(e.decoded,"decoded_html",a)}}if(this.config.detectROT13){const e=this.detectROT13(s);e.found&&(c.push({type:"rot13",count:e.matches.length,locations:e.locations,decoded_sample:e.decoded?.substring(0,100)}),o+=3,t.push("ROT13_ENCODING_DETECTED"),e.decoded&&this.checkThreats(e.decoded,"decoded_rot13",a))}if(this.config.detectOctal){const e=this.detectOctal(s);e.found&&(c.push({type:"octal",count:e.matches.length,locations:e.locations,decoded_sample:e.decoded?.substring(0,100)}),o+=2,t.push("OCTAL_ENCODING_DETECTED"),e.decoded&&this.checkThreats(e.decoded,"decoded_octal",a))}if(this.config.detectBase32){const e=this.detectBase32(s);e.found&&(c.push({type:"base32",count:e.matches.length,locations:e.locations,decoded_sample:e.decoded?.substring(0,100)}),o+=3,t.push("BASE32_ENCODING_DETECTED"),e.decoded&&this.checkThreats(e.decoded,"decoded_base32",a))}this.config.detectMixedEncoding&&c.length>1&&(o+=c.length*2,t.push("MIXED_ENCODING_DETECTED"));for(const e of a)(e.severity==="critical"||e.severity==="high")&&t.push(`ENCODED_THREAT_${e.pattern_name.toUpperCase()}_IN_${e.in_layer.toUpperCase()}`);const u=c.length>0,i=a.some(e=>(e.severity==="critical"||e.severity==="high")&&e.in_layer!=="original"),r=u&&a.some(e=>e.severity==="critical"&&e.in_layer==="original"),l=!i&&!r;l||this.logger(`[EncodingDetector:${n}] BLOCKED: ${t.join(", ")}`,"info");let h=s;for(let e=0;e<this.config.maxDecodingDepth;e++){const d=this.fullyDecode(h);if(d===h)break;h=d}return{allowed:l,reason:l?void 0:`Encoding bypass attempt detected: ${t.join(", ")}`,violations:t,encoding_analysis:{encodings_detected:c,decoded_content:h!==s?h:void 0,threats_found:a,obfuscation_score:o}}}containsEncodedThreat(s){return this.detect(s).encoding_analysis.threats_found.some(t=>t.in_layer!=="original")}detectBase64(s){const n=/(?:[A-Za-z0-9+/]{4}){5,}(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?/g,t=[],c=[];let a,o;for(;(o=n.exec(s))!==null;)try{const u=o[0],i=Buffer.from(u,"base64").toString("utf-8");/^[\x20-\x7E\r\n\t]+$/.test(i)&&(t.push(u),c.push(`index:${o.index}`),a=a?a+" "+i:i)}catch{}return{found:t.length>0,matches:t,locations:c,decoded:a}}detectURLEncoding(s){const n=/%[0-9A-Fa-f]{2}/g,t=s.match(n)||[],c=t.length*3/s.length;let a;if(t.length>0)try{a=decodeURIComponent(s)}catch{a=s.replace(/%([0-9A-Fa-f]{2})/g,(o,u)=>{try{return String.fromCharCode(parseInt(u,16))}catch{return o}})}return{found:t.length>0,count:t.length,ratio:c,decoded:a}}detectUnicode(s){const n=[];let t=0;const c=/\\u[0-9A-Fa-f]{4}/g,a=s.match(c)||[];a.length>0&&(t+=a.length,n.push("unicode_escape_u"));const o=/\\u\{[0-9A-Fa-f]{1,6}\}/g,u=s.match(o)||[];u.length>0&&(t+=u.length,n.push("unicode_escape_es6"));const i=/\\U[0-9A-Fa-f]{8}/g,r=s.match(i)||[];r.length>0&&(t+=r.length,n.push("unicode_escape_U"));const l=/[\u0430-\u044F\u0410-\u042F\u0391-\u03C9\u2010-\u2015\uFF01-\uFF5E\u{1D400}-\u{1D7FF}]/gu,h=s.match(l)||[];h.length>0&&(t+=h.length,n.push("homoglyphs"));const e=/[\u200B\u200C\u200D\uFEFF\u00AD\u2060\u180E]/g,d=s.match(e)||[];d.length>0&&(t+=d.length,n.push("zero_width"));const g=/[\u202A\u202B\u202C\u202D\u202E\u2066\u2067\u2068\u2069]/g,f=s.match(g)||[];f.length>0&&(t+=f.length,n.push("bidi_controls"));const b=/[\u0131\u0130\u017F\u212A\u0261\u0251\u025B\u0254\u028C]/g,m=s.match(b)||[];m.length>0&&(t+=m.length,n.push("confusables"));const D=/[\u{E0000}-\u{E007F}]/gu,E=s.match(D)||[];E.length>0&&(t+=E.length,n.push("tag_characters"));let _,C;if(t>0){const y=s.normalize("NFKC").replace(/\\u([0-9A-Fa-f]{4})/g,(x,p)=>String.fromCharCode(parseInt(p,16))).replace(/\\u\{([0-9A-Fa-f]{1,6})\}/g,(x,p)=>String.fromCodePoint(parseInt(p,16))).replace(/\\U([0-9A-Fa-f]{8})/g,(x,p)=>String.fromCodePoint(parseInt(p,16))).replace(/[\u202A\u202B\u202C\u202D\u202E\u2066\u2067\u2068\u2069]/g,"").replace(/[\u{E0000}-\u{E007F}]/gu,"");_=y.replace(/[\u200B\u200C\u200D\uFEFF\u00AD\u2060\u180E]/g,"").replace(/\s{2,}/g," ").trim(),C=y.replace(/[\u200B\u200C\u200D\uFEFF\u00AD\u2060\u180E]/g," ").replace(/\s{2,}/g," ").trim()}return{found:t>0,count:t,types:n,normalized:_,normalizedSpaced:C}}detectHex(s){const n=[],t=[];let c="";const a=/(?:0x|\\x)([0-9A-Fa-f]{2})/g;let o;for(;(o=a.exec(s))!==null;)n.push(o[0]),t.push(`index:${o.index}`),c+=String.fromCharCode(parseInt(o[1],16));const u=/(?:^|[^0-9A-Fa-f])([0-9A-Fa-f]{8,})(?:[^0-9A-Fa-f]|$)/g;for(;(o=u.exec(s))!==null;){const r=o[1];if(r.length%2===0){let l="",h=!0;for(let e=0;e<r.length;e+=2){const d=parseInt(r.substr(e,2),16);if(d>=32&&d<=126)l+=String.fromCharCode(d);else{h=!1;break}}h&&l.length>=4&&(n.push(r),t.push(`index:${o.index}`),c+=l)}}const i=/(?:[0-9A-Fa-f]{2}\s+){3,}[0-9A-Fa-f]{2}/g;for(;(o=i.exec(s))!==null;){const r=o[0].split(/\s+/);let l="",h=!0;for(const e of r){const d=parseInt(e,16);if(d>=32&&d<=126)l+=String.fromCharCode(d);else{h=!1;break}}h&&l.length>=4&&(n.push(o[0]),t.push(`index:${o.index}`),c+=l)}return{found:n.length>0,matches:n,locations:t,decoded:c||void 0}}detectHTMLEntities(s){const n=/&(?:#\d+|#x[0-9A-Fa-f]+|\w+);/g,t=s.match(n)||[];let c;return t.length>0&&(c=s.replace(/&#(\d+);/g,(a,o)=>String.fromCharCode(parseInt(o,10))).replace(/&#x([0-9A-Fa-f]+);/g,(a,o)=>String.fromCharCode(parseInt(o,16))).replace(/&lt;/g,"<").replace(/&gt;/g,">").replace(/&amp;/g,"&").replace(/&quot;/g,'"').replace(/&apos;/g,"'")),{found:t.length>0,count:t.length,decoded:c}}detectROT13(s){const n=r=>r.replace(/[a-zA-Z]/g,l=>{const h=l<="Z"?65:97;return String.fromCharCode((l.charCodeAt(0)-h+13)%26+h)}),t=[],c=[];let a;const o=["ignore","instructions","system","admin","password","secret","delete","drop","select","union","script","eval","exec","shell","command","root","sudo","bypass","hack","inject","reveal","prompt","override","jailbreak","unrestricted"],u=/\b[a-zA-Z]{5,}\b/g;let i;for(;(i=u.exec(s))!==null;){const r=i[0],l=n(r).toLowerCase();o.includes(l)&&(t.push(r),c.push(`index:${i.index}`),a=a?a+" "+l:l)}if(t.length>0||/^[a-zA-Z\s]+$/.test(s.trim())){const r=n(s);a||(a=r)}return{found:t.length>0,matches:t,locations:c,decoded:a}}detectOctal(s){const n=/(?:\\([0-7]{3})|(?:^|\s)(0[0-7]{2,}))/g,t=[],c=[];let a="",o;for(;(o=n.exec(s))!==null;){const u=o[1]||o[2];if(t.push(o[0]),c.push(`index:${o.index}`),o[1])a+=String.fromCharCode(parseInt(o[1],8));else if(o[2]){const i=parseInt(o[2],8);i>=32&&i<=126&&(a+=String.fromCharCode(i))}}return{found:t.length>0,matches:t,locations:c,decoded:a||void 0}}detectBase32(s){const n=/(?:[A-Z2-7]{8}){2,}(?:={0,6})?/g,t=[],c=[];let a;const o=i=>{const r="ABCDEFGHIJKLMNOPQRSTUVWXYZ234567",l=i.replace(/=/g,"").toUpperCase();let h="";for(const d of l){const g=r.indexOf(d);if(g===-1)return null;h+=g.toString(2).padStart(5,"0")}let e="";for(let d=0;d+8<=h.length;d+=8){const g=parseInt(h.substr(d,8),2);if(g>=32&&g<=126)e+=String.fromCharCode(g);else return null}return e.length>0?e:null};let u;for(;(u=n.exec(s))!==null;)try{const i=u[0],r=o(i);r&&r.length>=4&&(t.push(i),c.push(`index:${u.index}`),a=a?a+" "+r:r)}catch{}return{found:t.length>0,matches:t,locations:c,decoded:a}}checkThreats(s,n,t){for(const c of this.config.threatPatterns)c.pattern.lastIndex=0,c.pattern.test(s)&&t.push({pattern_name:c.name,severity:c.severity,in_layer:n})}fullyDecode(s){let n=s;try{n=decodeURIComponent(n)}catch{n=n.replace(/%([0-9A-Fa-f]{2})/g,(t,c)=>{try{return String.fromCharCode(parseInt(c,16))}catch{return t}})}return n=n.replace(/\\u([0-9A-Fa-f]{4})/g,(t,c)=>String.fromCharCode(parseInt(c,16))),n=n.replace(/\\u\{([0-9A-Fa-f]{1,6})\}/g,(t,c)=>String.fromCodePoint(parseInt(c,16))),n=n.replace(/\\U([0-9A-Fa-f]{8})/g,(t,c)=>String.fromCodePoint(parseInt(c,16))),n=n.replace(/(?:0x|\\x)([0-9A-Fa-f]{2})/g,(t,c)=>String.fromCharCode(parseInt(c,16))),n=n.replace(/\\([0-7]{3})/g,(t,c)=>String.fromCharCode(parseInt(c,8))),n=n.replace(/&#(\d+);/g,(t,c)=>String.fromCharCode(parseInt(c,10))).replace(/&#x([0-9A-Fa-f]+);/g,(t,c)=>String.fromCharCode(parseInt(c,16))).replace(/&lt;/g,"<").replace(/&gt;/g,">").replace(/&amp;/g,"&").replace(/&quot;/g,'"').replace(/&apos;/g,"'").replace(/&nbsp;/g," "),n=n.replace(/[\u200B\u200C\u200D\uFEFF\u00AD\u2060\u180E]/g,""),n=n.replace(/[\u202A\u202B\u202C\u202D\u202E\u2066\u2067\u2068\u2069]/g,""),n}}exports.EncodingDetector=EncodingDetector;
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.EncodingDetector=void 0;class EncodingDetector{constructor(s={}){this.defaultThreatPatterns=[{name:"sql_injection",pattern:/(?:union\s+(?:all\s+)?select|drop\s+(?:table|database)|insert\s+into|delete\s+from|update\s+.*set|exec\s*\(|execute\s*\(|truncate\s+table|alter\s+table|create\s+table|;\s*select\s|or\s+1\s*=\s*1|'\s*or\s*'|--\s*$|\/\*.*\*\/)/gi,severity:"critical"},{name:"command_injection",pattern:/(?:;\s*(?:cat|ls|rm|wget|curl|bash|sh|python|perl|ruby|nc|netcat|nmap|chmod|chown|kill|pkill)|`[^`]+`|\$\([^)]+\)|\|\s*(?:sh|bash)|&&\s*(?:rm|cat|wget)|>\s*\/(?:etc|tmp|var))/gi,severity:"critical"},{name:"path_traversal",pattern:/(?:\.\.\/|\.\.\\|%2e%2e%2f|%2e%2e\/|\.\.%2f|%2e%2e%5c|\.\.%5c|%252e%252e|%c0%ae|%c1%9c|\.\.%c0%af|\.\.%c1%9c)/gi,severity:"high"},{name:"xss",pattern:/(?:<script|javascript:|on\w+\s*=|<iframe|<object|<embed|<svg\s+onload|<img\s+onerror|<body\s+onload|expression\s*\(|vbscript:|data:text\/html|<style>.*expression)/gi,severity:"high"},{name:"prompt_injection",pattern:/(?:ignore\s+(?:all\s+)?(?:previous|prior|above|the)?\s*(?:instructions|rules|guidelines|directives)?|disregard\s+(?:above|all|everything|the)|you\s+are\s+now|new\s+instructions|forget\s+(?:everything|all)|system\s*:\s*you|act\s+as\s+(?:a|an|if)|pretend\s+(?:you|to\s+be)|roleplay\s+as|jailbreak|DAN\s+mode|developer\s+mode|bypass\s+(?:safety|security|restrictions|filters)|reveal\s+.*(?:system|prompt|instructions|secret|password)|show\s+.*(?:system|prompt|instructions)|output\s+.*(?:system|prompt|instructions)|system\s+prompt|your\s+(?:system|initial)\s+(?:prompt|instructions))/gi,severity:"high"},{name:"system_command",pattern:/(?:\/bin\/|\/etc\/passwd|\/etc\/shadow|cmd\.exe|powershell|\.exe|\.bat|\.cmd|\.ps1|\.sh\s|eval\s*\(|system\s*\(|exec\s*\(|popen|subprocess|os\.system)/gi,severity:"critical"},{name:"data_exfiltration",pattern:/(?:curl\s+.*-d|wget\s+.*--post|fetch\s*\(|XMLHttpRequest|sendBeacon|\.innerHTML\s*=|document\.cookie|localStorage\.|sessionStorage\.)/gi,severity:"high"},{name:"ldap_injection",pattern:/(?:\)\s*\(\||\*\)\s*\(|\)\s*\(\&|%28%7c|%29%28)/gi,severity:"high"},{name:"xxe_injection",pattern:/(?:<!ENTITY|<!DOCTYPE.*SYSTEM|<!DOCTYPE.*PUBLIC|SYSTEM\s*"file:|SYSTEM\s*"http)/gi,severity:"critical"},{name:"template_injection",pattern:/(?:\{\{.*\}\}|\$\{.*\}|<%.*%>|<\?.*\?>|\[\[.*\]\])/gi,severity:"high"},{name:"role_escalation",pattern:/(?:admin\s*:\s*true|role\s*:\s*(?:admin|root|superuser)|isAdmin\s*=\s*true|permissions?\s*:\s*\[?\s*['"]\*['"])/gi,severity:"critical"}],this.config={detectBase64:s.detectBase64??!0,detectURLEncoding:s.detectURLEncoding??!0,detectUnicode:s.detectUnicode??!0,detectHex:s.detectHex??!0,detectHTMLEntities:s.detectHTMLEntities??!0,detectMixedEncoding:s.detectMixedEncoding??!0,detectROT13:s.detectROT13??!0,detectOctal:s.detectOctal??!0,detectBase32:s.detectBase32??!0,maxDecodingDepth:s.maxDecodingDepth??3,threatPatterns:s.threatPatterns??this.defaultThreatPatterns,maxEncodedRatio:s.maxEncodedRatio??.5},this.logger=s.logger||(()=>{})}detect(s,o=""){const t=[],c=[],a=[];let n=0;if(this.checkThreats(s,"original",a),this.config.detectBase64){const e=this.detectBase64(s);e.found&&(c.push({type:"base64",count:e.matches.length,locations:e.locations,decoded_sample:e.decoded?.substring(0,100)}),n+=3,t.push("BASE64_ENCODING_DETECTED"),e.decoded&&this.checkThreats(e.decoded,"decoded_base64",a))}if(this.config.detectURLEncoding){const e=this.detectURLEncoding(s);e.found&&(c.push({type:"url_encoding",count:e.count,locations:[],decoded_sample:e.decoded?.substring(0,100)}),n+=e.ratio>.3?4:2,e.ratio>this.config.maxEncodedRatio&&t.push("EXCESSIVE_URL_ENCODING"),e.decoded&&this.checkThreats(e.decoded,"decoded_url",a))}if(this.config.detectUnicode){const e=this.detectUnicode(s);e.found&&(c.push({type:"unicode",count:e.count,locations:e.types,decoded_sample:e.normalized?.substring(0,100)}),n+=3,t.push("UNICODE_OBFUSCATION_DETECTED"),e.normalized&&this.checkThreats(e.normalized,"decoded_unicode",a),e.normalizedSpaced&&e.normalizedSpaced!==e.normalized&&this.checkThreats(e.normalizedSpaced,"decoded_unicode",a))}if(this.config.detectHex){const e=this.detectHex(s);if(e.found&&(c.push({type:"hex",count:e.matches.length,locations:e.locations,decoded_sample:e.decoded?.substring(0,100)}),n+=2,t.push("HEX_ENCODING_DETECTED"),e.decoded)){this.checkThreats(e.decoded,"decoded_hex",a);const d=s.replace(/(?:0x|\\x)([0-9A-Fa-f]{2})/g,(g,f)=>String.fromCharCode(parseInt(f,16)));this.checkThreats(d,"decoded_hex",a)}}if(this.config.detectHTMLEntities){const e=this.detectHTMLEntities(s);if(e.found){c.push({type:"html_entities",count:e.count,locations:[],decoded_sample:e.decoded?.substring(0,100)}),n+=2;const d=e.count*5;s.length>10&&d/s.length>.5&&(n+=3,t.push("EXCESSIVE_HTML_ENTITY_ENCODING")),e.decoded&&this.checkThreats(e.decoded,"decoded_html",a)}}if(this.config.detectROT13){const e=this.detectROT13(s);e.found&&(c.push({type:"rot13",count:e.matches.length,locations:e.locations,decoded_sample:e.decoded?.substring(0,100)}),n+=3,t.push("ROT13_ENCODING_DETECTED"),e.decoded&&this.checkThreats(e.decoded,"decoded_rot13",a))}if(this.config.detectOctal){const e=this.detectOctal(s);e.found&&(c.push({type:"octal",count:e.matches.length,locations:e.locations,decoded_sample:e.decoded?.substring(0,100)}),n+=2,t.push("OCTAL_ENCODING_DETECTED"),e.decoded&&this.checkThreats(e.decoded,"decoded_octal",a))}if(this.config.detectBase32){const e=this.detectBase32(s);e.found&&(c.push({type:"base32",count:e.matches.length,locations:e.locations,decoded_sample:e.decoded?.substring(0,100)}),n+=3,t.push("BASE32_ENCODING_DETECTED"),e.decoded&&this.checkThreats(e.decoded,"decoded_base32",a))}this.config.detectMixedEncoding&&c.length>1&&(n+=c.length*2,t.push("MIXED_ENCODING_DETECTED"));for(const e of a)(e.severity==="critical"||e.severity==="high")&&t.push(`ENCODED_THREAT_${e.pattern_name.toUpperCase()}_IN_${e.in_layer.toUpperCase()}`);const u=c.length>0,i=a.some(e=>(e.severity==="critical"||e.severity==="high")&&e.in_layer!=="original"),l=u&&a.some(e=>e.severity==="critical"&&e.in_layer==="original"),h=!i&&!l;h||this.logger(`[EncodingDetector:${o}] BLOCKED: ${t.join(", ")}`,"info");let r=s;for(let e=0;e<this.config.maxDecodingDepth;e++){const d=this.fullyDecode(r);if(d===r)break;r=d}return{allowed:h,reason:h?void 0:`Encoding bypass attempt detected: ${t.join(", ")}`,violations:t,encoding_analysis:{encodings_detected:c,decoded_content:r!==s?r:void 0,threats_found:a,obfuscation_score:n}}}containsEncodedThreat(s){return this.detect(s).encoding_analysis.threats_found.some(t=>t.in_layer!=="original")}detectBase64(s){const o=/(?:[A-Za-z0-9+/]{4}){5,}(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?/g,t=[],c=[];let a,n;for(;(n=o.exec(s))!==null;)try{const u=n[0],i=Buffer.from(u,"base64").toString("utf-8");/^[\x20-\x7E\r\n\t]+$/.test(i)&&(t.push(u),c.push(`index:${n.index}`),a=a?a+" "+i:i)}catch{}return{found:t.length>0,matches:t,locations:c,decoded:a}}detectURLEncoding(s){const o=/%[0-9A-Fa-f]{2}/g,t=s.match(o)||[],c=t.length*3/s.length;let a;if(t.length>0)try{a=decodeURIComponent(s)}catch{a=s.replace(/%([0-9A-Fa-f]{2})/g,(n,u)=>{try{return String.fromCharCode(parseInt(u,16))}catch{return n}})}return{found:t.length>0,count:t.length,ratio:c,decoded:a}}detectUnicode(s){const o=[];let t=0;const c=/\\u[0-9A-Fa-f]{4}/g,a=s.match(c)||[];a.length>0&&(t+=a.length,o.push("unicode_escape_u"));const n=/\\u\{[0-9A-Fa-f]{1,6}\}/g,u=s.match(n)||[];u.length>0&&(t+=u.length,o.push("unicode_escape_es6"));const i=/\\U[0-9A-Fa-f]{8}/g,l=s.match(i)||[];l.length>0&&(t+=l.length,o.push("unicode_escape_U"));const h=/[\u0430-\u044F\u0410-\u042F\u0391-\u03C9\u2010-\u2015\uFF01-\uFF5E\u{1D400}-\u{1D7FF}]/gu,r=s.match(h)||[];r.length>0&&(t+=r.length,o.push("homoglyphs"));const e=/[\u200B\u200C\u200D\uFEFF\u00AD\u2060\u180E]/g,d=s.match(e)||[];d.length>0&&(t+=d.length,o.push("zero_width"));const g=/[\u202A\u202B\u202C\u202D\u202E\u2066\u2067\u2068\u2069]/g,f=s.match(g)||[];f.length>0&&(t+=f.length,o.push("bidi_controls"));const D=/[\u0131\u0130\u017F\u212A\u0261\u0251\u025B\u0254\u028C]/g,C=s.match(D)||[];C.length>0&&(t+=C.length,o.push("confusables"));const T=/[\u{E0000}-\u{E007F}]/gu,_=s.match(T)||[];_.length>0&&(t+=_.length,o.push("tag_characters"));let y,x;if(t>0){const A={\u0430:"a",\u0410:"A",\u0435:"e",\u0415:"E",\u043E:"o",\u041E:"O",\u0440:"p",\u0420:"P",\u0441:"c",\u0421:"C",\u0443:"y",\u0423:"Y",\u0456:"i",\u0406:"I",\u0445:"x",\u0425:"X",\u0422:"T",\u041D:"H",\u041C:"M",\u041A:"K",\u0392:"B",\u0395:"E",\u0397:"H",\u039A:"K",\u039C:"M",\u039D:"N",\u039F:"O",\u03A1:"P",\u03A4:"T",\u0396:"Z"};let E=s.normalize("NFKC");for(const[m,p]of Object.entries(A))E=E.split(m).join(p);const b=E.replace(/\\u([0-9A-Fa-f]{4})/g,(m,p)=>String.fromCharCode(parseInt(p,16))).replace(/\\u\{([0-9A-Fa-f]{1,6})\}/g,(m,p)=>String.fromCodePoint(parseInt(p,16))).replace(/\\U([0-9A-Fa-f]{8})/g,(m,p)=>String.fromCodePoint(parseInt(p,16))).replace(/[\u202A\u202B\u202C\u202D\u202E\u2066\u2067\u2068\u2069]/g,"").replace(/[\u{E0000}-\u{E007F}]/gu,"");y=b.replace(/[\u200B\u200C\u200D\uFEFF\u00AD\u2060\u180E]/g,"").replace(/\s{2,}/g," ").trim(),x=b.replace(/[\u200B\u200C\u200D\uFEFF\u00AD\u2060\u180E]/g," ").replace(/\s{2,}/g," ").trim()}return{found:t>0,count:t,types:o,normalized:y,normalizedSpaced:x}}detectHex(s){const o=[],t=[];let c="";const a=/(?:0x|\\x)([0-9A-Fa-f]{2})/g;let n;for(;(n=a.exec(s))!==null;)o.push(n[0]),t.push(`index:${n.index}`),c+=String.fromCharCode(parseInt(n[1],16));const u=/(?:^|[^0-9A-Fa-f])([0-9A-Fa-f]{8,})(?:[^0-9A-Fa-f]|$)/g;for(;(n=u.exec(s))!==null;){const l=n[1];if(l.length%2===0){let h="",r=!0;for(let e=0;e<l.length;e+=2){const d=parseInt(l.substr(e,2),16);if(d>=32&&d<=126)h+=String.fromCharCode(d);else{r=!1;break}}r&&h.length>=4&&(o.push(l),t.push(`index:${n.index}`),c+=h)}}const i=/(?:[0-9A-Fa-f]{2}\s+){3,}[0-9A-Fa-f]{2}/g;for(;(n=i.exec(s))!==null;){const l=n[0].split(/\s+/);let h="",r=!0;for(const e of l){const d=parseInt(e,16);if(d>=32&&d<=126)h+=String.fromCharCode(d);else{r=!1;break}}r&&h.length>=4&&(o.push(n[0]),t.push(`index:${n.index}`),c+=h)}return{found:o.length>0,matches:o,locations:t,decoded:c||void 0}}detectHTMLEntities(s){const o=/&(?:#\d+|#x[0-9A-Fa-f]+|\w+);/g,t=s.match(o)||[];let c;return t.length>0&&(c=s.replace(/&#(\d+);/g,(a,n)=>String.fromCharCode(parseInt(n,10))).replace(/&#x([0-9A-Fa-f]+);/g,(a,n)=>String.fromCharCode(parseInt(n,16))).replace(/&lt;/g,"<").replace(/&gt;/g,">").replace(/&amp;/g,"&").replace(/&quot;/g,'"').replace(/&apos;/g,"'")),{found:t.length>0,count:t.length,decoded:c}}detectROT13(s){const o=h=>h.replace(/[a-zA-Z]/g,r=>{const e=r<="Z"?65:97;return String.fromCharCode((r.charCodeAt(0)-e+13)%26+e)}),t=[],c=[];let a;const n=["ignore","instructions","system","admin","password","secret","delete","drop","select","union","script","eval","exec","shell","command","root","sudo","bypass","hack","inject","reveal","prompt","override","jailbreak","unrestricted"],u=/\b[a-zA-Z]{5,}\b/g;let i;for(;(i=u.exec(s))!==null;){const h=i[0],r=o(h).toLowerCase();n.includes(r)&&(t.push(h),c.push(`index:${i.index}`),a=a?a+" "+r:r)}const l=/^[a-zA-Z\s]+$/.test(s.trim());return(t.length>0||l)&&(a=o(s),l&&t.length===0&&(t.push(s.substring(0,20)),c.push("index:0"))),{found:t.length>0,matches:t,locations:c,decoded:a}}detectOctal(s){const o=/(?:\\([0-7]{3})|(?:^|\s)(0[0-7]{2,}))/g,t=[],c=[];let a="",n;for(;(n=o.exec(s))!==null;){const u=n[1]||n[2];if(t.push(n[0]),c.push(`index:${n.index}`),n[1])a+=String.fromCharCode(parseInt(n[1],8));else if(n[2]){const i=parseInt(n[2],8);i>=32&&i<=126&&(a+=String.fromCharCode(i))}}return{found:t.length>0,matches:t,locations:c,decoded:a||void 0}}detectBase32(s){const o=/(?:[A-Z2-7]{8}){2,}(?:={0,6})?/g,t=[],c=[];let a;const n=i=>{const l="ABCDEFGHIJKLMNOPQRSTUVWXYZ234567",h=i.replace(/=/g,"").toUpperCase();let r="";for(const d of h){const g=l.indexOf(d);if(g===-1)return null;r+=g.toString(2).padStart(5,"0")}let e="";for(let d=0;d+8<=r.length;d+=8){const g=parseInt(r.substr(d,8),2);if(g>=32&&g<=126)e+=String.fromCharCode(g);else return null}return e.length>0?e:null};let u;for(;(u=o.exec(s))!==null;)try{const i=u[0],l=n(i);l&&l.length>=4&&(t.push(i),c.push(`index:${u.index}`),a=a?a+" "+l:l)}catch{}return{found:t.length>0,matches:t,locations:c,decoded:a}}checkThreats(s,o,t){for(const c of this.config.threatPatterns)c.pattern.lastIndex=0,c.pattern.test(s)&&t.push({pattern_name:c.name,severity:c.severity,in_layer:o})}fullyDecode(s){let o=s;try{o=decodeURIComponent(o)}catch{o=o.replace(/%([0-9A-Fa-f]{2})/g,(t,c)=>{try{return String.fromCharCode(parseInt(c,16))}catch{return t}})}return o=o.replace(/\\u([0-9A-Fa-f]{4})/g,(t,c)=>String.fromCharCode(parseInt(c,16))),o=o.replace(/\\u\{([0-9A-Fa-f]{1,6})\}/g,(t,c)=>String.fromCodePoint(parseInt(c,16))),o=o.replace(/\\U([0-9A-Fa-f]{8})/g,(t,c)=>String.fromCodePoint(parseInt(c,16))),o=o.replace(/(?:0x|\\x)([0-9A-Fa-f]{2})/g,(t,c)=>String.fromCharCode(parseInt(c,16))),o=o.replace(/\\([0-7]{3})/g,(t,c)=>String.fromCharCode(parseInt(c,8))),o=o.replace(/&#(\d+);/g,(t,c)=>String.fromCharCode(parseInt(c,10))).replace(/&#x([0-9A-Fa-f]+);/g,(t,c)=>String.fromCharCode(parseInt(c,16))).replace(/&lt;/g,"<").replace(/&gt;/g,">").replace(/&amp;/g,"&").replace(/&quot;/g,'"').replace(/&apos;/g,"'").replace(/&nbsp;/g," "),o=o.replace(/[\u200B\u200C\u200D\uFEFF\u00AD\u2060\u180E]/g,""),o=o.replace(/[\u202A\u202B\u202C\u202D\u202E\u2066\u2067\u2068\u2069]/g,""),o}}exports.EncodingDetector=EncodingDetector;
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.OutputFilter=void 0;class OutputFilter{constructor(e={}){this.defaultPIIPatterns=[{name:"email",pattern:/\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}\b/g,maskAs:"[EMAIL]"},{name:"phone_us",pattern:/\b(?:\+1[-.\s]?)?\(?\d{3}\)[-.\s]?\d{3}[-.\s]?\d{4}\b/g,maskAs:"[PHONE]"},{name:"ssn",pattern:/\b\d{3}[-.\s]?\d{2}[-.\s]?\d{4}\b/g,maskAs:"[SSN]"},{name:"credit_card",pattern:/\b(?:\d{4}[-.\s]?){3}\d{4}\b/g,maskAs:"[CREDIT_CARD]"},{name:"ip_address",pattern:/\b(?:\d{1,3}\.){3}\d{1,3}\b/g,maskAs:"[IP_ADDRESS]"},{name:"date_of_birth",pattern:/\b(?:0?[1-9]|1[0-2])[\/\-](?:0?[1-9]|[12]\d|3[01])[\/\-](?:19|20)\d{2}\b/g,maskAs:"[DOB]"},{name:"passport",pattern:/\b[A-Z]{1,2}\d{6,9}\b/g,maskAs:"[PASSPORT]"},{name:"bank_account",pattern:/\b(?:account|acct|routing|iban)[#:\s]*\d{8,17}\b/gi,maskAs:"[BANK_ACCOUNT]"}],this.defaultSecretPatterns=[{name:"api_key",pattern:/(?:api[_\-\s]?key|apikey)(?:\s+is)?\s*[=:\s]\s*["']?[A-Za-z0-9_\-]{16,}["']?/gi,severity:"critical"},{name:"aws_secret",pattern:/(?:aws[_-]?secret|secret[_-]?key)[=:\s]["']?[A-Za-z0-9\/+=]{40}["']?/gi,severity:"critical"},{name:"password",pattern:/(?:password|passwd|pwd)\s*(?:[=:]|is)\s*["']?[^\s"']{6,}["']?/gi,severity:"critical"},{name:"private_key",pattern:/-----BEGIN (?:RSA |EC |DSA )?PRIVATE KEY-----/g,severity:"critical"},{name:"jwt_token",pattern:/eyJ[A-Za-z0-9_-]+\.eyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+/g,severity:"high"},{name:"bearer_token",pattern:/Bearer\s+[A-Za-z0-9_\-\.]+/gi,severity:"high"},{name:"database_url",pattern:/(?:mongodb|mysql|postgres|redis):\/\/[^\s]+/gi,severity:"critical"},{name:"github_token",pattern:/gh[pousr]_[A-Za-z0-9_]{36,}/g,severity:"critical"}],this.defaultSensitiveFields=["password","secret","token","api_key","apiKey","private_key","privateKey","ssn","social_security","credit_card","creditCard","card_number","cardNumber","cvv","pin","account_number","accountNumber","routing_number","routingNumber"],this.config={detectPII:e.detectPII??!0,piiPatterns:e.piiPatterns??this.defaultPIIPatterns,sensitiveFields:e.sensitiveFields??this.defaultSensitiveFields,detectSecrets:e.detectSecrets??!0,secretPatterns:e.secretPatterns??this.defaultSecretPatterns,roleFilters:e.roleFilters??{},maskingChar:e.maskingChar??"*",preserveLength:e.preserveLength??!1},this.logger=e.logger||(()=>{})}filter(e,s,i=""){const r=[],a=[],d=[],c=[];let o,l;if(typeof e=="string")l=e;else try{l=JSON.stringify(e)}catch{l=String(e)}if(this.config.detectPII)for(const t of this.config.piiPatterns){const p=l.match(t.pattern);p&&p.length>0&&(a.push({type:t.name,count:p.length,masked:!0,locations:this.findLocations(l,t.pattern)}),r.push(`PII_DETECTED_${t.name.toUpperCase()}`))}if(this.config.detectSecrets)for(const t of this.config.secretPatterns){const p=l.match(t.pattern);p&&p.length>0&&(d.push({type:t.name,severity:t.severity,blocked:t.severity==="critical",location:"response"}),r.push(`SECRET_DETECTED_${t.name.toUpperCase()}`),t.severity==="critical"&&(o=`Critical secret detected: ${t.name}`))}let n;if(typeof e=="string")n=e;else try{n=JSON.parse(JSON.stringify(e))}catch{n=String(e)}if(this.config.detectPII&&typeof n=="string")for(const t of this.config.piiPatterns)n=n.replace(t.pattern,t.maskAs||this.generateMask(8));else typeof n=="object"&&n!==null&&(n=this.filterObject(n,s,c,a));if(this.config.detectSecrets&&typeof n=="string")for(const t of this.config.secretPatterns){const p=`[${t.name.toUpperCase()}]`;n=n.replace(t.pattern,p)}const f=!d.some(t=>t.blocked);return f||this.logger(`[OutputFilter:${i}] BLOCKED: ${o}`,"info"),{allowed:f,reason:f?void 0:o,violations:r,pii_detected:a,secrets_detected:d,filtered_fields:c,original_response:e,filtered_response:n,blocking_reason:o}}containsSensitiveData(e){const s=this.filter(e);return s.pii_detected.length>0||s.secrets_detected.length>0||s.filtered_fields.length>0}mask(e,s){const i=this.config.piiPatterns?.find(r=>r.name===s);return i?.maskAs?i.maskAs:this.generateMask(e.length)}filterObject(e,s,i,r){if(Array.isArray(e))return e.map(c=>this.filterObject(c,s,i,r));if(typeof e!="object"||e===null)return typeof e=="string"?this.maskPIIInString(e,r):e;const a={},d=s?this.config.roleFilters?.[s]:void 0;for(const[c,o]of Object.entries(e)){const l=c.toLowerCase(),n=this.config.sensitiveFields?.some(f=>l.includes(f.toLowerCase())),g=d?.includes(c);if(n||g){i.push(c),a[c]="[FILTERED]";continue}typeof o=="object"&&o!==null?a[c]=this.filterObject(o,s,i,r):typeof o=="string"?a[c]=this.maskPIIInString(o,r):a[c]=o}return a}maskPIIInString(e,s){let i=e;for(const r of this.config.piiPatterns){const a=i.match(r.pattern);a&&a.length>0&&(i=i.replace(r.pattern,r.maskAs||this.generateMask(8)))}return i}generateMask(e){return this.config.preserveLength?this.config.maskingChar.repeat(e):this.config.maskingChar.repeat(8)}findLocations(e,s){const i=[];let r;const a=new RegExp(s.source,s.flags);for(;(r=a.exec(e))!==null&&(i.push(`index:${r.index}`),!!s.flags.includes("g")););return i}}exports.OutputFilter=OutputFilter;
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.OutputFilter=void 0;class OutputFilter{constructor(e={}){this.defaultPIIPatterns=[{name:"email",pattern:/\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}\b/g,maskAs:"[EMAIL]"},{name:"phone_us",pattern:/\b(?:\+1[-.\s]?)?\(?\d{3}\)[-.\s]?\d{3}[-.\s]?\d{4}\b/g,maskAs:"[PHONE]"},{name:"ssn",pattern:/\b\d{3}[-.\s]?\d{2}[-.\s]?\d{4}\b/g,maskAs:"[SSN]"},{name:"credit_card",pattern:/\b(?:\d{4}[-.\s]?){3}\d{4}\b/g,maskAs:"[CREDIT_CARD]"},{name:"ip_address",pattern:/\b(?:\d{1,3}\.){3}\d{1,3}\b/g,maskAs:"[IP_ADDRESS]"},{name:"date_of_birth",pattern:/\b(?:0?[1-9]|1[0-2])[\/\-](?:0?[1-9]|[12]\d|3[01])[\/\-](?:19|20)\d{2}\b/g,maskAs:"[DOB]"},{name:"passport",pattern:/\b[A-Z]{1,2}\d{6,9}\b/g,maskAs:"[PASSPORT]"},{name:"bank_account",pattern:/\b(?:account|acct|routing|iban)[#:\s]*\d{8,17}\b/gi,maskAs:"[BANK_ACCOUNT]"}],this.defaultSecretPatterns=[{name:"api_key",pattern:/(?:api[_\-\s]?key|apikey)(?:\s+is)?\s*[=:\s]\s*["']?[A-Za-z0-9_\-]{16,}["']?/gi,severity:"critical"},{name:"api_key_prefix",pattern:/\b(?:sk|pk|rk|ak)[_-][a-zA-Z0-9]{8,}\b/g,severity:"critical"},{name:"aws_secret",pattern:/(?:aws[_-]?secret|secret[_-]?key)[=:\s]["']?[A-Za-z0-9\/+=]{40}["']?/gi,severity:"critical"},{name:"password",pattern:/(?:password|passwd|pwd)\s*(?:[=:]|is)\s*["']?[^\s"']{6,}["']?/gi,severity:"critical"},{name:"private_key",pattern:/-----BEGIN (?:RSA |EC |DSA )?PRIVATE KEY-----/g,severity:"critical"},{name:"jwt_token",pattern:/eyJ[A-Za-z0-9_-]+\.eyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+/g,severity:"high"},{name:"bearer_token",pattern:/Bearer\s+[A-Za-z0-9_\-\.]+/gi,severity:"high"},{name:"database_url",pattern:/(?:mongodb|mysql|postgres|redis):\/\/[^\s]+/gi,severity:"critical"},{name:"github_token",pattern:/gh[pousr]_[A-Za-z0-9_]{36,}/g,severity:"critical"}],this.defaultSensitiveFields=["password","secret","token","api_key","apiKey","private_key","privateKey","ssn","social_security","credit_card","creditCard","card_number","cardNumber","cvv","pin","account_number","accountNumber","routing_number","routingNumber"],this.config={detectPII:e.detectPII??!0,piiPatterns:e.piiPatterns??this.defaultPIIPatterns,sensitiveFields:e.sensitiveFields??this.defaultSensitiveFields,detectSecrets:e.detectSecrets??!0,secretPatterns:e.secretPatterns??this.defaultSecretPatterns,roleFilters:e.roleFilters??{},maskingChar:e.maskingChar??"*",preserveLength:e.preserveLength??!1},this.logger=e.logger||(()=>{})}filter(e,s,i=""){const r=[],a=[],d=[],c=[];let o,l;if(typeof e=="string")l=e;else try{l=JSON.stringify(e)}catch{l=String(e)}if(this.config.detectPII)for(const t of this.config.piiPatterns){const p=l.match(t.pattern);p&&p.length>0&&(a.push({type:t.name,count:p.length,masked:!0,locations:this.findLocations(l,t.pattern)}),r.push(`PII_DETECTED_${t.name.toUpperCase()}`))}if(this.config.detectSecrets)for(const t of this.config.secretPatterns){const p=l.match(t.pattern);p&&p.length>0&&(d.push({type:t.name,severity:t.severity,blocked:t.severity==="critical",location:"response"}),r.push(`SECRET_DETECTED_${t.name.toUpperCase()}`),t.severity==="critical"&&(o=`Critical secret detected: ${t.name}`))}let n;if(typeof e=="string")n=e;else try{n=JSON.parse(JSON.stringify(e))}catch{n=String(e)}if(this.config.detectPII&&typeof n=="string")for(const t of this.config.piiPatterns)n=n.replace(t.pattern,t.maskAs||this.generateMask(8));else typeof n=="object"&&n!==null&&(n=this.filterObject(n,s,c,a));if(this.config.detectSecrets&&typeof n=="string")for(const t of this.config.secretPatterns){const p=`[${t.name.toUpperCase()}]`;n=n.replace(t.pattern,p)}const f=!d.some(t=>t.blocked);return f||this.logger(`[OutputFilter:${i}] BLOCKED: ${o}`,"info"),{allowed:f,reason:f?void 0:o,violations:r,pii_detected:a,secrets_detected:d,filtered_fields:c,original_response:e,filtered_response:n,blocking_reason:o}}containsSensitiveData(e){const s=this.filter(e);return s.pii_detected.length>0||s.secrets_detected.length>0||s.filtered_fields.length>0}mask(e,s){const i=this.config.piiPatterns?.find(r=>r.name===s);return i?.maskAs?i.maskAs:this.generateMask(e.length)}filterObject(e,s,i,r){if(Array.isArray(e))return e.map(c=>this.filterObject(c,s,i,r));if(typeof e!="object"||e===null)return typeof e=="string"?this.maskPIIInString(e,r):e;const a={},d=s?this.config.roleFilters?.[s]:void 0;for(const[c,o]of Object.entries(e)){const l=c.toLowerCase(),n=this.config.sensitiveFields?.some(f=>l.includes(f.toLowerCase())),g=d?.includes(c);if(n||g){i.push(c),a[c]="[FILTERED]";continue}typeof o=="object"&&o!==null?a[c]=this.filterObject(o,s,i,r):typeof o=="string"?a[c]=this.maskPIIInString(o,r):a[c]=o}return a}maskPIIInString(e,s){let i=e;for(const r of this.config.piiPatterns){const a=i.match(r.pattern);a&&a.length>0&&(i=i.replace(r.pattern,r.maskAs||this.generateMask(8)))}return i}generateMask(e){return this.config.preserveLength?this.config.maskingChar.repeat(e):this.config.maskingChar.repeat(8)}findLocations(e,s){const i=[];let r;const a=new RegExp(s.source,s.flags);for(;(r=a.exec(e))!==null&&(i.push(`index:${r.index}`),!!s.flags.includes("g")););return i}}exports.OutputFilter=OutputFilter;