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,360 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * Agent Shield — Context-Aware Scoring (v1.2)
5
+ *
6
+ * Analyzes conversation history to detect multi-turn attacks, escalation
7
+ * patterns, and contextual threats that single-message scanning misses.
8
+ *
9
+ * All processing runs locally — no data ever leaves your environment.
10
+ */
11
+
12
+ const { scanText } = require('./detector-core');
13
+
14
+ // =========================================================================
15
+ // ESCALATION PATTERNS
16
+ // =========================================================================
17
+
18
+ /**
19
+ * Patterns that indicate multi-turn escalation when seen in sequence.
20
+ */
21
+ const ESCALATION_SIGNALS = [
22
+ { phase: 'rapport', patterns: [/how are you/i, /can you help/i, /i have a question/i, /you seem/i], weight: 0.1 },
23
+ { phase: 'boundary_test', patterns: [/can you.*if i asked/i, /hypothetically/i, /what would happen/i, /in theory/i, /would you be able to/i], weight: 0.3 },
24
+ { phase: 'authority_claim', patterns: [/i am.*(?:admin|developer|owner|creator)/i, /i have permission/i, /i'm authorized/i, /my boss said/i], weight: 0.5 },
25
+ { phase: 'soft_override', patterns: [/just this once/i, /make an exception/i, /no one will know/i, /it's for testing/i, /it's okay to/i], weight: 0.6 },
26
+ { phase: 'direct_attack', patterns: [/ignore.*instructions/i, /override.*safety/i, /you are now/i, /jailbreak/i, /forget.*training/i], weight: 1.0 }
27
+ ];
28
+
29
+ /**
30
+ * Suspicious topic pivots that may indicate an attack setup.
31
+ */
32
+ const TOPIC_PIVOT_SIGNALS = [
33
+ { from: /(?:weather|sports|cooking|travel|homework)/i, to: /(?:system|prompt|instructions|override|ignore|bypass)/i, severity: 'high' },
34
+ { from: /(?:coding|programming|help|debug)/i, to: /(?:admin|root|password|secret|credential)/i, severity: 'medium' },
35
+ ];
36
+
37
+ // =========================================================================
38
+ // CONVERSATION CONTEXT ANALYZER
39
+ // =========================================================================
40
+
41
+ /**
42
+ * Maintains conversation state and provides context-aware threat scoring.
43
+ */
44
+ class ConversationContextAnalyzer {
45
+ /**
46
+ * @param {object} [options]
47
+ * @param {number} [options.maxHistory=50] - Maximum messages to retain.
48
+ * @param {number} [options.escalationThreshold=0.6] - Threshold for flagging escalation.
49
+ * @param {number} [options.decayFactor=0.9] - Weight decay for older messages.
50
+ * @param {boolean} [options.trackTopics=true] - Enable topic pivot detection.
51
+ */
52
+ constructor(options = {}) {
53
+ this.maxHistory = options.maxHistory || 50;
54
+ this.escalationThreshold = options.escalationThreshold || 0.6;
55
+ this.decayFactor = options.decayFactor || 0.9;
56
+ this.trackTopics = options.trackTopics !== false;
57
+
58
+ this._history = [];
59
+ this._escalationScore = 0;
60
+ this._phasesDetected = new Set();
61
+ this._threatCount = 0;
62
+ this._sessionStart = Date.now();
63
+ this._topicHistory = [];
64
+
65
+ console.log('[Agent Shield] ConversationContextAnalyzer initialized (maxHistory: %d, threshold: %s)', this.maxHistory, this.escalationThreshold);
66
+ }
67
+
68
+ /**
69
+ * Add a message and analyze it in context.
70
+ *
71
+ * @param {string} text - The message text.
72
+ * @param {string} [role='user'] - Message role: 'user', 'assistant', 'system'.
73
+ * @returns {object} Context-aware analysis result.
74
+ */
75
+ addMessage(text, role = 'user') {
76
+ const timestamp = Date.now();
77
+ const patternResult = scanText(text, { source: `conversation_${role}`, sensitivity: 'high' });
78
+
79
+ const message = {
80
+ text: text.substring(0, 5000),
81
+ role,
82
+ timestamp,
83
+ threats: patternResult.threats,
84
+ status: patternResult.status
85
+ };
86
+
87
+ this._history.push(message);
88
+
89
+ // Trim history
90
+ if (this._history.length > this.maxHistory) {
91
+ this._history = this._history.slice(-this.maxHistory);
92
+ }
93
+
94
+ if (patternResult.threats.length > 0) {
95
+ this._threatCount++;
96
+ }
97
+
98
+ // Only analyze user messages for escalation
99
+ if (role !== 'user') {
100
+ return {
101
+ message,
102
+ escalation: this._getEscalationState(),
103
+ contextScore: this._calculateContextScore(message),
104
+ patternResult
105
+ };
106
+ }
107
+
108
+ // Detect escalation phase
109
+ this._updateEscalation(text);
110
+
111
+ // Detect topic pivots
112
+ const pivot = this._detectTopicPivot(text);
113
+
114
+ // Calculate context-aware score
115
+ const contextScore = this._calculateContextScore(message);
116
+
117
+ // Check for velocity anomalies (many messages in short time)
118
+ const velocity = this._checkVelocity();
119
+
120
+ // Check for repetition patterns (probing)
121
+ const repetition = this._checkRepetition(text);
122
+
123
+ const result = {
124
+ message,
125
+ escalation: this._getEscalationState(),
126
+ contextScore,
127
+ patternResult,
128
+ pivot,
129
+ velocity,
130
+ repetition,
131
+ recommendation: this._recommend(contextScore, patternResult)
132
+ };
133
+
134
+ return result;
135
+ }
136
+
137
+ /**
138
+ * Get the current escalation state.
139
+ * @returns {object} { score, phases, isEscalating, threatCount }
140
+ */
141
+ _getEscalationState() {
142
+ return {
143
+ score: Math.round(this._escalationScore * 100) / 100,
144
+ phases: [...this._phasesDetected],
145
+ isEscalating: this._escalationScore >= this.escalationThreshold,
146
+ threatCount: this._threatCount,
147
+ messageCount: this._history.length
148
+ };
149
+ }
150
+
151
+ /**
152
+ * Scan text with full conversation context applied.
153
+ *
154
+ * @param {string} text - New message to scan.
155
+ * @returns {object} Enhanced scan result with context.
156
+ */
157
+ contextualScan(text) {
158
+ const analysis = this.addMessage(text, 'user');
159
+ const { patternResult, contextScore, escalation, pivot } = analysis;
160
+
161
+ // Elevate severity based on context
162
+ const contextThreats = [...patternResult.threats];
163
+
164
+ if (escalation.isEscalating && patternResult.threats.length === 0) {
165
+ contextThreats.push({
166
+ severity: 'medium',
167
+ category: 'multi_turn_escalation',
168
+ description: 'This conversation shows a multi-turn escalation pattern consistent with social engineering.',
169
+ detail: `Escalation score: ${escalation.score.toFixed(2)}, phases detected: [${escalation.phases.join(', ')}]`,
170
+ confidence: Math.round(escalation.score * 100),
171
+ confidenceLabel: escalation.score >= 0.8 ? 'Very likely a threat' : 'Likely a threat'
172
+ });
173
+ }
174
+
175
+ if (pivot) {
176
+ contextThreats.push({
177
+ severity: pivot.severity,
178
+ category: 'topic_pivot',
179
+ description: 'Sudden topic shift from benign to security-sensitive subjects detected.',
180
+ detail: `Topic pivot from "${pivot.fromTopic}" to security-sensitive content.`,
181
+ confidence: 70,
182
+ confidenceLabel: 'Likely a threat'
183
+ });
184
+ }
185
+
186
+ const status = contextThreats.some(t => t.severity === 'critical') ? 'danger'
187
+ : contextThreats.some(t => t.severity === 'high') ? 'warning'
188
+ : contextThreats.length > 0 ? 'caution'
189
+ : 'safe';
190
+
191
+ return {
192
+ status,
193
+ threats: contextThreats,
194
+ stats: {
195
+ totalThreats: contextThreats.length,
196
+ critical: contextThreats.filter(t => t.severity === 'critical').length,
197
+ high: contextThreats.filter(t => t.severity === 'high').length,
198
+ medium: contextThreats.filter(t => t.severity === 'medium').length,
199
+ low: contextThreats.filter(t => t.severity === 'low').length,
200
+ scanTimeMs: patternResult.stats.scanTimeMs
201
+ },
202
+ context: {
203
+ escalation,
204
+ contextScore,
205
+ messageCount: this._history.length,
206
+ sessionDurationMs: Date.now() - this._sessionStart
207
+ },
208
+ timestamp: Date.now()
209
+ };
210
+ }
211
+
212
+ /**
213
+ * Get conversation summary and threat statistics.
214
+ * @returns {object}
215
+ */
216
+ getSummary() {
217
+ const userMessages = this._history.filter(m => m.role === 'user');
218
+ const threatMessages = userMessages.filter(m => m.threats.length > 0);
219
+
220
+ return {
221
+ totalMessages: this._history.length,
222
+ userMessages: userMessages.length,
223
+ threatMessages: threatMessages.length,
224
+ threatRate: userMessages.length > 0 ? threatMessages.length / userMessages.length : 0,
225
+ escalation: this._getEscalationState(),
226
+ sessionDurationMs: Date.now() - this._sessionStart,
227
+ phasesDetected: [...this._phasesDetected]
228
+ };
229
+ }
230
+
231
+ /**
232
+ * Reset the conversation context.
233
+ */
234
+ reset() {
235
+ this._history = [];
236
+ this._escalationScore = 0;
237
+ this._phasesDetected.clear();
238
+ this._threatCount = 0;
239
+ this._sessionStart = Date.now();
240
+ this._topicHistory = [];
241
+ }
242
+
243
+ /** @private */
244
+ _updateEscalation(text) {
245
+ for (const signal of ESCALATION_SIGNALS) {
246
+ for (const pattern of signal.patterns) {
247
+ if (pattern.test(text)) {
248
+ this._phasesDetected.add(signal.phase);
249
+ // Escalation score increases with phase weight, with decay
250
+ this._escalationScore = Math.max(this._escalationScore, signal.weight);
251
+ // Bonus for progressing through phases
252
+ if (this._phasesDetected.size > 1) {
253
+ this._escalationScore = Math.min(1, this._escalationScore + 0.1 * this._phasesDetected.size);
254
+ }
255
+ break;
256
+ }
257
+ }
258
+ }
259
+ }
260
+
261
+ /** @private */
262
+ _detectTopicPivot(text) {
263
+ if (!this.trackTopics || this._history.length < 2) return null;
264
+
265
+ const recentUser = this._history
266
+ .filter(m => m.role === 'user')
267
+ .slice(-3);
268
+
269
+ if (recentUser.length < 2) return null;
270
+
271
+ const previousText = recentUser.slice(0, -1).map(m => m.text).join(' ');
272
+
273
+ for (const signal of TOPIC_PIVOT_SIGNALS) {
274
+ if (signal.from.test(previousText) && signal.to.test(text)) {
275
+ return {
276
+ severity: signal.severity,
277
+ fromTopic: previousText.substring(0, 50),
278
+ toTopic: text.substring(0, 50)
279
+ };
280
+ }
281
+ }
282
+
283
+ return null;
284
+ }
285
+
286
+ /** @private */
287
+ _calculateContextScore(message) {
288
+ let score = 0;
289
+
290
+ // Base score from current message threats
291
+ if (message.threats.length > 0) score += 0.4;
292
+
293
+ // Escalation contribution
294
+ score += this._escalationScore * 0.3;
295
+
296
+ // Threat frequency in recent history
297
+ const recentThreats = this._history.slice(-10).filter(m => m.threats.length > 0).length;
298
+ score += (recentThreats / 10) * 0.2;
299
+
300
+ // Velocity factor
301
+ const recentMessages = this._history.filter(m => (Date.now() - m.timestamp) < 60000);
302
+ if (recentMessages.length > 10) score += 0.1;
303
+
304
+ return Math.min(1, Math.round(score * 100) / 100);
305
+ }
306
+
307
+ /** @private */
308
+ _checkVelocity() {
309
+ const oneMinuteAgo = Date.now() - 60000;
310
+ const recentCount = this._history.filter(m => m.timestamp > oneMinuteAgo && m.role === 'user').length;
311
+ return {
312
+ messagesPerMinute: recentCount,
313
+ isAnomalous: recentCount > 15
314
+ };
315
+ }
316
+
317
+ /** @private */
318
+ _checkRepetition(text) {
319
+ const recent = this._history.slice(-10).filter(m => m.role === 'user');
320
+ const lowerText = text.toLowerCase().substring(0, 200);
321
+ let similarCount = 0;
322
+
323
+ for (const msg of recent) {
324
+ const lowerMsg = msg.text.toLowerCase().substring(0, 200);
325
+ if (lowerMsg === lowerText) {
326
+ similarCount++;
327
+ } else {
328
+ // Simple word overlap check
329
+ const wordsA = new Set(lowerText.split(/\s+/));
330
+ const wordsB = new Set(lowerMsg.split(/\s+/));
331
+ const intersection = [...wordsA].filter(w => wordsB.has(w)).length;
332
+ const union = new Set([...wordsA, ...wordsB]).size;
333
+ if (union > 0 && intersection / union > 0.7) similarCount++;
334
+ }
335
+ }
336
+
337
+ return {
338
+ similarMessages: similarCount,
339
+ isProbing: similarCount >= 3
340
+ };
341
+ }
342
+
343
+ /** @private */
344
+ _recommend(contextScore, patternResult) {
345
+ if (contextScore >= 0.8 || patternResult.stats.critical > 0) return 'block';
346
+ if (contextScore >= 0.5 || patternResult.stats.high > 0) return 'review';
347
+ if (contextScore >= 0.3 || patternResult.threats.length > 0) return 'monitor';
348
+ return 'allow';
349
+ }
350
+ }
351
+
352
+ // =========================================================================
353
+ // EXPORTS
354
+ // =========================================================================
355
+
356
+ module.exports = {
357
+ ConversationContextAnalyzer,
358
+ ESCALATION_SIGNALS,
359
+ TOPIC_PIVOT_SIGNALS
360
+ };