onion-ai 1.0.6 → 1.1.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/README.md CHANGED
@@ -160,6 +160,52 @@ if (!scan.safe) {
160
160
  }
161
161
  ```
162
162
 
163
+ ## ⚙️ Advanced Customization
164
+
165
+ ### 4. Custom PII Validators (New!)
166
+ Need to mask internal IDs (like `TRIP-1234`)? You can now add custom patterns.
167
+
168
+ ```typescript
169
+ const onion = new OnionAI({
170
+ piiProtection: {
171
+ enabled: true,
172
+ custom: [
173
+ {
174
+ name: "Trip ID",
175
+ pattern: /TRIP-\d{4}/,
176
+ replaceWith: "[TRIP_ID]"
177
+ }
178
+ ]
179
+ }
180
+ });
181
+ ```
182
+
183
+ ### 5. Bring Your Own Logger (BYOL)
184
+ Integrate OnionAI with your existing observability tools (Datadog, Winston, etc.).
185
+
186
+ ```typescript
187
+ const onion = new OnionAI({
188
+ logger: {
189
+ log: (msg, meta) => console.log(`[OnionInfo] ${msg}`, meta),
190
+ error: (msg, meta) => console.error(`[OnionAlert] ${msg}`, meta)
191
+ }
192
+ });
193
+ ```
194
+
195
+ ---
196
+
197
+ ## 🔐 OWASP LLM Top 10 Compliance
198
+ Onion AI is designed to mitigate specific risks outlined in the [OWASP Top 10 for Large Language Model Applications](https://owasp.org/www-project-top-10-for-large-language-model-applications/).
199
+
200
+ | OWASP Vulnerability | Onion AI Defense Layer | Mechanism |
201
+ | :--- | :--- | :--- |
202
+ | **LLM01: Prompt Injection** | **Guard Layer** | Blocks "Ignore Previous Instructions" & Jailbreak patterns. |
203
+ | **LLM02: Sensitive Info Disclosure** | **Privacy Layer** | Redacts PII (SSN, Email, Phone) from inputs. |
204
+ | **LLM02: Sensitive Info Disclosure** | **Validator Layer** | Scans output for accidental PII or Key leakage. |
205
+ | **LLM04: Model Denial of Service** | **Sentry Layer** | Enforces Token limits & Rate limiting logic. |
206
+ | **LLM06: Excessive Agency** | **Vault Layer** | Prevents destructive actions (DROP, DELETE) in SQL agents. |
207
+ | **LLM02: Insecure Output Handling** | **Sanitizer Layer** | Strips XSS vectors (Scripts, HTML) from inputs. |
208
+
163
209
  ---
164
210
 
165
211
  ## ⚙️ Advanced Configuration
package/dist/config.d.ts CHANGED
@@ -166,6 +166,22 @@ export declare const OnionConfigSchema: z.ZodObject<{
166
166
  maskCreditCard: z.ZodDefault<z.ZodBoolean>;
167
167
  maskSSN: z.ZodDefault<z.ZodBoolean>;
168
168
  maskIP: z.ZodDefault<z.ZodBoolean>;
169
+ custom: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodObject<{
170
+ name: z.ZodString;
171
+ pattern: z.ZodOptional<z.ZodType<RegExp, z.ZodTypeDef, RegExp>>;
172
+ validator: z.ZodOptional<z.ZodFunction<z.ZodTuple<[z.ZodString], z.ZodUnknown>, z.ZodBoolean>>;
173
+ replaceWith: z.ZodOptional<z.ZodString>;
174
+ }, "strip", z.ZodTypeAny, {
175
+ name: string;
176
+ pattern?: RegExp | undefined;
177
+ validator?: ((args_0: string, ...args: unknown[]) => boolean) | undefined;
178
+ replaceWith?: string | undefined;
179
+ }, {
180
+ name: string;
181
+ pattern?: RegExp | undefined;
182
+ validator?: ((args_0: string, ...args: unknown[]) => boolean) | undefined;
183
+ replaceWith?: string | undefined;
184
+ }>, "many">>>;
169
185
  }, "strip", z.ZodTypeAny, {
170
186
  enabled: boolean;
171
187
  maskEmail: boolean;
@@ -173,6 +189,12 @@ export declare const OnionConfigSchema: z.ZodObject<{
173
189
  maskCreditCard: boolean;
174
190
  maskSSN: boolean;
175
191
  maskIP: boolean;
192
+ custom: {
193
+ name: string;
194
+ pattern?: RegExp | undefined;
195
+ validator?: ((args_0: string, ...args: unknown[]) => boolean) | undefined;
196
+ replaceWith?: string | undefined;
197
+ }[];
176
198
  }, {
177
199
  enabled?: boolean | undefined;
178
200
  maskEmail?: boolean | undefined;
@@ -180,6 +202,19 @@ export declare const OnionConfigSchema: z.ZodObject<{
180
202
  maskCreditCard?: boolean | undefined;
181
203
  maskSSN?: boolean | undefined;
182
204
  maskIP?: boolean | undefined;
205
+ custom?: {
206
+ name: string;
207
+ pattern?: RegExp | undefined;
208
+ validator?: ((args_0: string, ...args: unknown[]) => boolean) | undefined;
209
+ replaceWith?: string | undefined;
210
+ }[] | undefined;
211
+ }>>;
212
+ logger: z.ZodOptional<z.ZodType<{
213
+ log: (message: string, meta?: any) => void;
214
+ error: (message: string, meta?: any) => void;
215
+ }, z.ZodTypeDef, {
216
+ log: (message: string, meta?: any) => void;
217
+ error: (message: string, meta?: any) => void;
183
218
  }>>;
184
219
  }, "strip", z.ZodTypeAny, {
185
220
  inputSanitization: {
@@ -248,7 +283,17 @@ export declare const OnionConfigSchema: z.ZodObject<{
248
283
  maskCreditCard: boolean;
249
284
  maskSSN: boolean;
250
285
  maskIP: boolean;
286
+ custom: {
287
+ name: string;
288
+ pattern?: RegExp | undefined;
289
+ validator?: ((args_0: string, ...args: unknown[]) => boolean) | undefined;
290
+ replaceWith?: string | undefined;
291
+ }[];
251
292
  };
293
+ logger?: {
294
+ log: (message: string, meta?: any) => void;
295
+ error: (message: string, meta?: any) => void;
296
+ } | undefined;
252
297
  }, {
253
298
  inputSanitization?: {
254
299
  sanitizeHtml?: boolean | undefined;
@@ -316,6 +361,16 @@ export declare const OnionConfigSchema: z.ZodObject<{
316
361
  maskCreditCard?: boolean | undefined;
317
362
  maskSSN?: boolean | undefined;
318
363
  maskIP?: boolean | undefined;
364
+ custom?: {
365
+ name: string;
366
+ pattern?: RegExp | undefined;
367
+ validator?: ((args_0: string, ...args: unknown[]) => boolean) | undefined;
368
+ replaceWith?: string | undefined;
369
+ }[] | undefined;
370
+ } | undefined;
371
+ logger?: {
372
+ log: (message: string, meta?: any) => void;
373
+ error: (message: string, meta?: any) => void;
319
374
  } | undefined;
320
375
  }>;
321
376
  export type OnionConfig = z.infer<typeof OnionConfigSchema>;
@@ -327,6 +382,10 @@ export interface SimpleOnionConfig {
327
382
  piiSafe?: boolean;
328
383
  debug?: boolean;
329
384
  strict?: boolean;
385
+ logger?: {
386
+ log: (message: string, meta?: any) => void;
387
+ error: (message: string, meta?: any) => void;
388
+ };
330
389
  onWarning?: (threats: string[]) => void;
331
390
  }
332
391
  export interface SecurityResult {
package/dist/config.js CHANGED
@@ -132,7 +132,13 @@ exports.OnionConfigSchema = zod_1.z.object({
132
132
  maskPhone: zod_1.z.boolean().default(true),
133
133
  maskCreditCard: zod_1.z.boolean().default(true),
134
134
  maskSSN: zod_1.z.boolean().default(true),
135
- maskIP: zod_1.z.boolean().default(true)
135
+ maskIP: zod_1.z.boolean().default(true),
136
+ custom: zod_1.z.array(zod_1.z.object({
137
+ name: zod_1.z.string(),
138
+ pattern: zod_1.z.instanceof(RegExp).optional(),
139
+ validator: zod_1.z.function().args(zod_1.z.string()).returns(zod_1.z.boolean()).optional(),
140
+ replaceWith: zod_1.z.string().optional()
141
+ })).optional().default([])
136
142
  }).default({
137
143
  enabled: false,
138
144
  maskEmail: true,
@@ -140,5 +146,7 @@ exports.OnionConfigSchema = zod_1.z.object({
140
146
  maskCreditCard: true,
141
147
  maskSSN: true,
142
148
  maskIP: true
143
- })
149
+ }),
150
+ // Plugins & Logger (Optional runtime objects)
151
+ logger: zod_1.z.custom((val) => typeof val === 'object' && val !== null && 'log' in val).optional()
144
152
  });
package/dist/index.js CHANGED
@@ -36,7 +36,8 @@ class OnionAI {
36
36
  },
37
37
  enhance: { enabled: config.enhance ?? false },
38
38
  loggingMonitoringAndAudit: { logRequests: config.debug ?? false },
39
- piiProtection: { enabled: config.piiSafe ?? false }
39
+ piiProtection: { enabled: config.piiSafe ?? false },
40
+ logger: config.logger
40
41
  };
41
42
  }
42
43
  else {
@@ -74,6 +75,10 @@ class OnionAI {
74
75
  if (onWarning) {
75
76
  onWarning(secLikelihood.threats);
76
77
  }
78
+ // Custom Logger (Phase 1.2)
79
+ if (this.config.logger) {
80
+ this.config.logger.error("OnionAI Security Alert", { threats: secLikelihood.threats, riskScore: secLikelihood.riskScore });
81
+ }
77
82
  // Strict Mode: Throw error if threats found
78
83
  if (this.simpleConfig?.strict) {
79
84
  throw new Error(`OnionAI Security Violation: ${secLikelihood.threats.join(", ")}`);
@@ -56,6 +56,28 @@ class Privacy {
56
56
  threats.push("PII Detected: IP Address");
57
57
  }
58
58
  }
59
+ // Custom Validators (Phase 1.1)
60
+ if (this.config.custom && this.config.custom.length > 0) {
61
+ for (const validator of this.config.custom) {
62
+ // Regex Pattern Strategy
63
+ if (validator.pattern) {
64
+ if (sanitizedValue.match(validator.pattern)) {
65
+ const replacement = validator.replaceWith || `[${validator.name.toUpperCase()}_REDACTED]`;
66
+ sanitizedValue = sanitizedValue.replace(validator.pattern, replacement);
67
+ threats.push(`PII Detected: Custom (${validator.name})`);
68
+ }
69
+ }
70
+ // Function Validator Strategy (Simple Check)
71
+ else if (validator.validator) {
72
+ // Logic for validator function is harder for replacement unless it returns indices.
73
+ // For now, we assume it just FLAGS it, unless we scan word by word?
74
+ // Let's keep it simple: if it returns true, we flag it. Modification is hard without location.
75
+ if (validator.validator(input)) {
76
+ threats.push(`PII Detected: Custom (${validator.name}) - Detected by Validator`);
77
+ }
78
+ }
79
+ }
80
+ }
59
81
  return {
60
82
  safe: threats.length === 0, // It is technically "safe" now that it is redacted, but we flag the threat presence
61
83
  threats,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "onion-ai",
3
- "version": "1.0.6",
3
+ "version": "1.1.0",
4
4
  "description": "Layered security for AI prompting - input sanitization, injection protection, and output validation.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",