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 +46 -0
- package/dist/config.d.ts +59 -0
- package/dist/config.js +10 -2
- package/dist/index.js +6 -1
- package/dist/layers/privacy.js +22 -0
- package/package.json +1 -1
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(", ")}`);
|
package/dist/layers/privacy.js
CHANGED
|
@@ -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