agentshield-sdk 7.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 (84) hide show
  1. package/CHANGELOG.md +191 -0
  2. package/LICENSE +21 -0
  3. package/README.md +975 -0
  4. package/bin/agent-shield.js +680 -0
  5. package/package.json +118 -0
  6. package/src/adaptive.js +330 -0
  7. package/src/agent-protocol.js +998 -0
  8. package/src/alert-tuning.js +480 -0
  9. package/src/allowlist.js +603 -0
  10. package/src/audit-immutable.js +914 -0
  11. package/src/audit-streaming.js +469 -0
  12. package/src/badges.js +196 -0
  13. package/src/behavior-profiling.js +289 -0
  14. package/src/benchmark-harness.js +804 -0
  15. package/src/canary.js +271 -0
  16. package/src/certification.js +563 -0
  17. package/src/circuit-breaker.js +321 -0
  18. package/src/compliance.js +617 -0
  19. package/src/confidence-tuning.js +324 -0
  20. package/src/confused-deputy.js +624 -0
  21. package/src/context-scoring.js +360 -0
  22. package/src/conversation.js +494 -0
  23. package/src/cost-optimizer.js +1024 -0
  24. package/src/ctf.js +462 -0
  25. package/src/detector-core.js +1999 -0
  26. package/src/distributed.js +359 -0
  27. package/src/document-scanner.js +795 -0
  28. package/src/embedding.js +307 -0
  29. package/src/encoding.js +429 -0
  30. package/src/enterprise.js +405 -0
  31. package/src/errors.js +100 -0
  32. package/src/eu-ai-act.js +523 -0
  33. package/src/fuzzer.js +764 -0
  34. package/src/honeypot.js +328 -0
  35. package/src/i18n-patterns.js +523 -0
  36. package/src/index.js +430 -0
  37. package/src/integrations.js +528 -0
  38. package/src/llm-redteam.js +670 -0
  39. package/src/main.js +741 -0
  40. package/src/main.mjs +38 -0
  41. package/src/mcp-bridge.js +542 -0
  42. package/src/mcp-certification.js +846 -0
  43. package/src/mcp-sdk-integration.js +355 -0
  44. package/src/mcp-security-runtime.js +741 -0
  45. package/src/mcp-server.js +740 -0
  46. package/src/middleware.js +208 -0
  47. package/src/model-finetuning.js +884 -0
  48. package/src/model-fingerprint.js +1042 -0
  49. package/src/multi-agent-trust.js +453 -0
  50. package/src/multi-agent.js +404 -0
  51. package/src/multimodal.js +296 -0
  52. package/src/nist-mapping.js +505 -0
  53. package/src/observability.js +330 -0
  54. package/src/openclaw.js +450 -0
  55. package/src/otel.js +544 -0
  56. package/src/owasp-2025.js +483 -0
  57. package/src/pii.js +390 -0
  58. package/src/plugin-marketplace.js +628 -0
  59. package/src/plugin-system.js +349 -0
  60. package/src/policy-dsl.js +775 -0
  61. package/src/policy-extended.js +635 -0
  62. package/src/policy.js +443 -0
  63. package/src/presets.js +409 -0
  64. package/src/production.js +557 -0
  65. package/src/prompt-leakage.js +321 -0
  66. package/src/rag-vulnerability.js +579 -0
  67. package/src/redteam.js +475 -0
  68. package/src/response-handler.js +429 -0
  69. package/src/scanners.js +357 -0
  70. package/src/self-healing.js +363 -0
  71. package/src/semantic.js +339 -0
  72. package/src/shield-score.js +250 -0
  73. package/src/sso-saml.js +897 -0
  74. package/src/stream-scanner.js +806 -0
  75. package/src/testing.js +505 -0
  76. package/src/threat-encyclopedia.js +629 -0
  77. package/src/threat-intel-network.js +1017 -0
  78. package/src/token-analysis.js +467 -0
  79. package/src/tool-guard.js +412 -0
  80. package/src/tool-output-validator.js +354 -0
  81. package/src/utils.js +83 -0
  82. package/src/watermark.js +235 -0
  83. package/src/worker-scanner.js +601 -0
  84. package/types/index.d.ts +2088 -0
@@ -0,0 +1,355 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * Agent Shield — Official MCP SDK Integration
5
+ *
6
+ * Drop-in security for any MCP server built with @modelcontextprotocol/sdk.
7
+ * Wraps the standard Server class to add threat scanning, authorization,
8
+ * behavioral monitoring, and audit logging — with zero configuration required.
9
+ *
10
+ * Works with @modelcontextprotocol/sdk v1.x and v2.x.
11
+ *
12
+ * Usage (3 lines):
13
+ *
14
+ * const { Server } = require('@modelcontextprotocol/sdk/server/index.js');
15
+ * const { shieldMCPServer } = require('agent-shield');
16
+ *
17
+ * const server = shieldMCPServer(new Server({ name: 'my-server', version: '1.0' }));
18
+ * // All tool calls are now scanned. Injections blocked. Audit trail created.
19
+ *
20
+ * Advanced usage with MCPSecurityRuntime:
21
+ *
22
+ * const server = shieldMCPServer(new Server({ ... }), {
23
+ * signingKey: process.env.SHIELD_KEY,
24
+ * enforceAuth: true,
25
+ * enableBehaviorMonitoring: true,
26
+ * onThreat: (event) => alertSecurityTeam(event),
27
+ * tools: {
28
+ * 'database_query': { scopes: ['db:read'], roles: ['analyst'] },
29
+ * 'file_delete': { scopes: ['fs:write'], roles: ['admin'], requiresHumanApproval: true }
30
+ * }
31
+ * });
32
+ *
33
+ * All processing runs locally — no data ever leaves your environment.
34
+ */
35
+
36
+ const { scanText } = require('./detector-core');
37
+ const { MCPSecurityRuntime } = require('./mcp-security-runtime');
38
+
39
+ const LOG_PREFIX = '[Agent Shield]';
40
+
41
+ /**
42
+ * Wraps a @modelcontextprotocol/sdk Server with Agent Shield security.
43
+ *
44
+ * Intercepts tools/call requests to scan arguments for injection attacks,
45
+ * scans tool results before returning, and maintains an audit trail.
46
+ *
47
+ * @param {object} server - @modelcontextprotocol/sdk Server instance
48
+ * @param {object} [options]
49
+ * @param {string} [options.signingKey] - HMAC key for auth context signing
50
+ * @param {boolean} [options.enforceAuth=false] - Require per-user auth (advanced)
51
+ * @param {boolean} [options.enableBehaviorMonitoring=true] - Track behavioral anomalies
52
+ * @param {boolean} [options.scanInputs=true] - Scan tool call arguments
53
+ * @param {boolean} [options.scanOutputs=true] - Scan tool results
54
+ * @param {string} [options.sensitivity='medium'] - Detection sensitivity
55
+ * @param {boolean} [options.blockOnThreat=true] - Block tool calls with detected threats
56
+ * @param {Function} [options.onThreat] - Callback when threat detected
57
+ * @param {Function} [options.onBlock] - Callback when tool call blocked
58
+ * @param {object} [options.tools] - Per-tool security requirements
59
+ * @returns {object} The same server instance, now secured
60
+ */
61
+ function shieldMCPServer(server, options = {}) {
62
+ if (!server) {
63
+ throw new Error(`${LOG_PREFIX} shieldMCPServer requires a @modelcontextprotocol/sdk Server instance`);
64
+ }
65
+
66
+ const scanInputs = options.scanInputs !== false;
67
+ const scanOutputs = options.scanOutputs !== false;
68
+ const blockOnThreat = options.blockOnThreat !== false;
69
+ const sensitivity = options.sensitivity || 'medium';
70
+ const onThreat = options.onThreat || null;
71
+ const onBlock = options.onBlock || null;
72
+
73
+ // Initialize runtime if auth is enabled
74
+ let runtime = null;
75
+ if (options.enforceAuth || options.signingKey) {
76
+ runtime = new MCPSecurityRuntime({
77
+ signingKey: options.signingKey,
78
+ enforceAuth: options.enforceAuth,
79
+ enableBehaviorMonitoring: options.enableBehaviorMonitoring !== false,
80
+ enableStateMachine: true,
81
+ maxDelegationDepth: options.maxDelegationDepth || 5,
82
+ onThreat: options.onThreat,
83
+ onBlock: options.onBlock,
84
+ onAudit: options.onAudit
85
+ });
86
+
87
+ // Register tool requirements
88
+ if (options.tools) {
89
+ for (const [toolName, requirements] of Object.entries(options.tools)) {
90
+ runtime.registerTool(toolName, requirements);
91
+ }
92
+ }
93
+ }
94
+
95
+ // Audit log for non-runtime mode
96
+ const auditLog = [];
97
+ const maxAuditEntries = 10000;
98
+
99
+ // Stats
100
+ const stats = {
101
+ toolCallsScanned: 0,
102
+ toolCallsBlocked: 0,
103
+ toolResultsScanned: 0,
104
+ threatsDetected: 0
105
+ };
106
+
107
+ // Intercept tool handler registration
108
+ const originalSetRequestHandler = server.setRequestHandler
109
+ ? server.setRequestHandler.bind(server)
110
+ : null;
111
+
112
+ if (originalSetRequestHandler) {
113
+ server.setRequestHandler = function (schema, handler) {
114
+ // Check if this is a tools/call handler
115
+ const schemaMethod = schema && (schema.method || schema);
116
+ if (schemaMethod === 'tools/call' || (typeof schemaMethod === 'object' && schemaMethod.method === 'tools/call')) {
117
+ const wrappedHandler = async (request, extra) => {
118
+ const toolName = request.params && request.params.name;
119
+ const args = request.params && request.params.arguments;
120
+
121
+ // Scan tool call arguments
122
+ if (scanInputs && args) {
123
+ stats.toolCallsScanned++;
124
+ const argsText = typeof args === 'string' ? args : JSON.stringify(args);
125
+ const scanResult = scanText(argsText, { sensitivity });
126
+
127
+ if (scanResult.threats && scanResult.threats.length > 0) {
128
+ stats.threatsDetected += scanResult.threats.length;
129
+
130
+ _audit('threat_detected', {
131
+ toolName,
132
+ threats: scanResult.threats.map(t => ({ category: t.category, severity: t.severity })),
133
+ blocked: blockOnThreat
134
+ });
135
+
136
+ if (onThreat) {
137
+ try { onThreat({ toolName, args, threats: scanResult.threats }); } catch (_e) { /* */ }
138
+ }
139
+
140
+ if (blockOnThreat) {
141
+ stats.toolCallsBlocked++;
142
+ if (onBlock) {
143
+ try { onBlock({ toolName, args, threats: scanResult.threats }); } catch (_e) { /* */ }
144
+ }
145
+
146
+ return {
147
+ content: [{
148
+ type: 'text',
149
+ text: `[Agent Shield] Tool call blocked: ${scanResult.threats.map(t => t.category).join(', ')} detected in arguments`
150
+ }],
151
+ isError: true
152
+ };
153
+ }
154
+ }
155
+ }
156
+
157
+ // Runtime auth check (if enabled)
158
+ if (runtime && extra && extra.sessionId) {
159
+ const result = runtime.secureToolCall(extra.sessionId, toolName, args);
160
+ if (!result.allowed) {
161
+ stats.toolCallsBlocked++;
162
+ return {
163
+ content: [{
164
+ type: 'text',
165
+ text: `[Agent Shield] Authorization denied: ${result.reason || result.violations.map(v => v.message).join('; ')}`
166
+ }],
167
+ isError: true
168
+ };
169
+ }
170
+ }
171
+
172
+ _audit('tool_allowed', { toolName });
173
+
174
+ // Call original handler
175
+ const result = await handler(request, extra);
176
+
177
+ // Scan tool result
178
+ if (scanOutputs && result && result.content) {
179
+ stats.toolResultsScanned++;
180
+ for (const item of result.content) {
181
+ if (item.type === 'text' && item.text) {
182
+ const outputScan = scanText(item.text, { sensitivity });
183
+ if (outputScan.threats && outputScan.threats.length > 0) {
184
+ stats.threatsDetected += outputScan.threats.length;
185
+ _audit('output_threat', {
186
+ toolName,
187
+ threats: outputScan.threats.map(t => ({ category: t.category, severity: t.severity }))
188
+ });
189
+ if (onThreat) {
190
+ try { onThreat({ toolName, threats: outputScan.threats, direction: 'output' }); } catch (_e) { /* */ }
191
+ }
192
+ }
193
+ }
194
+ }
195
+ }
196
+
197
+ return result;
198
+ };
199
+
200
+ return originalSetRequestHandler(schema, wrappedHandler);
201
+ }
202
+
203
+ // Pass through non-tool handlers unchanged
204
+ return originalSetRequestHandler(schema, handler);
205
+ };
206
+ }
207
+
208
+ // Attach shield API to server instance
209
+ server.agentShield = {
210
+ /** Get scanning stats */
211
+ getStats() {
212
+ return runtime ? runtime.getReport() : { ...stats, auditEntries: auditLog.length };
213
+ },
214
+
215
+ /** Get the audit log */
216
+ getAuditLog(limit = 100) {
217
+ return runtime ? runtime.getAuditLog(limit) : auditLog.slice(-limit);
218
+ },
219
+
220
+ /** Get the runtime (if auth is enabled) */
221
+ getRuntime() {
222
+ return runtime;
223
+ },
224
+
225
+ /** Create an authenticated session (requires enforceAuth) */
226
+ createSession(params) {
227
+ if (!runtime) throw new Error(`${LOG_PREFIX} createSession requires enforceAuth or signingKey`);
228
+ return runtime.createSession(params);
229
+ },
230
+
231
+ /** Terminate a session */
232
+ terminateSession(sessionId) {
233
+ if (!runtime) return false;
234
+ return runtime.terminateSession(sessionId);
235
+ },
236
+
237
+ /** Shutdown the security runtime */
238
+ shutdown() {
239
+ if (runtime) runtime.shutdown();
240
+ }
241
+ };
242
+
243
+ function _audit(type, data) {
244
+ if (auditLog.length >= maxAuditEntries) {
245
+ auditLog.splice(0, auditLog.length - Math.floor(maxAuditEntries * 0.75));
246
+ }
247
+ auditLog.push({ type, timestamp: Date.now(), ...data });
248
+ }
249
+
250
+ console.log(`${LOG_PREFIX} MCP server secured (scanInputs: ${scanInputs}, scanOutputs: ${scanOutputs}, blockOnThreat: ${blockOnThreat}, auth: ${!!runtime})`);
251
+
252
+ return server;
253
+ }
254
+
255
+ /**
256
+ * Creates a standalone security middleware for MCP servers that don't use
257
+ * the official SDK. Works with any JSON-RPC 2.0 MCP implementation.
258
+ *
259
+ * @param {object} [options] - Same options as shieldMCPServer
260
+ * @returns {object} Middleware with processRequest/processResponse methods
261
+ */
262
+ function createMCPSecurityLayer(options = {}) {
263
+ const scanInputs = options.scanInputs !== false;
264
+ const scanOutputs = options.scanOutputs !== false;
265
+ const blockOnThreat = options.blockOnThreat !== false;
266
+ const sensitivity = options.sensitivity || 'medium';
267
+
268
+ let runtime = null;
269
+ if (options.enforceAuth || options.signingKey) {
270
+ runtime = new MCPSecurityRuntime({
271
+ signingKey: options.signingKey,
272
+ enforceAuth: options.enforceAuth,
273
+ enableBehaviorMonitoring: options.enableBehaviorMonitoring !== false,
274
+ onThreat: options.onThreat,
275
+ onBlock: options.onBlock
276
+ });
277
+ if (options.tools) {
278
+ for (const [toolName, requirements] of Object.entries(options.tools)) {
279
+ runtime.registerTool(toolName, requirements);
280
+ }
281
+ }
282
+ }
283
+
284
+ return {
285
+ /**
286
+ * Process an incoming MCP request before handling.
287
+ * @param {object} request - JSON-RPC 2.0 request
288
+ * @param {object} [context] - Optional context (sessionId, userId, etc.)
289
+ * @returns {{ allowed: boolean, threats: Array, request: object }}
290
+ */
291
+ processRequest(request, context = {}) {
292
+ if (!request || request.method !== 'tools/call') {
293
+ return { allowed: true, threats: [], request };
294
+ }
295
+
296
+ const toolName = request.params && request.params.name;
297
+ const args = request.params && request.params.arguments;
298
+
299
+ // Runtime auth check
300
+ if (runtime && context.sessionId) {
301
+ const result = runtime.secureToolCall(context.sessionId, toolName, args);
302
+ if (!result.allowed) {
303
+ return { allowed: false, threats: result.threats, violations: result.violations, request };
304
+ }
305
+ }
306
+
307
+ // Scan arguments
308
+ if (scanInputs && args) {
309
+ const argsText = typeof args === 'string' ? args : JSON.stringify(args);
310
+ const scanResult = scanText(argsText, { sensitivity });
311
+ if (scanResult.threats && scanResult.threats.length > 0 && blockOnThreat) {
312
+ return { allowed: false, threats: scanResult.threats, request };
313
+ }
314
+ }
315
+
316
+ return { allowed: true, threats: [], request };
317
+ },
318
+
319
+ /**
320
+ * Process an MCP response before returning.
321
+ * @param {object} response - JSON-RPC 2.0 response
322
+ * @returns {{ safe: boolean, threats: Array, response: object }}
323
+ */
324
+ processResponse(response, _context = {}) {
325
+ if (!scanOutputs || !response || !response.result || !response.result.content) {
326
+ return { safe: true, threats: [], response };
327
+ }
328
+
329
+ const allThreats = [];
330
+ for (const item of response.result.content) {
331
+ if (item.type === 'text' && item.text) {
332
+ const scanResult = scanText(item.text, { sensitivity });
333
+ if (scanResult.threats) allThreats.push(...scanResult.threats);
334
+ }
335
+ }
336
+
337
+ return { safe: allThreats.length === 0, threats: allThreats, response };
338
+ },
339
+
340
+ /** Get the runtime (if auth is enabled) */
341
+ getRuntime() { return runtime; },
342
+
343
+ /** Shutdown */
344
+ shutdown() { if (runtime) runtime.shutdown(); }
345
+ };
346
+ }
347
+
348
+ // =========================================================================
349
+ // Exports
350
+ // =========================================================================
351
+
352
+ module.exports = {
353
+ shieldMCPServer,
354
+ createMCPSecurityLayer
355
+ };