@openguardrails/gateway 1.0.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.
Files changed (41) hide show
  1. package/dist/config.d.ts +13 -0
  2. package/dist/config.d.ts.map +1 -0
  3. package/dist/config.js +100 -0
  4. package/dist/config.js.map +1 -0
  5. package/dist/handlers/anthropic.d.ts +12 -0
  6. package/dist/handlers/anthropic.d.ts.map +1 -0
  7. package/dist/handlers/anthropic.js +150 -0
  8. package/dist/handlers/anthropic.js.map +1 -0
  9. package/dist/handlers/gemini.d.ts +12 -0
  10. package/dist/handlers/gemini.d.ts.map +1 -0
  11. package/dist/handlers/gemini.js +80 -0
  12. package/dist/handlers/gemini.js.map +1 -0
  13. package/dist/handlers/openai.d.ts +13 -0
  14. package/dist/handlers/openai.d.ts.map +1 -0
  15. package/dist/handlers/openai.js +145 -0
  16. package/dist/handlers/openai.js.map +1 -0
  17. package/dist/index.d.ts +16 -0
  18. package/dist/index.d.ts.map +1 -0
  19. package/dist/index.js +136 -0
  20. package/dist/index.js.map +1 -0
  21. package/dist/restorer.d.ts +21 -0
  22. package/dist/restorer.d.ts.map +1 -0
  23. package/dist/restorer.js +91 -0
  24. package/dist/restorer.js.map +1 -0
  25. package/dist/sanitizer.d.ts +17 -0
  26. package/dist/sanitizer.d.ts.map +1 -0
  27. package/dist/sanitizer.js +226 -0
  28. package/dist/sanitizer.js.map +1 -0
  29. package/dist/types.d.ts +35 -0
  30. package/dist/types.d.ts.map +1 -0
  31. package/dist/types.js +5 -0
  32. package/dist/types.js.map +1 -0
  33. package/package.json +55 -0
  34. package/src/config.ts +122 -0
  35. package/src/handlers/anthropic.ts +195 -0
  36. package/src/handlers/gemini.ts +99 -0
  37. package/src/handlers/openai.ts +188 -0
  38. package/src/index.ts +159 -0
  39. package/src/restorer.ts +101 -0
  40. package/src/sanitizer.ts +278 -0
  41. package/src/types.ts +43 -0
package/dist/index.js ADDED
@@ -0,0 +1,136 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * OpenGuardrails AI Security Gateway
4
+ *
5
+ * Local HTTP proxy that intercepts LLM API calls, sanitizes sensitive data
6
+ * before sending to providers, and restores it in responses.
7
+ * Supports Anthropic, OpenAI, and Gemini protocols.
8
+ */
9
+ import { createServer } from "node:http";
10
+ import { loadConfig, validateConfig } from "./config.js";
11
+ import { handleAnthropicRequest } from "./handlers/anthropic.js";
12
+ import { handleOpenAIRequest } from "./handlers/openai.js";
13
+ import { handleGeminiRequest } from "./handlers/gemini.js";
14
+ const GATEWAY_MODE = process.env.GATEWAY_MODE || "selfhosted";
15
+ let config;
16
+ /**
17
+ * Main request handler
18
+ */
19
+ async function handleRequest(req, res) {
20
+ const { method, url } = req;
21
+ // Log request
22
+ console.log(`[ai-security-gateway] ${method} ${url}`);
23
+ // CORS headers (for browser-based clients)
24
+ res.setHeader("Access-Control-Allow-Origin", "*");
25
+ res.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
26
+ res.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization, x-api-key, anthropic-version");
27
+ // Handle OPTIONS for CORS preflight
28
+ if (method === "OPTIONS") {
29
+ res.writeHead(204);
30
+ res.end();
31
+ return;
32
+ }
33
+ // Health check (allow GET)
34
+ if (url === "/health") {
35
+ res.writeHead(200, { "Content-Type": "application/json" });
36
+ res.end(JSON.stringify({ status: "ok", version: "1.0.0" }));
37
+ return;
38
+ }
39
+ // Only allow POST for API endpoints
40
+ if (method !== "POST") {
41
+ res.writeHead(405, { "Content-Type": "application/json" });
42
+ res.end(JSON.stringify({ error: "Method not allowed" }));
43
+ return;
44
+ }
45
+ // Route to appropriate handler
46
+ try {
47
+ if (url === "/v1/messages") {
48
+ // Anthropic Messages API
49
+ await handleAnthropicRequest(req, res, config);
50
+ }
51
+ else if (url === "/v1/chat/completions") {
52
+ // OpenAI Chat Completions API
53
+ await handleOpenAIRequest(req, res, config);
54
+ }
55
+ else if (url?.match(/^\/v1\/models\/(.+):generateContent$/)) {
56
+ // Gemini API
57
+ const match = url.match(/^\/v1\/models\/(.+):generateContent$/);
58
+ const modelName = match?.[1];
59
+ if (modelName) {
60
+ await handleGeminiRequest(req, res, config, modelName);
61
+ }
62
+ else {
63
+ res.writeHead(404, { "Content-Type": "application/json" });
64
+ res.end(JSON.stringify({ error: "Model name required" }));
65
+ }
66
+ }
67
+ else {
68
+ // Unknown endpoint
69
+ res.writeHead(404, { "Content-Type": "application/json" });
70
+ res.end(JSON.stringify({ error: "Not found", url }));
71
+ }
72
+ }
73
+ catch (error) {
74
+ console.error("[ai-security-gateway] Request handler error:", error);
75
+ res.writeHead(500, { "Content-Type": "application/json" });
76
+ res.end(JSON.stringify({
77
+ error: "Internal server error",
78
+ message: error instanceof Error ? error.message : String(error),
79
+ }));
80
+ }
81
+ }
82
+ /**
83
+ * Start gateway server
84
+ */
85
+ export function startGateway(configPath) {
86
+ try {
87
+ // Load and validate configuration
88
+ config = loadConfig(configPath);
89
+ validateConfig(config);
90
+ console.log("[ai-security-gateway] Configuration loaded:");
91
+ console.log(` Mode: ${GATEWAY_MODE}`);
92
+ console.log(` Port: ${config.port}`);
93
+ console.log(` Backends: ${Object.keys(config.backends).join(", ")}`);
94
+ // Create HTTP server
95
+ const server = createServer(handleRequest);
96
+ // Start listening
97
+ server.listen(config.port, "127.0.0.1", () => {
98
+ console.log(`[ai-security-gateway] Server listening on http://127.0.0.1:${config.port}`);
99
+ console.log("[ai-security-gateway] Ready to proxy requests");
100
+ console.log("");
101
+ console.log("Endpoints:");
102
+ console.log(` POST http://127.0.0.1:${config.port}/v1/messages - Anthropic`);
103
+ console.log(` POST http://127.0.0.1:${config.port}/v1/chat/completions - OpenAI`);
104
+ console.log(` POST http://127.0.0.1:${config.port}/v1/models/:model:generateContent - Gemini`);
105
+ console.log(` GET http://127.0.0.1:${config.port}/health - Health check`);
106
+ });
107
+ // Handle shutdown
108
+ process.on("SIGINT", () => {
109
+ console.log("\n[ai-security-gateway] Shutting down...");
110
+ server.close(() => {
111
+ console.log("[ai-security-gateway] Server stopped");
112
+ process.exit(0);
113
+ });
114
+ });
115
+ process.on("SIGTERM", () => {
116
+ console.log("\n[ai-security-gateway] Shutting down...");
117
+ server.close(() => {
118
+ console.log("[ai-security-gateway] Server stopped");
119
+ process.exit(0);
120
+ });
121
+ });
122
+ }
123
+ catch (error) {
124
+ console.error("[ai-security-gateway] Failed to start:", error);
125
+ process.exit(1);
126
+ }
127
+ }
128
+ // Re-export for programmatic use
129
+ export { sanitize, sanitizeMessages } from "./sanitizer.js";
130
+ export { restore, restoreJSON, restoreSSELine } from "./restorer.js";
131
+ // Start if run directly
132
+ if (import.meta.url === `file://${process.argv[1]}`) {
133
+ const configPath = process.argv[2];
134
+ startGateway(configPath);
135
+ }
136
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * AI Security Gateway - Content restorer
3
+ *
4
+ * Restores sanitized placeholders back to original values using the mapping table.
5
+ */
6
+ import type { MappingTable } from "./types.js";
7
+ /**
8
+ * Restore any content (object, array, string) using the mapping table
9
+ */
10
+ export declare function restore(content: any, mappingTable: MappingTable): any;
11
+ /**
12
+ * Restore a JSON string
13
+ * Useful for SSE streaming where each chunk is a JSON string
14
+ */
15
+ export declare function restoreJSON(jsonString: string, mappingTable: MappingTable): string;
16
+ /**
17
+ * Restore SSE data line (for streaming responses)
18
+ * Format: "data: {...}\n"
19
+ */
20
+ export declare function restoreSSELine(line: string, mappingTable: MappingTable): string;
21
+ //# sourceMappingURL=restorer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"restorer.d.ts","sourceRoot":"","sources":["../src/restorer.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAiD/C;;GAEG;AACH,wBAAgB,OAAO,CAAC,OAAO,EAAE,GAAG,EAAE,YAAY,EAAE,YAAY,GAAG,GAAG,CAGrE;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,UAAU,EAAE,MAAM,EAAE,YAAY,EAAE,YAAY,GAAG,MAAM,CAYlF;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,YAAY,GAAG,MAAM,CAe/E"}
@@ -0,0 +1,91 @@
1
+ /**
2
+ * AI Security Gateway - Content restorer
3
+ *
4
+ * Restores sanitized placeholders back to original values using the mapping table.
5
+ */
6
+ /**
7
+ * Restore placeholders in a string
8
+ */
9
+ function restoreText(text, mappingTable) {
10
+ let restored = text;
11
+ // Sort placeholders by length descending to handle nested cases
12
+ const placeholders = Array.from(mappingTable.keys()).sort((a, b) => b.length - a.length);
13
+ for (const placeholder of placeholders) {
14
+ const originalValue = mappingTable.get(placeholder);
15
+ // Use split/join for safe replacement (handles special regex chars)
16
+ restored = restored.split(placeholder).join(originalValue);
17
+ }
18
+ return restored;
19
+ }
20
+ /**
21
+ * Recursively restore any value (string, object, array)
22
+ */
23
+ function restoreValue(value, mappingTable) {
24
+ // String: restore placeholders
25
+ if (typeof value === "string") {
26
+ return restoreText(value, mappingTable);
27
+ }
28
+ // Array: restore each element
29
+ if (Array.isArray(value)) {
30
+ return value.map((item) => restoreValue(item, mappingTable));
31
+ }
32
+ // Object: restore each property
33
+ if (value !== null && typeof value === "object") {
34
+ const restored = {};
35
+ for (const [key, val] of Object.entries(value)) {
36
+ restored[key] = restoreValue(val, mappingTable);
37
+ }
38
+ return restored;
39
+ }
40
+ // Primitives: return as-is
41
+ return value;
42
+ }
43
+ /**
44
+ * Restore any content (object, array, string) using the mapping table
45
+ */
46
+ export function restore(content, mappingTable) {
47
+ if (mappingTable.size === 0)
48
+ return content;
49
+ return restoreValue(content, mappingTable);
50
+ }
51
+ /**
52
+ * Restore a JSON string
53
+ * Useful for SSE streaming where each chunk is a JSON string
54
+ */
55
+ export function restoreJSON(jsonString, mappingTable) {
56
+ if (mappingTable.size === 0)
57
+ return jsonString;
58
+ try {
59
+ // Try to parse as JSON first
60
+ const parsed = JSON.parse(jsonString);
61
+ const restored = restore(parsed, mappingTable);
62
+ return JSON.stringify(restored);
63
+ }
64
+ catch {
65
+ // If not valid JSON, treat as plain text
66
+ return restoreText(jsonString, mappingTable);
67
+ }
68
+ }
69
+ /**
70
+ * Restore SSE data line (for streaming responses)
71
+ * Format: "data: {...}\n"
72
+ */
73
+ export function restoreSSELine(line, mappingTable) {
74
+ if (mappingTable.size === 0)
75
+ return line;
76
+ if (!line.startsWith("data: "))
77
+ return line;
78
+ const dataContent = line.slice(6); // Remove "data: " prefix
79
+ if (dataContent === "[DONE]")
80
+ return line;
81
+ try {
82
+ const parsed = JSON.parse(dataContent);
83
+ const restored = restore(parsed, mappingTable);
84
+ return `data: ${JSON.stringify(restored)}\n`;
85
+ }
86
+ catch {
87
+ // Fallback to text restoration
88
+ return `data: ${restoreText(dataContent, mappingTable)}\n`;
89
+ }
90
+ }
91
+ //# sourceMappingURL=restorer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"restorer.js","sourceRoot":"","sources":["../src/restorer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * AI Security Gateway - Content sanitizer
3
+ *
4
+ * Recursively processes message structures, replaces sensitive data with
5
+ * numbered placeholders, and returns a mapping table for restoration.
6
+ */
7
+ import type { SanitizeResult } from "./types.js";
8
+ /**
9
+ * Sanitize any content (messages array, object, string)
10
+ * Returns sanitized content and mapping table for restoration
11
+ */
12
+ export declare function sanitize(content: any): SanitizeResult;
13
+ /**
14
+ * Sanitize messages array (common case for LLM APIs)
15
+ */
16
+ export declare function sanitizeMessages(messages: any[]): SanitizeResult;
17
+ //# sourceMappingURL=sanitizer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sanitizer.d.ts","sourceRoot":"","sources":["../src/sanitizer.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,cAAc,EAA6B,MAAM,YAAY,CAAC;AAwP5E;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,OAAO,EAAE,GAAG,GAAG,cAAc,CAWrD;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,GAAG,EAAE,GAAG,cAAc,CAEhE"}
@@ -0,0 +1,226 @@
1
+ /**
2
+ * AI Security Gateway - Content sanitizer
3
+ *
4
+ * Recursively processes message structures, replaces sensitive data with
5
+ * numbered placeholders, and returns a mapping table for restoration.
6
+ */
7
+ const ENTITIES = [
8
+ // URLs (must come before email to avoid partial matches)
9
+ {
10
+ category: "URL",
11
+ categoryKey: "url",
12
+ pattern: /https?:\/\/[^\s<>"{}|\\^`\[\]]+/g,
13
+ },
14
+ // Email
15
+ {
16
+ category: "EMAIL",
17
+ categoryKey: "email",
18
+ pattern: /[A-Za-z0-9._%+\-]+@[A-Za-z0-9.\-]+\.[A-Za-z]{2,}/g,
19
+ },
20
+ // Credit Card (4 groups of 4 digits)
21
+ {
22
+ category: "CREDIT_CARD",
23
+ categoryKey: "credit_card",
24
+ pattern: /\b\d{4}[-\s]?\d{4}[-\s]?\d{4}[-\s]?\d{4}\b/g,
25
+ },
26
+ // Bank Card (Chinese format: 16-19 digits)
27
+ {
28
+ category: "BANK_CARD",
29
+ categoryKey: "bank_card",
30
+ pattern: /\b\d{16,19}\b/g,
31
+ },
32
+ // SSN (###-##-####)
33
+ {
34
+ category: "SSN",
35
+ categoryKey: "ssn",
36
+ pattern: /\b\d{3}-\d{2}-\d{4}\b/g,
37
+ },
38
+ // IBAN
39
+ {
40
+ category: "IBAN",
41
+ categoryKey: "iban",
42
+ pattern: /\b[A-Z]{2}\d{2}[A-Z0-9]{4}\d{7}[A-Z0-9]{0,16}\b/g,
43
+ },
44
+ // IP Address
45
+ {
46
+ category: "IP_ADDRESS",
47
+ categoryKey: "ip",
48
+ pattern: /\b(?:[0-9]{1,3}\.){3}[0-9]{1,3}\b/g,
49
+ },
50
+ // Phone numbers (US/intl formats, including +86-xxx-xxxx-xxxx)
51
+ {
52
+ category: "PHONE",
53
+ categoryKey: "phone",
54
+ pattern: /[+]?[0-9]{1,3}?[-\s.]?[(]?[0-9]{3}[)]?[-\s.][0-9]{3,4}[-\s.][0-9]{4,6}\b/g,
55
+ },
56
+ ];
57
+ // Known secret prefixes
58
+ const SECRET_PREFIXES = [
59
+ "sk-",
60
+ "sk_",
61
+ "pk_",
62
+ "ghp_",
63
+ "AKIA",
64
+ "xox",
65
+ "SG.",
66
+ "hf_",
67
+ "api-",
68
+ "token-",
69
+ "secret-",
70
+ ];
71
+ const BEARER_PATTERN = /Bearer\s+[A-Za-z0-9\-_.~+/]+=*/g;
72
+ const SECRET_PREFIX_PATTERN = new RegExp(`(?:${SECRET_PREFIXES.map((p) => p.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("|")})[A-Za-z0-9\\-_.~+/]{8,}=*`, "g");
73
+ // =============================================================================
74
+ // Shannon Entropy
75
+ // =============================================================================
76
+ function shannonEntropy(s) {
77
+ if (s.length === 0)
78
+ return 0;
79
+ const freq = new Map();
80
+ for (const ch of s) {
81
+ freq.set(ch, (freq.get(ch) ?? 0) + 1);
82
+ }
83
+ let entropy = 0;
84
+ for (const count of freq.values()) {
85
+ const p = count / s.length;
86
+ entropy -= p * Math.log2(p);
87
+ }
88
+ return entropy;
89
+ }
90
+ // =============================================================================
91
+ // Match Collection
92
+ // =============================================================================
93
+ function collectMatches(content) {
94
+ const matches = [];
95
+ // Regex-based entities
96
+ for (const entity of ENTITIES) {
97
+ entity.pattern.lastIndex = 0;
98
+ let m;
99
+ while ((m = entity.pattern.exec(content)) !== null) {
100
+ matches.push({
101
+ originalText: m[0],
102
+ category: entity.categoryKey,
103
+ placeholder: "", // Will be set later with numbering
104
+ });
105
+ }
106
+ }
107
+ // Secret prefixes
108
+ SECRET_PREFIX_PATTERN.lastIndex = 0;
109
+ let m;
110
+ while ((m = SECRET_PREFIX_PATTERN.exec(content)) !== null) {
111
+ matches.push({
112
+ originalText: m[0],
113
+ category: "secret",
114
+ placeholder: "",
115
+ });
116
+ }
117
+ // Bearer tokens
118
+ BEARER_PATTERN.lastIndex = 0;
119
+ while ((m = BEARER_PATTERN.exec(content)) !== null) {
120
+ matches.push({
121
+ originalText: m[0],
122
+ category: "secret",
123
+ placeholder: "",
124
+ });
125
+ }
126
+ // High-entropy tokens
127
+ const tokenPattern = /\b[A-Za-z0-9\-_.~+/]{20,}={0,3}\b/g;
128
+ tokenPattern.lastIndex = 0;
129
+ while ((m = tokenPattern.exec(content)) !== null) {
130
+ const token = m[0];
131
+ if (matches.some((existing) => existing.originalText === token))
132
+ continue;
133
+ if (/^[a-z]+$/.test(token))
134
+ continue;
135
+ if (shannonEntropy(token) >= 4.0) {
136
+ matches.push({
137
+ originalText: token,
138
+ category: "secret",
139
+ placeholder: "",
140
+ });
141
+ }
142
+ }
143
+ return matches;
144
+ }
145
+ // =============================================================================
146
+ // Text Sanitization
147
+ // =============================================================================
148
+ function sanitizeText(text, mappingTable, categoryCounters) {
149
+ const matches = collectMatches(text);
150
+ if (matches.length === 0)
151
+ return text;
152
+ // Deduplicate by original text
153
+ const unique = new Map();
154
+ for (const match of matches) {
155
+ if (!unique.has(match.originalText)) {
156
+ unique.set(match.originalText, match);
157
+ }
158
+ }
159
+ // Sort by length descending
160
+ const sorted = [...unique.values()].sort((a, b) => b.originalText.length - a.originalText.length);
161
+ // Replace and build mapping table
162
+ let sanitized = text;
163
+ for (const match of sorted) {
164
+ // Generate numbered placeholder
165
+ const counter = (categoryCounters.get(match.category) ?? 0) + 1;
166
+ categoryCounters.set(match.category, counter);
167
+ const placeholder = `__${match.category}_${counter}__`;
168
+ // Replace all occurrences
169
+ const parts = sanitized.split(match.originalText);
170
+ if (parts.length > 1) {
171
+ sanitized = parts.join(placeholder);
172
+ mappingTable.set(placeholder, match.originalText);
173
+ }
174
+ }
175
+ return sanitized;
176
+ }
177
+ // =============================================================================
178
+ // Recursive Sanitization
179
+ // =============================================================================
180
+ /**
181
+ * Recursively sanitize any value (string, object, array)
182
+ */
183
+ function sanitizeValue(value, mappingTable, categoryCounters) {
184
+ // String: sanitize directly
185
+ if (typeof value === "string") {
186
+ return sanitizeText(value, mappingTable, categoryCounters);
187
+ }
188
+ // Array: sanitize each element
189
+ if (Array.isArray(value)) {
190
+ return value.map((item) => sanitizeValue(item, mappingTable, categoryCounters));
191
+ }
192
+ // Object: sanitize each property
193
+ if (value !== null && typeof value === "object") {
194
+ const sanitized = {};
195
+ for (const [key, val] of Object.entries(value)) {
196
+ sanitized[key] = sanitizeValue(val, mappingTable, categoryCounters);
197
+ }
198
+ return sanitized;
199
+ }
200
+ // Primitives: return as-is
201
+ return value;
202
+ }
203
+ // =============================================================================
204
+ // Public API
205
+ // =============================================================================
206
+ /**
207
+ * Sanitize any content (messages array, object, string)
208
+ * Returns sanitized content and mapping table for restoration
209
+ */
210
+ export function sanitize(content) {
211
+ const mappingTable = new Map();
212
+ const categoryCounters = new Map();
213
+ const sanitized = sanitizeValue(content, mappingTable, categoryCounters);
214
+ return {
215
+ sanitized,
216
+ mappingTable,
217
+ redactionCount: mappingTable.size,
218
+ };
219
+ }
220
+ /**
221
+ * Sanitize messages array (common case for LLM APIs)
222
+ */
223
+ export function sanitizeMessages(messages) {
224
+ return sanitize(messages);
225
+ }
226
+ //# sourceMappingURL=sanitizer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sanitizer.js","sourceRoot":"","sources":["../src/sanitizer.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAcH,MAAM,QAAQ,GAAa;IACzB,yDAAyD;IACzD;QACE,QAAQ,EAAE,KAAK;QACf,WAAW,EAAE,KAAK;QAClB,OAAO,EAAE,kCAAkC;KAC5C;IACD,QAAQ;IACR;QACE,QAAQ,EAAE,OAAO;QACjB,WAAW,EAAE,OAAO;QACpB,OAAO,EAAE,mDAAmD;KAC7D;IACD,qCAAqC;IACrC;QACE,QAAQ,EAAE,aAAa;QACvB,WAAW,EAAE,aAAa;QAC1B,OAAO,EAAE,6CAA6C;KACvD;IACD,2CAA2C;IAC3C;QACE,QAAQ,EAAE,WAAW;QACrB,WAAW,EAAE,WAAW;QACxB,OAAO,EAAE,gBAAgB;KAC1B;IACD,oBAAoB;IACpB;QACE,QAAQ,EAAE,KAAK;QACf,WAAW,EAAE,KAAK;QAClB,OAAO,EAAE,wBAAwB;KAClC;IACD,OAAO;IACP;QACE,QAAQ,EAAE,MAAM;QAChB,WAAW,EAAE,MAAM;QACnB,OAAO,EAAE,kDAAkD;KAC5D;IACD,aAAa;IACb;QACE,QAAQ,EAAE,YAAY;QACtB,WAAW,EAAE,IAAI;QACjB,OAAO,EAAE,oCAAoC;KAC9C;IACD,+DAA+D;IAC/D;QACE,QAAQ,EAAE,OAAO;QACjB,WAAW,EAAE,OAAO;QACpB,OAAO,EAAE,2EAA2E;KACrF;CACF,CAAC;AAEF,wBAAwB;AACxB,MAAM,eAAe,GAAG;IACtB,KAAK;IACL,KAAK;IACL,KAAK;IACL,MAAM;IACN,MAAM;IACN,KAAK;IACL,KAAK;IACL,KAAK;IACL,MAAM;IACN,QAAQ;IACR,SAAS;CACV,CAAC;AAEF,MAAM,cAAc,GAAG,iCAAiC,CAAC;AAEzD,MAAM,qBAAqB,GAAG,IAAI,MAAM,CACtC,MAAM,eAAe,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,qBAAqB,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,4BAA4B,EAChH,GAAG,CACJ,CAAC;AAEF,gFAAgF;AAChF,kBAAkB;AAClB,gFAAgF;AAEhF,SAAS,cAAc,CAAC,CAAS;IAC/B,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,CAAC,CAAC;IAC7B,MAAM,IAAI,GAAG,IAAI,GAAG,EAAkB,CAAC;IACvC,KAAK,MAAM,EAAE,IAAI,CAAC,EAAE,CAAC;QACnB,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IACxC,CAAC;IACD,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;QAClC,MAAM,CAAC,GAAG,KAAK,GAAG,CAAC,CAAC,MAAM,CAAC;QAC3B,OAAO,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC9B,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,gFAAgF;AAChF,mBAAmB;AACnB,gFAAgF;AAEhF,SAAS,cAAc,CAAC,OAAe;IACrC,MAAM,OAAO,GAAkB,EAAE,CAAC;IAElC,uBAAuB;IACvB,KAAK,MAAM,MAAM,IAAI,QAAQ,EAAE,CAAC;QAC9B,MAAM,CAAC,OAAO,CAAC,SAAS,GAAG,CAAC,CAAC;QAC7B,IAAI,CAAyB,CAAC;QAC9B,OAAO,CAAC,CAAC,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;YACnD,OAAO,CAAC,IAAI,CAAC;gBACX,YAAY,EAAE,CAAC,CAAC,CAAC,CAAC;gBAClB,QAAQ,EAAE,MAAM,CAAC,WAAW;gBAC5B,WAAW,EAAE,EAAE,EAAE,mCAAmC;aACrD,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,kBAAkB;IAClB,qBAAqB,CAAC,SAAS,GAAG,CAAC,CAAC;IACpC,IAAI,CAAyB,CAAC;IAC9B,OAAO,CAAC,CAAC,GAAG,qBAAqB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;QAC1D,OAAO,CAAC,IAAI,CAAC;YACX,YAAY,EAAE,CAAC,CAAC,CAAC,CAAC;YAClB,QAAQ,EAAE,QAAQ;YAClB,WAAW,EAAE,EAAE;SAChB,CAAC,CAAC;IACL,CAAC;IAED,gBAAgB;IAChB,cAAc,CAAC,SAAS,GAAG,CAAC,CAAC;IAC7B,OAAO,CAAC,CAAC,GAAG,cAAc,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;QACnD,OAAO,CAAC,IAAI,CAAC;YACX,YAAY,EAAE,CAAC,CAAC,CAAC,CAAC;YAClB,QAAQ,EAAE,QAAQ;YAClB,WAAW,EAAE,EAAE;SAChB,CAAC,CAAC;IACL,CAAC;IAED,sBAAsB;IACtB,MAAM,YAAY,GAAG,oCAAoC,CAAC;IAC1D,YAAY,CAAC,SAAS,GAAG,CAAC,CAAC;IAC3B,OAAO,CAAC,CAAC,GAAG,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;QACjD,MAAM,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QACnB,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,YAAY,KAAK,KAAK,CAAC;YAAE,SAAS;QAC1E,IAAI,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC;YAAE,SAAS;QACrC,IAAI,cAAc,CAAC,KAAK,CAAC,IAAI,GAAG,EAAE,CAAC;YACjC,OAAO,CAAC,IAAI,CAAC;gBACX,YAAY,EAAE,KAAK;gBACnB,QAAQ,EAAE,QAAQ;gBAClB,WAAW,EAAE,EAAE;aAChB,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,gFAAgF;AAChF,oBAAoB;AACpB,gFAAgF;AAEhF,SAAS,YAAY,CACnB,IAAY,EACZ,YAA0B,EAC1B,gBAAqC;IAErC,MAAM,OAAO,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC;IACrC,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAEtC,+BAA+B;IAC/B,MAAM,MAAM,GAAG,IAAI,GAAG,EAAuB,CAAC;IAC9C,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,YAAY,CAAC,EAAE,CAAC;YACpC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,YAAY,EAAE,KAAK,CAAC,CAAC;QACxC,CAAC;IACH,CAAC;IAED,4BAA4B;IAC5B,MAAM,MAAM,GAAG,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CACtC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC,YAAY,CAAC,MAAM,CACxD,CAAC;IAEF,kCAAkC;IAClC,IAAI,SAAS,GAAG,IAAI,CAAC;IACrB,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,gCAAgC;QAChC,MAAM,OAAO,GAAG,CAAC,gBAAgB,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;QAChE,gBAAgB,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QAC9C,MAAM,WAAW,GAAG,KAAK,KAAK,CAAC,QAAQ,IAAI,OAAO,IAAI,CAAC;QAEvD,0BAA0B;QAC1B,MAAM,KAAK,GAAG,SAAS,CAAC,KAAK,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;QAClD,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACrB,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YACpC,YAAY,CAAC,GAAG,CAAC,WAAW,EAAE,KAAK,CAAC,YAAY,CAAC,CAAC;QACpD,CAAC;IACH,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,gFAAgF;AAChF,yBAAyB;AACzB,gFAAgF;AAEhF;;GAEG;AACH,SAAS,aAAa,CACpB,KAAU,EACV,YAA0B,EAC1B,gBAAqC;IAErC,4BAA4B;IAC5B,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,OAAO,YAAY,CAAC,KAAK,EAAE,YAAY,EAAE,gBAAgB,CAAC,CAAC;IAC7D,CAAC;IAED,+BAA+B;IAC/B,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CACxB,aAAa,CAAC,IAAI,EAAE,YAAY,EAAE,gBAAgB,CAAC,CACpD,CAAC;IACJ,CAAC;IAED,iCAAiC;IACjC,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAChD,MAAM,SAAS,GAAQ,EAAE,CAAC;QAC1B,KAAK,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YAC/C,SAAS,CAAC,GAAG,CAAC,GAAG,aAAa,CAAC,GAAG,EAAE,YAAY,EAAE,gBAAgB,CAAC,CAAC;QACtE,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,2BAA2B;IAC3B,OAAO,KAAK,CAAC;AACf,CAAC;AAED,gFAAgF;AAChF,aAAa;AACb,gFAAgF;AAEhF;;;GAGG;AACH,MAAM,UAAU,QAAQ,CAAC,OAAY;IACnC,MAAM,YAAY,GAAiB,IAAI,GAAG,EAAE,CAAC;IAC7C,MAAM,gBAAgB,GAAG,IAAI,GAAG,EAAkB,CAAC;IAEnD,MAAM,SAAS,GAAG,aAAa,CAAC,OAAO,EAAE,YAAY,EAAE,gBAAgB,CAAC,CAAC;IAEzE,OAAO;QACL,SAAS;QACT,YAAY;QACZ,cAAc,EAAE,YAAY,CAAC,IAAI;KAClC,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,QAAe;IAC9C,OAAO,QAAQ,CAAC,QAAQ,CAAC,CAAC;AAC5B,CAAC"}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * AI Security Gateway types
3
+ */
4
+ export type MappingTable = Map<string, string>;
5
+ export type SanitizeResult = {
6
+ sanitized: any;
7
+ mappingTable: MappingTable;
8
+ redactionCount: number;
9
+ };
10
+ export type GatewayConfig = {
11
+ port: number;
12
+ backends: {
13
+ anthropic?: {
14
+ baseUrl: string;
15
+ apiKey: string;
16
+ };
17
+ openai?: {
18
+ baseUrl: string;
19
+ apiKey: string;
20
+ };
21
+ gemini?: {
22
+ baseUrl: string;
23
+ apiKey: string;
24
+ };
25
+ };
26
+ routing?: {
27
+ [path: string]: keyof GatewayConfig["backends"];
28
+ };
29
+ };
30
+ export type EntityMatch = {
31
+ originalText: string;
32
+ category: string;
33
+ placeholder: string;
34
+ };
35
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,MAAM,MAAM,YAAY,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAG/C,MAAM,MAAM,cAAc,GAAG;IAC3B,SAAS,EAAE,GAAG,CAAC;IACf,YAAY,EAAE,YAAY,CAAC;IAC3B,cAAc,EAAE,MAAM,CAAC;CACxB,CAAC;AAGF,MAAM,MAAM,aAAa,GAAG;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE;QACR,SAAS,CAAC,EAAE;YACV,OAAO,EAAE,MAAM,CAAC;YAChB,MAAM,EAAE,MAAM,CAAC;SAChB,CAAC;QACF,MAAM,CAAC,EAAE;YACP,OAAO,EAAE,MAAM,CAAC;YAChB,MAAM,EAAE,MAAM,CAAC;SAChB,CAAC;QACF,MAAM,CAAC,EAAE;YACP,OAAO,EAAE,MAAM,CAAC;YAChB,MAAM,EAAE,MAAM,CAAC;SAChB,CAAC;KACH,CAAC;IAEF,OAAO,CAAC,EAAE;QACR,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,aAAa,CAAC,UAAU,CAAC,CAAC;KACjD,CAAC;CACH,CAAC;AAGF,MAAM,MAAM,WAAW,GAAG;IACxB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC"}
package/dist/types.js ADDED
@@ -0,0 +1,5 @@
1
+ /**
2
+ * AI Security Gateway types
3
+ */
4
+ export {};
5
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG"}
package/package.json ADDED
@@ -0,0 +1,55 @@
1
+ {
2
+ "name": "@openguardrails/gateway",
3
+ "version": "1.0.0",
4
+ "description": "AI Security Gateway — secure proxy for LLM APIs with PII sanitization, credential detection, and content security",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "bin": {
9
+ "og-gateway": "./dist/index.js"
10
+ },
11
+ "scripts": {
12
+ "build": "tsc",
13
+ "dev": "tsx src/index.ts",
14
+ "start": "node dist/index.js",
15
+ "typecheck": "tsc --noEmit",
16
+ "test": "tsx test/sanitizer.test.ts"
17
+ },
18
+ "keywords": [
19
+ "ai-security",
20
+ "ai-gateway",
21
+ "llm-proxy",
22
+ "pii-sanitization",
23
+ "credential-detection",
24
+ "openguardrails",
25
+ "anthropic",
26
+ "openai",
27
+ "gemini"
28
+ ],
29
+ "author": "OpenGuardrails",
30
+ "license": "Apache-2.0",
31
+ "publishConfig": {
32
+ "access": "public"
33
+ },
34
+ "repository": {
35
+ "type": "git",
36
+ "url": "git+https://github.com/openguardrails/openguardrails.git",
37
+ "directory": "gateway"
38
+ },
39
+ "bugs": {
40
+ "url": "https://github.com/openguardrails/openguardrails/issues"
41
+ },
42
+ "homepage": "https://github.com/openguardrails/openguardrails/tree/main/gateway#readme",
43
+ "files": [
44
+ "dist/",
45
+ "src/"
46
+ ],
47
+ "devDependencies": {
48
+ "@types/node": "^22.0.0",
49
+ "tsx": "^4.0.0",
50
+ "typescript": "^5.6.0"
51
+ },
52
+ "engines": {
53
+ "node": ">=22.0.0"
54
+ }
55
+ }