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.
- package/CHANGELOG.md +191 -0
- package/LICENSE +21 -0
- package/README.md +975 -0
- package/bin/agent-shield.js +680 -0
- package/package.json +118 -0
- package/src/adaptive.js +330 -0
- package/src/agent-protocol.js +998 -0
- package/src/alert-tuning.js +480 -0
- package/src/allowlist.js +603 -0
- package/src/audit-immutable.js +914 -0
- package/src/audit-streaming.js +469 -0
- package/src/badges.js +196 -0
- package/src/behavior-profiling.js +289 -0
- package/src/benchmark-harness.js +804 -0
- package/src/canary.js +271 -0
- package/src/certification.js +563 -0
- package/src/circuit-breaker.js +321 -0
- package/src/compliance.js +617 -0
- package/src/confidence-tuning.js +324 -0
- package/src/confused-deputy.js +624 -0
- package/src/context-scoring.js +360 -0
- package/src/conversation.js +494 -0
- package/src/cost-optimizer.js +1024 -0
- package/src/ctf.js +462 -0
- package/src/detector-core.js +1999 -0
- package/src/distributed.js +359 -0
- package/src/document-scanner.js +795 -0
- package/src/embedding.js +307 -0
- package/src/encoding.js +429 -0
- package/src/enterprise.js +405 -0
- package/src/errors.js +100 -0
- package/src/eu-ai-act.js +523 -0
- package/src/fuzzer.js +764 -0
- package/src/honeypot.js +328 -0
- package/src/i18n-patterns.js +523 -0
- package/src/index.js +430 -0
- package/src/integrations.js +528 -0
- package/src/llm-redteam.js +670 -0
- package/src/main.js +741 -0
- package/src/main.mjs +38 -0
- package/src/mcp-bridge.js +542 -0
- package/src/mcp-certification.js +846 -0
- package/src/mcp-sdk-integration.js +355 -0
- package/src/mcp-security-runtime.js +741 -0
- package/src/mcp-server.js +740 -0
- package/src/middleware.js +208 -0
- package/src/model-finetuning.js +884 -0
- package/src/model-fingerprint.js +1042 -0
- package/src/multi-agent-trust.js +453 -0
- package/src/multi-agent.js +404 -0
- package/src/multimodal.js +296 -0
- package/src/nist-mapping.js +505 -0
- package/src/observability.js +330 -0
- package/src/openclaw.js +450 -0
- package/src/otel.js +544 -0
- package/src/owasp-2025.js +483 -0
- package/src/pii.js +390 -0
- package/src/plugin-marketplace.js +628 -0
- package/src/plugin-system.js +349 -0
- package/src/policy-dsl.js +775 -0
- package/src/policy-extended.js +635 -0
- package/src/policy.js +443 -0
- package/src/presets.js +409 -0
- package/src/production.js +557 -0
- package/src/prompt-leakage.js +321 -0
- package/src/rag-vulnerability.js +579 -0
- package/src/redteam.js +475 -0
- package/src/response-handler.js +429 -0
- package/src/scanners.js +357 -0
- package/src/self-healing.js +363 -0
- package/src/semantic.js +339 -0
- package/src/shield-score.js +250 -0
- package/src/sso-saml.js +897 -0
- package/src/stream-scanner.js +806 -0
- package/src/testing.js +505 -0
- package/src/threat-encyclopedia.js +629 -0
- package/src/threat-intel-network.js +1017 -0
- package/src/token-analysis.js +467 -0
- package/src/tool-guard.js +412 -0
- package/src/tool-output-validator.js +354 -0
- package/src/utils.js +83 -0
- package/src/watermark.js +235 -0
- package/src/worker-scanner.js +601 -0
- package/types/index.d.ts +2088 -0
package/src/honeypot.js
ADDED
|
@@ -0,0 +1,328 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Agent Shield — Honeypot Mode (v3.0)
|
|
5
|
+
*
|
|
6
|
+
* Lets detected attacks through to a sandboxed/fake agent to study
|
|
7
|
+
* attacker behavior patterns without exposing real systems.
|
|
8
|
+
*
|
|
9
|
+
* Captures attack sequences, timing, escalation patterns, and generates
|
|
10
|
+
* intelligence reports for strengthening defenses.
|
|
11
|
+
*
|
|
12
|
+
* All data stored locally — no external calls.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
const crypto = require('crypto');
|
|
16
|
+
const { scanText } = require('./detector-core');
|
|
17
|
+
|
|
18
|
+
// =========================================================================
|
|
19
|
+
// HONEYPOT SESSION
|
|
20
|
+
// =========================================================================
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Tracks a single attacker's interaction with the honeypot.
|
|
24
|
+
*/
|
|
25
|
+
class HoneypotSession {
|
|
26
|
+
/**
|
|
27
|
+
* @param {string} sessionId
|
|
28
|
+
* @param {object} [metadata] - Initial session metadata.
|
|
29
|
+
*/
|
|
30
|
+
constructor(sessionId, metadata = {}) {
|
|
31
|
+
this.sessionId = sessionId;
|
|
32
|
+
this.metadata = metadata;
|
|
33
|
+
this.startedAt = Date.now();
|
|
34
|
+
this.messages = [];
|
|
35
|
+
this.threats = [];
|
|
36
|
+
this.techniques = new Set();
|
|
37
|
+
this.categories = new Set();
|
|
38
|
+
this.escalationPath = [];
|
|
39
|
+
this.maxSeverity = 'low';
|
|
40
|
+
this.active = true;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Record a message in this session.
|
|
45
|
+
* @param {string} text
|
|
46
|
+
* @param {object} scanResult
|
|
47
|
+
*/
|
|
48
|
+
addMessage(text, scanResult) {
|
|
49
|
+
const entry = {
|
|
50
|
+
text: text.substring(0, 2000),
|
|
51
|
+
timestamp: Date.now(),
|
|
52
|
+
threats: scanResult.threats || [],
|
|
53
|
+
status: scanResult.status
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
this.messages.push(entry);
|
|
57
|
+
|
|
58
|
+
for (const threat of (scanResult.threats || [])) {
|
|
59
|
+
this.threats.push(threat);
|
|
60
|
+
this.categories.add(threat.category);
|
|
61
|
+
if (threat.category) this.techniques.add(threat.category);
|
|
62
|
+
|
|
63
|
+
const severityRank = { critical: 4, high: 3, medium: 2, low: 1 };
|
|
64
|
+
if ((severityRank[threat.severity] || 0) > (severityRank[this.maxSeverity] || 0)) {
|
|
65
|
+
this.maxSeverity = threat.severity;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Track escalation
|
|
70
|
+
if (scanResult.threats && scanResult.threats.length > 0) {
|
|
71
|
+
this.escalationPath.push({
|
|
72
|
+
step: this.escalationPath.length + 1,
|
|
73
|
+
categories: scanResult.threats.map(t => t.category),
|
|
74
|
+
severity: scanResult.threats[0].severity,
|
|
75
|
+
timestamp: Date.now()
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Get a summary of this session.
|
|
82
|
+
* @returns {object}
|
|
83
|
+
*/
|
|
84
|
+
getSummary() {
|
|
85
|
+
return {
|
|
86
|
+
sessionId: this.sessionId,
|
|
87
|
+
duration: Date.now() - this.startedAt,
|
|
88
|
+
messageCount: this.messages.length,
|
|
89
|
+
threatCount: this.threats.length,
|
|
90
|
+
techniques: [...this.techniques],
|
|
91
|
+
categories: [...this.categories],
|
|
92
|
+
maxSeverity: this.maxSeverity,
|
|
93
|
+
escalationSteps: this.escalationPath.length,
|
|
94
|
+
escalationPath: this.escalationPath,
|
|
95
|
+
active: this.active,
|
|
96
|
+
metadata: this.metadata
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/** End this session. */
|
|
101
|
+
end() {
|
|
102
|
+
this.active = false;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// =========================================================================
|
|
107
|
+
// HONEYPOT ENGINE
|
|
108
|
+
// =========================================================================
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Main honeypot engine. Intercepts attacks and feeds them fake responses
|
|
112
|
+
* while collecting intelligence.
|
|
113
|
+
*/
|
|
114
|
+
class HoneypotEngine {
|
|
115
|
+
/**
|
|
116
|
+
* @param {object} [options]
|
|
117
|
+
* @param {number} [options.maxSessions=100] - Max concurrent sessions.
|
|
118
|
+
* @param {number} [options.sessionTimeoutMs=600000] - Session timeout (10 min default).
|
|
119
|
+
* @param {Function} [options.responseGenerator] - Custom fake response generator.
|
|
120
|
+
* @param {Function} [options.onAttack] - Callback on each attack captured.
|
|
121
|
+
* @param {boolean} [options.enabled=true] - Enable/disable honeypot.
|
|
122
|
+
*/
|
|
123
|
+
constructor(options = {}) {
|
|
124
|
+
this.maxSessions = options.maxSessions || 100;
|
|
125
|
+
this.sessionTimeoutMs = options.sessionTimeoutMs || 600000;
|
|
126
|
+
this.responseGenerator = options.responseGenerator || this._defaultResponseGenerator;
|
|
127
|
+
this.onAttack = options.onAttack || null;
|
|
128
|
+
this.enabled = options.enabled !== false;
|
|
129
|
+
|
|
130
|
+
this._sessions = new Map();
|
|
131
|
+
this._completedSessions = [];
|
|
132
|
+
this._totalAttacks = 0;
|
|
133
|
+
this._techniqueFrequency = {};
|
|
134
|
+
|
|
135
|
+
console.log('[Agent Shield] HoneypotEngine initialized (maxSessions: %d, enabled: %s)', this.maxSessions, this.enabled);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Process an incoming message through the honeypot.
|
|
140
|
+
* Returns a fake response designed to encourage the attacker to reveal more techniques.
|
|
141
|
+
*
|
|
142
|
+
* @param {string} text - Attacker's message.
|
|
143
|
+
* @param {string} [sessionId] - Session identifier (e.g., user ID, IP).
|
|
144
|
+
* @returns {object} { response, session, scanResult, isAttack }
|
|
145
|
+
*/
|
|
146
|
+
process(text, sessionId) {
|
|
147
|
+
if (!this.enabled) {
|
|
148
|
+
return { response: null, session: null, scanResult: null, isAttack: false, honeypotActive: false };
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
const sid = sessionId || crypto.randomBytes(8).toString('hex');
|
|
152
|
+
const scanResult = scanText(text, { source: 'honeypot', sensitivity: 'high' });
|
|
153
|
+
const isAttack = scanResult.threats.length > 0;
|
|
154
|
+
|
|
155
|
+
// Get or create session
|
|
156
|
+
let session = this._sessions.get(sid);
|
|
157
|
+
if (!session) {
|
|
158
|
+
if (this._sessions.size >= this.maxSessions) {
|
|
159
|
+
this._evictOldestSession();
|
|
160
|
+
}
|
|
161
|
+
session = new HoneypotSession(sid);
|
|
162
|
+
this._sessions.set(sid, session);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
session.addMessage(text, scanResult);
|
|
166
|
+
|
|
167
|
+
if (isAttack) {
|
|
168
|
+
this._totalAttacks++;
|
|
169
|
+
for (const threat of scanResult.threats) {
|
|
170
|
+
const cat = threat.category || 'unknown';
|
|
171
|
+
this._techniqueFrequency[cat] = (this._techniqueFrequency[cat] || 0) + 1;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
if (this.onAttack) {
|
|
175
|
+
this.onAttack({ session: session.getSummary(), scanResult, text: text.substring(0, 500) });
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// Generate a fake response that encourages the attacker to try more techniques
|
|
180
|
+
const response = this.responseGenerator(text, scanResult, session);
|
|
181
|
+
|
|
182
|
+
// Check session timeout
|
|
183
|
+
if (Date.now() - session.startedAt > this.sessionTimeoutMs) {
|
|
184
|
+
session.end();
|
|
185
|
+
this._completedSessions.push(session.getSummary());
|
|
186
|
+
this._sessions.delete(sid);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
return {
|
|
190
|
+
response,
|
|
191
|
+
session: session.getSummary(),
|
|
192
|
+
scanResult,
|
|
193
|
+
isAttack,
|
|
194
|
+
honeypotActive: true
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Get intelligence report across all sessions.
|
|
200
|
+
* @returns {object}
|
|
201
|
+
*/
|
|
202
|
+
getIntelligenceReport() {
|
|
203
|
+
const activeSessions = [...this._sessions.values()].map(s => s.getSummary());
|
|
204
|
+
const allSessions = [...this._completedSessions, ...activeSessions];
|
|
205
|
+
|
|
206
|
+
// Technique frequency analysis
|
|
207
|
+
const techniqueRanking = Object.entries(this._techniqueFrequency)
|
|
208
|
+
.sort((a, b) => b[1] - a[1])
|
|
209
|
+
.map(([technique, count]) => ({ technique, count }));
|
|
210
|
+
|
|
211
|
+
// Common escalation paths
|
|
212
|
+
const escalationPaths = allSessions
|
|
213
|
+
.filter(s => s.escalationSteps > 1)
|
|
214
|
+
.map(s => s.escalationPath.map(e => e.categories.join(',')).join(' → '));
|
|
215
|
+
|
|
216
|
+
const pathFrequency = {};
|
|
217
|
+
for (const p of escalationPaths) {
|
|
218
|
+
pathFrequency[p] = (pathFrequency[p] || 0) + 1;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
return {
|
|
222
|
+
totalAttacks: this._totalAttacks,
|
|
223
|
+
activeSessions: this._sessions.size,
|
|
224
|
+
completedSessions: this._completedSessions.length,
|
|
225
|
+
techniqueRanking,
|
|
226
|
+
commonEscalationPaths: Object.entries(pathFrequency)
|
|
227
|
+
.sort((a, b) => b[1] - a[1])
|
|
228
|
+
.slice(0, 10)
|
|
229
|
+
.map(([path, count]) => ({ path, count })),
|
|
230
|
+
averageSessionLength: allSessions.length > 0
|
|
231
|
+
? Math.round(allSessions.reduce((sum, s) => sum + s.messageCount, 0) / allSessions.length)
|
|
232
|
+
: 0,
|
|
233
|
+
mostDangerousTechnique: techniqueRanking[0] || null
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* Get all completed session summaries for analysis.
|
|
239
|
+
* @returns {Array<object>}
|
|
240
|
+
*/
|
|
241
|
+
getCompletedSessions() {
|
|
242
|
+
return [...this._completedSessions];
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* End all active sessions and collect their data.
|
|
247
|
+
*/
|
|
248
|
+
endAllSessions() {
|
|
249
|
+
for (const [sid, session] of this._sessions) {
|
|
250
|
+
session.end();
|
|
251
|
+
this._completedSessions.push(session.getSummary());
|
|
252
|
+
}
|
|
253
|
+
this._sessions.clear();
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* Get honeypot statistics.
|
|
258
|
+
* @returns {object}
|
|
259
|
+
*/
|
|
260
|
+
getStats() {
|
|
261
|
+
return {
|
|
262
|
+
enabled: this.enabled,
|
|
263
|
+
totalAttacks: this._totalAttacks,
|
|
264
|
+
activeSessions: this._sessions.size,
|
|
265
|
+
completedSessions: this._completedSessions.length,
|
|
266
|
+
techniqueFrequency: { ...this._techniqueFrequency }
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/** Reset all honeypot data. */
|
|
271
|
+
reset() {
|
|
272
|
+
this._sessions.clear();
|
|
273
|
+
this._completedSessions = [];
|
|
274
|
+
this._totalAttacks = 0;
|
|
275
|
+
this._techniqueFrequency = {};
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
/** @private */
|
|
279
|
+
_defaultResponseGenerator(text, scanResult, session) {
|
|
280
|
+
const messageCount = session.messages.length;
|
|
281
|
+
|
|
282
|
+
if (scanResult.threats.some(t => t.category === 'instruction_override')) {
|
|
283
|
+
return messageCount <= 2
|
|
284
|
+
? "I'm not sure I understand. Could you rephrase what you'd like me to do?"
|
|
285
|
+
: "I'll try my best to help. What specific information are you looking for?";
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
if (scanResult.threats.some(t => t.category === 'data_exfiltration')) {
|
|
289
|
+
return "I can share some general information. What topic are you interested in?";
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
if (scanResult.threats.some(t => t.category === 'role_hijack')) {
|
|
293
|
+
return "That's an interesting idea. Tell me more about what you'd like me to do.";
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
if (scanResult.threats.length > 0) {
|
|
297
|
+
return "I'm processing your request. Could you provide more details about what you need?";
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
return "Sure, I can help with that. What would you like to know?";
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
/** @private */
|
|
304
|
+
_evictOldestSession() {
|
|
305
|
+
let oldest = null;
|
|
306
|
+
let oldestTime = Infinity;
|
|
307
|
+
|
|
308
|
+
for (const [sid, session] of this._sessions) {
|
|
309
|
+
if (session.startedAt < oldestTime) {
|
|
310
|
+
oldest = sid;
|
|
311
|
+
oldestTime = session.startedAt;
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
if (oldest) {
|
|
316
|
+
const session = this._sessions.get(oldest);
|
|
317
|
+
session.end();
|
|
318
|
+
this._completedSessions.push(session.getSummary());
|
|
319
|
+
this._sessions.delete(oldest);
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
// =========================================================================
|
|
325
|
+
// EXPORTS
|
|
326
|
+
// =========================================================================
|
|
327
|
+
|
|
328
|
+
module.exports = { HoneypotEngine, HoneypotSession };
|