contextguard 0.1.7 → 0.2.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/LICENSE +23 -17
- package/README.md +157 -109
- package/dist/agent.d.ts +24 -0
- package/dist/agent.js +369 -0
- package/dist/cli.d.ts +11 -0
- package/dist/cli.js +266 -0
- package/dist/config.d.ts +23 -0
- package/dist/config.js +56 -0
- package/dist/database.d.ts +116 -0
- package/dist/database.js +291 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.js +18 -0
- package/dist/init.d.ts +7 -0
- package/dist/init.js +173 -0
- package/dist/lib/supabase-client.d.ts +27 -0
- package/dist/lib/supabase-client.js +97 -0
- package/dist/logger.d.ts +36 -0
- package/dist/logger.js +145 -0
- package/dist/mcp-security-wrapper.d.ts +84 -0
- package/dist/mcp-security-wrapper.js +394 -120
- package/dist/mcp-traceability-integration.d.ts +118 -0
- package/dist/mcp-traceability-integration.js +302 -0
- package/dist/policy.d.ts +30 -0
- package/dist/policy.js +273 -0
- package/dist/premium-features.d.ts +364 -0
- package/dist/premium-features.js +950 -0
- package/dist/security-logger.d.ts +45 -0
- package/dist/security-logger.js +125 -0
- package/dist/security-policy.d.ts +55 -0
- package/dist/security-policy.js +140 -0
- package/dist/semantic-detector.d.ts +21 -0
- package/dist/semantic-detector.js +49 -0
- package/dist/sse-proxy.d.ts +21 -0
- package/dist/sse-proxy.js +276 -0
- package/dist/supabase-client.d.ts +27 -0
- package/dist/supabase-client.js +89 -0
- package/dist/types/database.types.d.ts +220 -0
- package/dist/types/database.types.js +8 -0
- package/dist/types/mcp.d.ts +27 -0
- package/dist/types/mcp.js +15 -0
- package/dist/types/types.d.ts +65 -0
- package/dist/types/types.js +8 -0
- package/dist/types.d.ts +84 -0
- package/dist/types.js +8 -0
- package/dist/wrapper.d.ts +115 -0
- package/dist/wrapper.js +417 -0
- package/package.json +35 -10
- package/.github/ISSUE_TEMPLATE/bug_report.md +0 -57
- package/CONTRIBUTING.md +0 -532
- package/SECURITY.md +0 -254
- package/assets/demo.mp4 +0 -0
- package/eslint.config.mts +0 -23
- package/examples/config/config.json +0 -19
- package/examples/mcp-server/demo.js +0 -228
- package/examples/mcp-server/package-lock.json +0 -978
- package/examples/mcp-server/package.json +0 -16
- package/examples/mcp-server/pnpm-lock.yaml +0 -745
- package/src/mcp-security-wrapper.ts +0 -529
- package/test/test-server.ts +0 -295
- package/tsconfig.json +0 -16
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Copyright (c) 2026 Amir Mironi
|
|
4
|
+
*
|
|
5
|
+
* This source code is licensed under the MIT license found in the
|
|
6
|
+
* LICENSE file in the root directory of this source tree.
|
|
7
|
+
*/
|
|
8
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
9
|
+
if (k2 === undefined) k2 = k;
|
|
10
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
11
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
12
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
13
|
+
}
|
|
14
|
+
Object.defineProperty(o, k2, desc);
|
|
15
|
+
}) : (function(o, m, k, k2) {
|
|
16
|
+
if (k2 === undefined) k2 = k;
|
|
17
|
+
o[k2] = m[k];
|
|
18
|
+
}));
|
|
19
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
20
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
21
|
+
}) : function(o, v) {
|
|
22
|
+
o["default"] = v;
|
|
23
|
+
});
|
|
24
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
25
|
+
var ownKeys = function(o) {
|
|
26
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
27
|
+
var ar = [];
|
|
28
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
29
|
+
return ar;
|
|
30
|
+
};
|
|
31
|
+
return ownKeys(o);
|
|
32
|
+
};
|
|
33
|
+
return function (mod) {
|
|
34
|
+
if (mod && mod.__esModule) return mod;
|
|
35
|
+
var result = {};
|
|
36
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
37
|
+
__setModuleDefault(result, mod);
|
|
38
|
+
return result;
|
|
39
|
+
};
|
|
40
|
+
})();
|
|
41
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
42
|
+
exports.createSSEProxy = void 0;
|
|
43
|
+
const http = __importStar(require("http"));
|
|
44
|
+
const https = __importStar(require("https"));
|
|
45
|
+
const policy_1 = require("./policy");
|
|
46
|
+
const logger_1 = require("./logger");
|
|
47
|
+
const mcp_1 = require("./types/mcp");
|
|
48
|
+
/**
|
|
49
|
+
* Create an SSE/HTTP proxy for MCP servers
|
|
50
|
+
* @param policyConfig - Policy configuration
|
|
51
|
+
* @returns SSE proxy functions
|
|
52
|
+
*/
|
|
53
|
+
const createSSEProxy = (policyConfig) => {
|
|
54
|
+
const policy = (0, policy_1.createPolicyChecker)(policyConfig);
|
|
55
|
+
const logger = (0, logger_1.createLogger)(policyConfig.logPath);
|
|
56
|
+
const sessionId = (0, mcp_1.generateSessionId)();
|
|
57
|
+
let toolCallTimestamps = [];
|
|
58
|
+
/**
|
|
59
|
+
* Inspect outbound request for security violations
|
|
60
|
+
*/
|
|
61
|
+
const inspectOutbound = (message) => {
|
|
62
|
+
const violations = [];
|
|
63
|
+
let shouldBlock = false;
|
|
64
|
+
if (message.method === "tools/call") {
|
|
65
|
+
const now = Date.now();
|
|
66
|
+
toolCallTimestamps.push(now);
|
|
67
|
+
toolCallTimestamps = toolCallTimestamps.filter((t) => t > now - 60000);
|
|
68
|
+
if (!policy.checkRateLimit(toolCallTimestamps)) {
|
|
69
|
+
violations.push("Rate limit exceeded");
|
|
70
|
+
if (policy.isBlockingMode())
|
|
71
|
+
shouldBlock = true;
|
|
72
|
+
}
|
|
73
|
+
if (message.params?.name) {
|
|
74
|
+
violations.push(...policy.checkToolAccess(message.params.name));
|
|
75
|
+
}
|
|
76
|
+
const paramsStr = JSON.stringify(message.params);
|
|
77
|
+
violations.push(...policy.checkPromptInjection(paramsStr));
|
|
78
|
+
violations.push(...policy.checkSensitiveData(paramsStr));
|
|
79
|
+
violations.push(...policy.checkBlockedPatterns(paramsStr));
|
|
80
|
+
violations.push(...policy.checkSQLInjection(paramsStr));
|
|
81
|
+
violations.push(...policy.checkXSS(paramsStr));
|
|
82
|
+
violations.push(...policy.checkCustomRules(paramsStr));
|
|
83
|
+
const filePathParams = [
|
|
84
|
+
message.params?.arguments?.path,
|
|
85
|
+
message.params?.arguments?.filePath,
|
|
86
|
+
].filter((p) => typeof p === "string");
|
|
87
|
+
for (const fp of filePathParams) {
|
|
88
|
+
violations.push(...policy.checkFileAccess(fp));
|
|
89
|
+
}
|
|
90
|
+
if (violations.length > 0 && policy.isBlockingMode()) {
|
|
91
|
+
shouldBlock = true;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return { violations, shouldBlock };
|
|
95
|
+
};
|
|
96
|
+
return {
|
|
97
|
+
/**
|
|
98
|
+
* Start the SSE/HTTP proxy server
|
|
99
|
+
*/
|
|
100
|
+
start: (port, targetUrl) => {
|
|
101
|
+
const target = new URL(targetUrl);
|
|
102
|
+
const isHttps = target.protocol === "https:";
|
|
103
|
+
const server = http.createServer((clientReq, clientRes) => {
|
|
104
|
+
// ── 1. Collect request body ──────────────────────────────────────────
|
|
105
|
+
const chunks = [];
|
|
106
|
+
clientReq.on("data", (chunk) => chunks.push(chunk));
|
|
107
|
+
clientReq.on("end", () => {
|
|
108
|
+
const rawBody = Buffer.concat(chunks);
|
|
109
|
+
const bodyStr = rawBody.toString();
|
|
110
|
+
// ── 2. Inspect request ──────────────────────────────────────────────
|
|
111
|
+
let violations = [];
|
|
112
|
+
let shouldBlock = false;
|
|
113
|
+
if (bodyStr) {
|
|
114
|
+
try {
|
|
115
|
+
const msg = JSON.parse(bodyStr);
|
|
116
|
+
const result = inspectOutbound(msg);
|
|
117
|
+
violations = result.violations;
|
|
118
|
+
shouldBlock = result.shouldBlock;
|
|
119
|
+
if (violations.length > 0) {
|
|
120
|
+
logger.logEvent("SECURITY_VIOLATION", "CRITICAL", {
|
|
121
|
+
violations,
|
|
122
|
+
blocked: shouldBlock,
|
|
123
|
+
}, sessionId);
|
|
124
|
+
console.error(`\n⚠️ SECURITY VIOLATIONS DETECTED:\n${violations.join("\n")}\n`);
|
|
125
|
+
}
|
|
126
|
+
if (shouldBlock) {
|
|
127
|
+
console.error("🚫 REQUEST BLOCKED\n");
|
|
128
|
+
clientRes.writeHead(403, {
|
|
129
|
+
"Content-Type": "application/json",
|
|
130
|
+
});
|
|
131
|
+
clientRes.end(JSON.stringify({
|
|
132
|
+
jsonrpc: "2.0",
|
|
133
|
+
id: msg.id,
|
|
134
|
+
error: {
|
|
135
|
+
code: -32000,
|
|
136
|
+
message: "Security violation: Request blocked",
|
|
137
|
+
data: { violations },
|
|
138
|
+
},
|
|
139
|
+
}));
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
else if (violations.length > 0) {
|
|
143
|
+
console.error('⚠️ MONITOR MODE — request forwarded (set mode: "block" to block)\n');
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
catch {
|
|
147
|
+
// non-JSON body — forward as-is
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
// ── 3. Forward to upstream ──────────────────────────────────────────
|
|
151
|
+
const options = {
|
|
152
|
+
hostname: target.hostname,
|
|
153
|
+
port: target.port || (isHttps ? 443 : 80),
|
|
154
|
+
path: target.pathname + clientReq.url?.replace(/^[^?]*/, "") ||
|
|
155
|
+
target.pathname,
|
|
156
|
+
method: clientReq.method,
|
|
157
|
+
headers: {
|
|
158
|
+
...clientReq.headers,
|
|
159
|
+
host: target.host,
|
|
160
|
+
},
|
|
161
|
+
};
|
|
162
|
+
const lib = isHttps ? https : http;
|
|
163
|
+
const proxyReq = lib.request(options, (proxyRes) => {
|
|
164
|
+
const isSSE = proxyRes.headers["content-type"]?.includes("text/event-stream");
|
|
165
|
+
clientRes.writeHead(proxyRes.statusCode || 200, proxyRes.headers);
|
|
166
|
+
if (isSSE) {
|
|
167
|
+
// Stream SSE events, scanning each data line
|
|
168
|
+
let sseBuffer = "";
|
|
169
|
+
proxyRes.on("data", (chunk) => {
|
|
170
|
+
sseBuffer += chunk.toString();
|
|
171
|
+
const lines = sseBuffer.split("\n");
|
|
172
|
+
sseBuffer = lines.pop() || "";
|
|
173
|
+
for (const line of lines) {
|
|
174
|
+
if (line.startsWith("data:")) {
|
|
175
|
+
const data = line.slice(5).trim();
|
|
176
|
+
try {
|
|
177
|
+
const msg = JSON.parse(data);
|
|
178
|
+
const leakViolations = policy.checkSensitiveData(JSON.stringify(msg.result || msg));
|
|
179
|
+
if (leakViolations.length > 0) {
|
|
180
|
+
logger.logEvent("SENSITIVE_DATA_LEAK", "CRITICAL", {
|
|
181
|
+
violations: leakViolations,
|
|
182
|
+
}, sessionId);
|
|
183
|
+
console.error(`\n🚨 SENSITIVE DATA IN SSE STREAM:\n${leakViolations.join("\n")}\n`);
|
|
184
|
+
if (policy.isBlockingMode()) {
|
|
185
|
+
// Replace event with error event
|
|
186
|
+
clientRes.write(`data: ${JSON.stringify({
|
|
187
|
+
jsonrpc: "2.0",
|
|
188
|
+
id: msg.id,
|
|
189
|
+
error: {
|
|
190
|
+
code: -32001,
|
|
191
|
+
message: "Sensitive data blocked",
|
|
192
|
+
},
|
|
193
|
+
})}\n\n`);
|
|
194
|
+
continue;
|
|
195
|
+
}
|
|
196
|
+
else {
|
|
197
|
+
console.error("⚠️ MONITOR MODE — event forwarded\n");
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
catch {
|
|
202
|
+
/* non-JSON SSE data */
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
clientRes.write(line + "\n");
|
|
206
|
+
}
|
|
207
|
+
});
|
|
208
|
+
proxyRes.on("end", () => {
|
|
209
|
+
if (sseBuffer)
|
|
210
|
+
clientRes.write(sseBuffer);
|
|
211
|
+
clientRes.end();
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
else {
|
|
215
|
+
// Regular HTTP — collect response, scan, forward
|
|
216
|
+
const resChunks = [];
|
|
217
|
+
proxyRes.on("data", (chunk) => resChunks.push(chunk));
|
|
218
|
+
proxyRes.on("end", () => {
|
|
219
|
+
const resBody = Buffer.concat(resChunks).toString();
|
|
220
|
+
try {
|
|
221
|
+
const msg = JSON.parse(resBody);
|
|
222
|
+
const leakViolations = policy.checkSensitiveData(JSON.stringify(msg.result || msg));
|
|
223
|
+
if (leakViolations.length > 0) {
|
|
224
|
+
logger.logEvent("SENSITIVE_DATA_LEAK", "CRITICAL", {
|
|
225
|
+
violations: leakViolations,
|
|
226
|
+
}, sessionId);
|
|
227
|
+
console.error(`\n🚨 SENSITIVE DATA IN RESPONSE:\n${leakViolations.join("\n")}\n`);
|
|
228
|
+
if (policy.isBlockingMode() && msg.id !== undefined) {
|
|
229
|
+
console.error("🚫 RESPONSE BLOCKED\n");
|
|
230
|
+
clientRes.end(JSON.stringify({
|
|
231
|
+
jsonrpc: "2.0",
|
|
232
|
+
id: msg.id,
|
|
233
|
+
error: {
|
|
234
|
+
code: -32001,
|
|
235
|
+
message: "Sensitive data blocked",
|
|
236
|
+
},
|
|
237
|
+
}));
|
|
238
|
+
return;
|
|
239
|
+
}
|
|
240
|
+
else {
|
|
241
|
+
console.error("⚠️ MONITOR MODE — response forwarded\n");
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
catch {
|
|
246
|
+
/* non-JSON */
|
|
247
|
+
}
|
|
248
|
+
clientRes.end(resBody);
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
});
|
|
252
|
+
proxyReq.on("error", (err) => {
|
|
253
|
+
logger.logEvent("PROXY_ERROR", "HIGH", { error: err.message }, sessionId);
|
|
254
|
+
clientRes.writeHead(502);
|
|
255
|
+
clientRes.end("Bad Gateway");
|
|
256
|
+
});
|
|
257
|
+
if (rawBody.length > 0)
|
|
258
|
+
proxyReq.write(rawBody);
|
|
259
|
+
proxyReq.end();
|
|
260
|
+
});
|
|
261
|
+
});
|
|
262
|
+
server.listen(port, () => {
|
|
263
|
+
logger.logEvent("SSE_PROXY_START", "LOW", {
|
|
264
|
+
port,
|
|
265
|
+
targetUrl,
|
|
266
|
+
mode: policy.getConfig().mode,
|
|
267
|
+
}, sessionId);
|
|
268
|
+
console.error(`🛡️ ContextGuard SSE/HTTP proxy listening on port ${port}`);
|
|
269
|
+
console.error(` → Forwarding to: ${targetUrl}`);
|
|
270
|
+
console.error(` → Mode: ${policy.getConfig().mode}\n`);
|
|
271
|
+
});
|
|
272
|
+
},
|
|
273
|
+
getLogger: () => logger,
|
|
274
|
+
};
|
|
275
|
+
};
|
|
276
|
+
exports.createSSEProxy = createSSEProxy;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Amir Mironi
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
import { SecurityEvent } from "./types";
|
|
8
|
+
/**
|
|
9
|
+
* Supabase configuration
|
|
10
|
+
*/
|
|
11
|
+
export interface SupabaseConfig {
|
|
12
|
+
url: string;
|
|
13
|
+
serviceKey: string;
|
|
14
|
+
agentId?: string;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Supabase client for agent-dashboard communication
|
|
18
|
+
*/
|
|
19
|
+
export interface SupabaseClient {
|
|
20
|
+
reportEvent: (event: SecurityEvent) => Promise<void>;
|
|
21
|
+
fetchPolicy: (agentId: string) => Promise<any>;
|
|
22
|
+
updateAgentStatus: (agentId: string, status: string) => Promise<void>;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Create a Supabase client
|
|
26
|
+
*/
|
|
27
|
+
export declare const createSupabaseClient: (config: SupabaseConfig) => SupabaseClient;
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Copyright (c) 2025 Amir Mironi
|
|
4
|
+
*
|
|
5
|
+
* This source code is licensed under the MIT license found in the
|
|
6
|
+
* LICENSE file in the root directory of this source tree.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.createSupabaseClient = void 0;
|
|
10
|
+
/**
|
|
11
|
+
* Create a Supabase client
|
|
12
|
+
*/
|
|
13
|
+
const createSupabaseClient = (config) => {
|
|
14
|
+
const { url, serviceKey } = config;
|
|
15
|
+
/**
|
|
16
|
+
* Make a request to Supabase REST API
|
|
17
|
+
*/
|
|
18
|
+
const makeRequest = async (method, path, body) => {
|
|
19
|
+
const response = await fetch(`${url}/rest/v1${path}`, {
|
|
20
|
+
method,
|
|
21
|
+
headers: {
|
|
22
|
+
"Content-Type": "application/json",
|
|
23
|
+
apikey: serviceKey,
|
|
24
|
+
Authorization: `Bearer ${serviceKey}`,
|
|
25
|
+
Prefer: "return=representation",
|
|
26
|
+
},
|
|
27
|
+
body: body ? JSON.stringify(body) : undefined,
|
|
28
|
+
});
|
|
29
|
+
if (!response.ok) {
|
|
30
|
+
const error = await response.text();
|
|
31
|
+
throw new Error(`Supabase request failed: ${error}`);
|
|
32
|
+
}
|
|
33
|
+
const text = await response.text();
|
|
34
|
+
return text ? JSON.parse(text) : null;
|
|
35
|
+
};
|
|
36
|
+
return {
|
|
37
|
+
/**
|
|
38
|
+
* Report a security event to Supabase
|
|
39
|
+
*/
|
|
40
|
+
reportEvent: async (event) => {
|
|
41
|
+
try {
|
|
42
|
+
await makeRequest("POST", "/security_events", {
|
|
43
|
+
agent_id: config.agentId,
|
|
44
|
+
event_type: event.eventType,
|
|
45
|
+
severity: event.severity,
|
|
46
|
+
details: event.details,
|
|
47
|
+
session_id: event.sessionId,
|
|
48
|
+
timestamp: event.timestamp,
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
catch (error) {
|
|
52
|
+
console.error("Failed to report event to Supabase:", error);
|
|
53
|
+
// Don't throw - we don't want to break the agent if reporting fails
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
/**
|
|
57
|
+
* Fetch policy configuration for an agent
|
|
58
|
+
*/
|
|
59
|
+
fetchPolicy: async (agentId) => {
|
|
60
|
+
try {
|
|
61
|
+
const result = await makeRequest("GET", `/agent_policies?agent_id=eq.${agentId}&select=*&limit=1`);
|
|
62
|
+
if (result && result.length > 0) {
|
|
63
|
+
return result[0].policy;
|
|
64
|
+
}
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
catch (error) {
|
|
68
|
+
console.error("Failed to fetch policy from Supabase:", error);
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
},
|
|
72
|
+
/**
|
|
73
|
+
* Update agent status
|
|
74
|
+
*/
|
|
75
|
+
updateAgentStatus: async (agentId, status) => {
|
|
76
|
+
try {
|
|
77
|
+
await makeRequest("POST", "/agent_status", {
|
|
78
|
+
agent_id: agentId,
|
|
79
|
+
status,
|
|
80
|
+
last_seen: new Date().toISOString(),
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
catch (error) {
|
|
84
|
+
console.error("Failed to update agent status:", error);
|
|
85
|
+
}
|
|
86
|
+
},
|
|
87
|
+
};
|
|
88
|
+
};
|
|
89
|
+
exports.createSupabaseClient = createSupabaseClient;
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2026 Amir Mironi
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
export type SecuritySeverity = "LOW" | "MEDIUM" | "HIGH" | "CRITICAL";
|
|
8
|
+
export interface Database {
|
|
9
|
+
public: {
|
|
10
|
+
Tables: {
|
|
11
|
+
policies: {
|
|
12
|
+
Row: {
|
|
13
|
+
id: string;
|
|
14
|
+
agent_id: string;
|
|
15
|
+
maxToolCallsPerMinute?: number;
|
|
16
|
+
blockedPatterns?: string[];
|
|
17
|
+
allowedFilePaths?: string[];
|
|
18
|
+
alertThreshold?: number;
|
|
19
|
+
enablePromptInjectionDetection?: boolean;
|
|
20
|
+
enableSensitiveDataDetection?: boolean;
|
|
21
|
+
enablePathTraversalPrevention?: boolean;
|
|
22
|
+
mode?: "monitor" | "block";
|
|
23
|
+
logPath?: string;
|
|
24
|
+
enableProFeatures?: boolean;
|
|
25
|
+
licenseFilePath?: string;
|
|
26
|
+
transport?: "stdio" | "sse" | "http";
|
|
27
|
+
port?: number;
|
|
28
|
+
targetUrl?: string;
|
|
29
|
+
allowedTools?: string[];
|
|
30
|
+
blockedTools?: string[];
|
|
31
|
+
alertWebhook?: string;
|
|
32
|
+
alertOnSeverity?: string[];
|
|
33
|
+
enableSQLInjectionDetection?: boolean;
|
|
34
|
+
enableSemanticDetection?: boolean;
|
|
35
|
+
enableXSSDetection?: boolean;
|
|
36
|
+
customRules?: Array<{
|
|
37
|
+
name: string;
|
|
38
|
+
pattern: string;
|
|
39
|
+
severity?: string;
|
|
40
|
+
}>;
|
|
41
|
+
created_at: string;
|
|
42
|
+
updated_at: string;
|
|
43
|
+
};
|
|
44
|
+
Insert: {
|
|
45
|
+
id?: string;
|
|
46
|
+
agent_id: string;
|
|
47
|
+
maxToolCallsPerMinute?: number;
|
|
48
|
+
blockedPatterns?: string[];
|
|
49
|
+
allowedFilePaths?: string[];
|
|
50
|
+
alertThreshold?: number;
|
|
51
|
+
enablePromptInjectionDetection?: boolean;
|
|
52
|
+
enableSensitiveDataDetection?: boolean;
|
|
53
|
+
enablePathTraversalPrevention?: boolean;
|
|
54
|
+
mode?: "monitor" | "block";
|
|
55
|
+
logPath?: string;
|
|
56
|
+
enableProFeatures?: boolean;
|
|
57
|
+
licenseFilePath?: string;
|
|
58
|
+
transport?: "stdio" | "sse" | "http";
|
|
59
|
+
port?: number;
|
|
60
|
+
targetUrl?: string;
|
|
61
|
+
allowedTools?: string[];
|
|
62
|
+
blockedTools?: string[];
|
|
63
|
+
alertWebhook?: string;
|
|
64
|
+
alertOnSeverity?: string[];
|
|
65
|
+
enableSQLInjectionDetection?: boolean;
|
|
66
|
+
enableSemanticDetection?: boolean;
|
|
67
|
+
enableXSSDetection?: boolean;
|
|
68
|
+
customRules?: Array<{
|
|
69
|
+
name: string;
|
|
70
|
+
pattern: string;
|
|
71
|
+
severity?: string;
|
|
72
|
+
}>;
|
|
73
|
+
created_at?: string;
|
|
74
|
+
updated_at?: string;
|
|
75
|
+
};
|
|
76
|
+
Update: {
|
|
77
|
+
id?: string;
|
|
78
|
+
agent_id?: string;
|
|
79
|
+
maxToolCallsPerMinute?: number;
|
|
80
|
+
blockedPatterns?: string[];
|
|
81
|
+
allowedFilePaths?: string[];
|
|
82
|
+
alertThreshold?: number;
|
|
83
|
+
enablePromptInjectionDetection?: boolean;
|
|
84
|
+
enableSensitiveDataDetection?: boolean;
|
|
85
|
+
enablePathTraversalPrevention?: boolean;
|
|
86
|
+
mode?: "monitor" | "block";
|
|
87
|
+
logPath?: string;
|
|
88
|
+
enableProFeatures?: boolean;
|
|
89
|
+
licenseFilePath?: string;
|
|
90
|
+
transport?: "stdio" | "sse" | "http";
|
|
91
|
+
port?: number;
|
|
92
|
+
targetUrl?: string;
|
|
93
|
+
allowedTools?: string[];
|
|
94
|
+
blockedTools?: string[];
|
|
95
|
+
alertWebhook?: string;
|
|
96
|
+
alertOnSeverity?: string[];
|
|
97
|
+
enableSQLInjectionDetection?: boolean;
|
|
98
|
+
enableSemanticDetection?: boolean;
|
|
99
|
+
enableXSSDetection?: boolean;
|
|
100
|
+
customRules?: Array<{
|
|
101
|
+
name: string;
|
|
102
|
+
pattern: string;
|
|
103
|
+
severity?: string;
|
|
104
|
+
}>;
|
|
105
|
+
created_at?: string;
|
|
106
|
+
updated_at?: string;
|
|
107
|
+
};
|
|
108
|
+
};
|
|
109
|
+
events: {
|
|
110
|
+
Row: {
|
|
111
|
+
id: string;
|
|
112
|
+
agent_id: string;
|
|
113
|
+
session_id: string;
|
|
114
|
+
event_type: string;
|
|
115
|
+
severity: SecuritySeverity;
|
|
116
|
+
details: Record<string, unknown>;
|
|
117
|
+
timestamp: string;
|
|
118
|
+
created_at: string;
|
|
119
|
+
};
|
|
120
|
+
Insert: {
|
|
121
|
+
id?: string;
|
|
122
|
+
agent_id: string;
|
|
123
|
+
session_id: string;
|
|
124
|
+
event_type: string;
|
|
125
|
+
severity: SecuritySeverity;
|
|
126
|
+
details: Record<string, unknown>;
|
|
127
|
+
timestamp: string;
|
|
128
|
+
created_at?: string;
|
|
129
|
+
};
|
|
130
|
+
Update: {
|
|
131
|
+
id?: string;
|
|
132
|
+
agent_id?: string;
|
|
133
|
+
session_id?: string;
|
|
134
|
+
event_type?: string;
|
|
135
|
+
severity?: SecuritySeverity;
|
|
136
|
+
details?: Record<string, unknown>;
|
|
137
|
+
timestamp?: string;
|
|
138
|
+
created_at?: string;
|
|
139
|
+
};
|
|
140
|
+
};
|
|
141
|
+
agents: {
|
|
142
|
+
Row: {
|
|
143
|
+
id: string;
|
|
144
|
+
agent_id: string;
|
|
145
|
+
status: AgentStatus;
|
|
146
|
+
last_seen: string;
|
|
147
|
+
created_at: string;
|
|
148
|
+
updated_at: string;
|
|
149
|
+
};
|
|
150
|
+
Insert: {
|
|
151
|
+
id?: string;
|
|
152
|
+
agent_id: string;
|
|
153
|
+
status: AgentStatus;
|
|
154
|
+
last_seen: string;
|
|
155
|
+
created_at?: string;
|
|
156
|
+
updated_at?: string;
|
|
157
|
+
};
|
|
158
|
+
Update: {
|
|
159
|
+
id?: string;
|
|
160
|
+
agent_id?: string;
|
|
161
|
+
status?: AgentStatus;
|
|
162
|
+
last_seen?: string;
|
|
163
|
+
created_at?: string;
|
|
164
|
+
updated_at?: string;
|
|
165
|
+
};
|
|
166
|
+
};
|
|
167
|
+
};
|
|
168
|
+
Views: {
|
|
169
|
+
event_statistics: {
|
|
170
|
+
Row: {
|
|
171
|
+
agent_id: string;
|
|
172
|
+
event_type: string;
|
|
173
|
+
severity: SecuritySeverity;
|
|
174
|
+
count: number;
|
|
175
|
+
hour: string;
|
|
176
|
+
};
|
|
177
|
+
};
|
|
178
|
+
};
|
|
179
|
+
Functions: {
|
|
180
|
+
cleanup_old_events: {
|
|
181
|
+
Args: {
|
|
182
|
+
days_to_keep?: number;
|
|
183
|
+
};
|
|
184
|
+
Returns: number;
|
|
185
|
+
};
|
|
186
|
+
};
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Agent status types
|
|
191
|
+
*/
|
|
192
|
+
export type AgentStatus = "online" | "offline" | "error";
|
|
193
|
+
/**
|
|
194
|
+
* Security event from database
|
|
195
|
+
*/
|
|
196
|
+
export type SecurityEventRow = Database["public"]["Tables"]["events"]["Row"];
|
|
197
|
+
/**
|
|
198
|
+
* Agent policy from database
|
|
199
|
+
*/
|
|
200
|
+
export type AgentPolicyRow = Database["public"]["Tables"]["policies"]["Row"];
|
|
201
|
+
/**
|
|
202
|
+
* Agent status from database
|
|
203
|
+
*/
|
|
204
|
+
export type AgentStatusRow = Database["public"]["Tables"]["agents"]["Row"];
|
|
205
|
+
/**
|
|
206
|
+
* Event statistics from view
|
|
207
|
+
*/
|
|
208
|
+
export type EventStatisticsRow = Database["public"]["Views"]["event_statistics"]["Row"];
|
|
209
|
+
/**
|
|
210
|
+
* Insert types for convenience
|
|
211
|
+
*/
|
|
212
|
+
export type SecurityEventInsert = Database["public"]["Tables"]["events"]["Insert"];
|
|
213
|
+
export type AgentPolicyInsert = Database["public"]["Tables"]["policies"]["Insert"];
|
|
214
|
+
export type AgentStatusInsert = Database["public"]["Tables"]["agents"]["Insert"];
|
|
215
|
+
/**
|
|
216
|
+
* Update types for convenience
|
|
217
|
+
*/
|
|
218
|
+
export type SecurityEventUpdate = Database["public"]["Tables"]["events"]["Update"];
|
|
219
|
+
export type AgentPolicyUpdate = Database["public"]["Tables"]["policies"]["Update"];
|
|
220
|
+
export type AgentStatusUpdate = Database["public"]["Tables"]["agents"]["Update"];
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2026 Amir Mironi
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* MCP JSON-RPC message structure
|
|
9
|
+
*/
|
|
10
|
+
export interface MCPMessage {
|
|
11
|
+
jsonrpc: string;
|
|
12
|
+
id?: string | number;
|
|
13
|
+
method?: string;
|
|
14
|
+
params?: {
|
|
15
|
+
name?: string;
|
|
16
|
+
arguments?: Record<string, string>;
|
|
17
|
+
path?: string;
|
|
18
|
+
filePath?: string;
|
|
19
|
+
[key: string]: unknown;
|
|
20
|
+
};
|
|
21
|
+
result?: unknown;
|
|
22
|
+
error?: unknown;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Generate a unique session ID
|
|
26
|
+
*/
|
|
27
|
+
export declare const generateSessionId: () => string;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Copyright (c) 2026 Amir Mironi
|
|
4
|
+
*
|
|
5
|
+
* This source code is licensed under the MIT license found in the
|
|
6
|
+
* LICENSE file in the root directory of this source tree.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.generateSessionId = void 0;
|
|
10
|
+
const crypto_1 = require("crypto");
|
|
11
|
+
/**
|
|
12
|
+
* Generate a unique session ID
|
|
13
|
+
*/
|
|
14
|
+
const generateSessionId = () => (0, crypto_1.createHash)("md5").update(Date.now().toString()).digest("hex").substring(0, 8);
|
|
15
|
+
exports.generateSessionId = generateSessionId;
|