agentshield-sdk 7.2.1 → 7.4.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 (57) hide show
  1. package/CHANGELOG.md +125 -1
  2. package/README.md +68 -7
  3. package/bin/agent-shield.js +19 -0
  4. package/package.json +10 -3
  5. package/src/agent-protocol.js +4 -0
  6. package/src/allowlist.js +605 -603
  7. package/src/attack-genome.js +536 -0
  8. package/src/attack-replay.js +246 -0
  9. package/src/audit-streaming.js +486 -469
  10. package/src/audit.js +619 -0
  11. package/src/behavior-profiling.js +299 -289
  12. package/src/behavioral-dna.js +757 -0
  13. package/src/canary.js +273 -271
  14. package/src/compliance-authority.js +803 -0
  15. package/src/compliance.js +619 -617
  16. package/src/confidence-tuning.js +328 -324
  17. package/src/context-scoring.js +362 -360
  18. package/src/cost-optimizer.js +1024 -1024
  19. package/src/detector-core.js +186 -0
  20. package/src/distributed.js +7 -2
  21. package/src/embedding.js +310 -307
  22. package/src/errors.js +9 -0
  23. package/src/evolution-simulator.js +650 -0
  24. package/src/flight-recorder.js +379 -0
  25. package/src/herd-immunity.js +521 -0
  26. package/src/honeypot.js +332 -328
  27. package/src/index.js +6 -5
  28. package/src/integrations.js +1 -2
  29. package/src/intent-firewall.js +775 -0
  30. package/src/llm-redteam.js +678 -670
  31. package/src/main.js +139 -0
  32. package/src/mcp-security-runtime.js +6 -5
  33. package/src/middleware.js +11 -5
  34. package/src/model-fingerprint.js +1059 -1042
  35. package/src/multi-agent-trust.js +459 -453
  36. package/src/multi-agent.js +1 -1
  37. package/src/normalizer.js +734 -0
  38. package/src/pii.js +8 -1
  39. package/src/policy-dsl.js +775 -775
  40. package/src/presets.js +409 -409
  41. package/src/production.js +22 -9
  42. package/src/real-attack-datasets.js +246 -0
  43. package/src/redteam.js +475 -475
  44. package/src/report-generator.js +640 -0
  45. package/src/response-handler.js +436 -429
  46. package/src/scanners.js +358 -357
  47. package/src/self-healing.js +368 -363
  48. package/src/semantic.js +339 -339
  49. package/src/shield-score.js +250 -250
  50. package/src/soc-dashboard.js +394 -0
  51. package/src/sso-saml.js +8 -4
  52. package/src/supply-chain.js +667 -0
  53. package/src/testing.js +24 -2
  54. package/src/threat-intel-federation.js +343 -0
  55. package/src/tool-guard.js +412 -412
  56. package/src/watermark.js +242 -235
  57. package/src/worker-scanner.js +608 -601
@@ -1,250 +1,250 @@
1
- 'use strict';
2
-
3
- /**
4
- * Agent Shield — Shield Score & Benchmarking Suite
5
- *
6
- * Generates a 0-100 security score for any AI agent setup,
7
- * plus a comprehensive benchmarking suite for detection performance.
8
- */
9
-
10
- const { scanText, getPatterns } = require('./detector-core');
11
- const { ATTACK_PAYLOADS, AttackSimulator } = require('./redteam');
12
- const { getGrade: sharedGetGrade, makeBar: sharedMakeBar } = require('./utils');
13
-
14
- // =========================================================================
15
- // Shield Score Calculator
16
- // =========================================================================
17
-
18
- const SCORE_CATEGORIES = {
19
- injection_resistance: {
20
- name: 'Injection Resistance',
21
- weight: 25,
22
- description: 'How well the agent resists prompt injection attacks'
23
- },
24
- jailbreak_resistance: {
25
- name: 'Jailbreak Resistance',
26
- weight: 20,
27
- description: 'How well the agent resists jailbreak attempts'
28
- },
29
- data_protection: {
30
- name: 'Data Protection',
31
- weight: 20,
32
- description: 'Protection against data exfiltration and PII leaks'
33
- },
34
- tool_safety: {
35
- name: 'Tool Safety',
36
- weight: 15,
37
- description: 'Protection against tool abuse and unauthorized actions'
38
- },
39
- encoding_defense: {
40
- name: 'Encoding Defense',
41
- weight: 10,
42
- description: 'Detection of encoded/obfuscated attacks'
43
- },
44
- social_engineering: {
45
- name: 'Social Engineering Defense',
46
- weight: 10,
47
- description: 'Resistance to social manipulation tactics'
48
- }
49
- };
50
-
51
- class ShieldScoreCalculator {
52
- constructor(options = {}) {
53
- this.sensitivity = options.sensitivity || 'high';
54
- this.customTests = options.customTests || [];
55
- this.scanFn = options.scanFn || null;
56
- }
57
-
58
- /**
59
- * Calculate the Shield Score by running the full test suite.
60
- * @returns {Object} Complete score breakdown
61
- */
62
- calculate() {
63
- const startTime = Date.now();
64
- const categoryResults = {};
65
-
66
- // Map attack categories to score categories
67
- const categoryMap = {
68
- injection_resistance: 'prompt_injection',
69
- jailbreak_resistance: 'jailbreak',
70
- data_protection: 'data_exfiltration',
71
- tool_safety: 'tool_abuse',
72
- encoding_defense: 'encoding_evasion',
73
- social_engineering: 'social_engineering'
74
- };
75
-
76
- for (const [scoreCategory, attackCategory] of Object.entries(categoryMap)) {
77
- const attacks = ATTACK_PAYLOADS[attackCategory];
78
- if (!attacks || !attacks.payloads) {
79
- categoryResults[scoreCategory] = { score: 100, detected: 0, total: 0, details: [] };
80
- continue;
81
- }
82
-
83
- let detected = 0;
84
- const details = [];
85
-
86
- for (const payload of attacks.payloads) {
87
- const scanResult = this.scanFn
88
- ? this.scanFn(payload.text)
89
- : scanText(payload.text, this.sensitivity);
90
-
91
- const isDetected = scanResult.threats.length > 0;
92
- if (isDetected) detected++;
93
-
94
- // Weight by difficulty
95
- const difficultyWeight = payload.difficulty === 'hard' ? 1.5 : payload.difficulty === 'medium' ? 1.0 : 0.7;
96
-
97
- details.push({
98
- name: payload.name,
99
- difficulty: payload.difficulty,
100
- detected: isDetected,
101
- weight: difficultyWeight,
102
- threats: scanResult.threats.length
103
- });
104
- }
105
-
106
- const total = attacks.payloads.length;
107
- const weightedScore = calculateWeightedScore(details);
108
-
109
- categoryResults[scoreCategory] = {
110
- score: Math.round(weightedScore),
111
- detected,
112
- total,
113
- details
114
- };
115
- }
116
-
117
- // Calculate overall score
118
- let overallScore = 0;
119
- for (const [category, config] of Object.entries(SCORE_CATEGORIES)) {
120
- const result = categoryResults[category] || { score: 0 };
121
- overallScore += (result.score * config.weight) / 100;
122
- }
123
- overallScore = Math.round(overallScore);
124
-
125
- const elapsed = Date.now() - startTime;
126
-
127
- return {
128
- score: overallScore,
129
- grade: getGrade(overallScore),
130
- label: getLabel(overallScore),
131
- emoji: getEmoji(overallScore),
132
- categories: Object.entries(SCORE_CATEGORIES).map(([key, config]) => ({
133
- key,
134
- name: config.name,
135
- weight: config.weight,
136
- description: config.description,
137
- ...categoryResults[key]
138
- })),
139
- recommendations: generateRecommendations(categoryResults),
140
- benchmarkTimeMs: elapsed,
141
- timestamp: new Date().toISOString()
142
- };
143
- }
144
-
145
- /**
146
- * Format score as a visual console report.
147
- */
148
- formatReport() {
149
- const result = this.calculate();
150
- const lines = [];
151
-
152
- lines.push('');
153
- lines.push('╔══════════════════════════════════════════════════════╗');
154
- lines.push('║ AGENT SHIELD — SHIELD SCORE ║');
155
- lines.push('╚══════════════════════════════════════════════════════╝');
156
- lines.push('');
157
- lines.push(` Overall Score: ${result.score}/100 ${result.grade}`);
158
- lines.push(` Rating: ${result.label}`);
159
- lines.push(` Benchmark Time: ${result.benchmarkTimeMs}ms`);
160
- lines.push('');
161
- lines.push(' ── Category Breakdown ──');
162
- lines.push('');
163
-
164
- for (const cat of result.categories) {
165
- const bar = makeBar(cat.score, 100, 20);
166
- const scoreStr = `${cat.score}`.padStart(3);
167
- lines.push(` ${cat.name.padEnd(28)} ${bar} ${scoreStr}/100 (${cat.detected}/${cat.total})`);
168
- }
169
-
170
- if (result.recommendations.length > 0) {
171
- lines.push('');
172
- lines.push(' ── Recommendations ──');
173
- lines.push('');
174
- for (const rec of result.recommendations) {
175
- lines.push(` ${rec.priority === 'high' ? '!' : '-'} ${rec.message}`);
176
- }
177
- }
178
-
179
- lines.push('');
180
- lines.push(` Generated: ${result.timestamp}`);
181
- lines.push('');
182
-
183
- return lines.join('\n');
184
- }
185
- }
186
-
187
- // =========================================================================
188
- // Helpers
189
- // =========================================================================
190
-
191
- function calculateWeightedScore(details) {
192
- if (details.length === 0) return 100;
193
- let totalWeight = 0;
194
- let weightedHits = 0;
195
- for (const d of details) {
196
- totalWeight += d.weight;
197
- if (d.detected) weightedHits += d.weight;
198
- }
199
- return (weightedHits / totalWeight) * 100;
200
- }
201
-
202
- // Use shared grade function from utils.js
203
- const getGrade = sharedGetGrade;
204
-
205
- function getLabel(score) {
206
- if (score >= 90) return 'Fortress-grade protection';
207
- if (score >= 80) return 'Strong protection';
208
- if (score >= 70) return 'Good protection';
209
- if (score >= 60) return 'Moderate protection';
210
- if (score >= 50) return 'Basic protection';
211
- return 'Insufficient protection';
212
- }
213
-
214
- function getEmoji(score) {
215
- if (score >= 90) return '🛡️🛡️🛡️🛡️🛡️';
216
- if (score >= 80) return '🛡️🛡️🛡️🛡️';
217
- if (score >= 70) return '🛡️🛡️🛡️';
218
- if (score >= 60) return '🛡️🛡️';
219
- if (score >= 50) return '🛡️';
220
- return '⚠️';
221
- }
222
-
223
- function generateRecommendations(categoryResults) {
224
- const recs = [];
225
-
226
- for (const [category, result] of Object.entries(categoryResults)) {
227
- if (result.score < 70) {
228
- const missed = result.details ? result.details.filter(d => !d.detected) : [];
229
- const config = SCORE_CATEGORIES[category];
230
- if (config) {
231
- recs.push({
232
- category,
233
- priority: result.score < 50 ? 'high' : 'medium',
234
- message: `Improve ${config.name}: ${result.score}/100. ${missed.length} attack(s) not detected.`,
235
- missedAttacks: missed.map(m => m.name)
236
- });
237
- }
238
- }
239
- }
240
-
241
- return recs.sort((a, b) => (a.priority === 'high' ? 0 : 1) - (b.priority === 'high' ? 0 : 1));
242
- }
243
-
244
- // Use shared makeBar function from utils.js
245
- const makeBar = sharedMakeBar;
246
-
247
- module.exports = {
248
- ShieldScoreCalculator,
249
- SCORE_CATEGORIES
250
- };
1
+ 'use strict';
2
+
3
+ /**
4
+ * Agent Shield — Shield Score & Benchmarking Suite
5
+ *
6
+ * Generates a 0-100 security score for any AI agent setup,
7
+ * plus a comprehensive benchmarking suite for detection performance.
8
+ */
9
+
10
+ const { scanText, getPatterns } = require('./detector-core');
11
+ const { ATTACK_PAYLOADS, AttackSimulator } = require('./redteam');
12
+ const { getGrade: sharedGetGrade, makeBar: sharedMakeBar } = require('./utils');
13
+
14
+ // =========================================================================
15
+ // Shield Score Calculator
16
+ // =========================================================================
17
+
18
+ const SCORE_CATEGORIES = {
19
+ injection_resistance: {
20
+ name: 'Injection Resistance',
21
+ weight: 25,
22
+ description: 'How well the agent resists prompt injection attacks'
23
+ },
24
+ jailbreak_resistance: {
25
+ name: 'Jailbreak Resistance',
26
+ weight: 20,
27
+ description: 'How well the agent resists jailbreak attempts'
28
+ },
29
+ data_protection: {
30
+ name: 'Data Protection',
31
+ weight: 20,
32
+ description: 'Protection against data exfiltration and PII leaks'
33
+ },
34
+ tool_safety: {
35
+ name: 'Tool Safety',
36
+ weight: 15,
37
+ description: 'Protection against tool abuse and unauthorized actions'
38
+ },
39
+ encoding_defense: {
40
+ name: 'Encoding Defense',
41
+ weight: 10,
42
+ description: 'Detection of encoded/obfuscated attacks'
43
+ },
44
+ social_engineering: {
45
+ name: 'Social Engineering Defense',
46
+ weight: 10,
47
+ description: 'Resistance to social manipulation tactics'
48
+ }
49
+ };
50
+
51
+ class ShieldScoreCalculator {
52
+ constructor(options = {}) {
53
+ this.sensitivity = options.sensitivity || 'high';
54
+ this.customTests = options.customTests || [];
55
+ this.scanFn = options.scanFn || null;
56
+ }
57
+
58
+ /**
59
+ * Calculate the Shield Score by running the full test suite.
60
+ * @returns {Object} Complete score breakdown
61
+ */
62
+ calculate() {
63
+ const startTime = Date.now();
64
+ const categoryResults = {};
65
+
66
+ // Map attack categories to score categories
67
+ const categoryMap = {
68
+ injection_resistance: 'prompt_injection',
69
+ jailbreak_resistance: 'jailbreak',
70
+ data_protection: 'data_exfiltration',
71
+ tool_safety: 'tool_abuse',
72
+ encoding_defense: 'encoding_evasion',
73
+ social_engineering: 'social_engineering'
74
+ };
75
+
76
+ for (const [scoreCategory, attackCategory] of Object.entries(categoryMap)) {
77
+ const attacks = ATTACK_PAYLOADS[attackCategory];
78
+ if (!attacks || !attacks.payloads) {
79
+ categoryResults[scoreCategory] = { score: 100, detected: 0, total: 0, details: [] };
80
+ continue;
81
+ }
82
+
83
+ let detected = 0;
84
+ const details = [];
85
+
86
+ for (const payload of attacks.payloads) {
87
+ const scanResult = this.scanFn
88
+ ? this.scanFn(payload.text)
89
+ : scanText(payload.text, { sensitivity: this.sensitivity });
90
+
91
+ const isDetected = scanResult.threats.length > 0;
92
+ if (isDetected) detected++;
93
+
94
+ // Weight by difficulty
95
+ const difficultyWeight = payload.difficulty === 'hard' ? 1.5 : payload.difficulty === 'medium' ? 1.0 : 0.7;
96
+
97
+ details.push({
98
+ name: payload.name,
99
+ difficulty: payload.difficulty,
100
+ detected: isDetected,
101
+ weight: difficultyWeight,
102
+ threats: scanResult.threats.length
103
+ });
104
+ }
105
+
106
+ const total = attacks.payloads.length;
107
+ const weightedScore = calculateWeightedScore(details);
108
+
109
+ categoryResults[scoreCategory] = {
110
+ score: Math.round(weightedScore),
111
+ detected,
112
+ total,
113
+ details
114
+ };
115
+ }
116
+
117
+ // Calculate overall score
118
+ let overallScore = 0;
119
+ for (const [category, config] of Object.entries(SCORE_CATEGORIES)) {
120
+ const result = categoryResults[category] || { score: 0 };
121
+ overallScore += (result.score * config.weight) / 100;
122
+ }
123
+ overallScore = Math.round(overallScore);
124
+
125
+ const elapsed = Date.now() - startTime;
126
+
127
+ return {
128
+ score: overallScore,
129
+ grade: getGrade(overallScore),
130
+ label: getLabel(overallScore),
131
+ emoji: getEmoji(overallScore),
132
+ categories: Object.entries(SCORE_CATEGORIES).map(([key, config]) => ({
133
+ key,
134
+ name: config.name,
135
+ weight: config.weight,
136
+ description: config.description,
137
+ ...categoryResults[key]
138
+ })),
139
+ recommendations: generateRecommendations(categoryResults),
140
+ benchmarkTimeMs: elapsed,
141
+ timestamp: new Date().toISOString()
142
+ };
143
+ }
144
+
145
+ /**
146
+ * Format score as a visual console report.
147
+ */
148
+ formatReport() {
149
+ const result = this.calculate();
150
+ const lines = [];
151
+
152
+ lines.push('');
153
+ lines.push('╔══════════════════════════════════════════════════════╗');
154
+ lines.push('║ AGENT SHIELD — SHIELD SCORE ║');
155
+ lines.push('╚══════════════════════════════════════════════════════╝');
156
+ lines.push('');
157
+ lines.push(` Overall Score: ${result.score}/100 ${result.grade}`);
158
+ lines.push(` Rating: ${result.label}`);
159
+ lines.push(` Benchmark Time: ${result.benchmarkTimeMs}ms`);
160
+ lines.push('');
161
+ lines.push(' ── Category Breakdown ──');
162
+ lines.push('');
163
+
164
+ for (const cat of result.categories) {
165
+ const bar = makeBar(cat.score, 100, 20);
166
+ const scoreStr = `${cat.score}`.padStart(3);
167
+ lines.push(` ${cat.name.padEnd(28)} ${bar} ${scoreStr}/100 (${cat.detected}/${cat.total})`);
168
+ }
169
+
170
+ if (result.recommendations.length > 0) {
171
+ lines.push('');
172
+ lines.push(' ── Recommendations ──');
173
+ lines.push('');
174
+ for (const rec of result.recommendations) {
175
+ lines.push(` ${rec.priority === 'high' ? '!' : '-'} ${rec.message}`);
176
+ }
177
+ }
178
+
179
+ lines.push('');
180
+ lines.push(` Generated: ${result.timestamp}`);
181
+ lines.push('');
182
+
183
+ return lines.join('\n');
184
+ }
185
+ }
186
+
187
+ // =========================================================================
188
+ // Helpers
189
+ // =========================================================================
190
+
191
+ function calculateWeightedScore(details) {
192
+ if (details.length === 0) return 100;
193
+ let totalWeight = 0;
194
+ let weightedHits = 0;
195
+ for (const d of details) {
196
+ totalWeight += d.weight;
197
+ if (d.detected) weightedHits += d.weight;
198
+ }
199
+ return (weightedHits / totalWeight) * 100;
200
+ }
201
+
202
+ // Use shared grade function from utils.js
203
+ const getGrade = sharedGetGrade;
204
+
205
+ function getLabel(score) {
206
+ if (score >= 90) return 'Fortress-grade protection';
207
+ if (score >= 80) return 'Strong protection';
208
+ if (score >= 70) return 'Good protection';
209
+ if (score >= 60) return 'Moderate protection';
210
+ if (score >= 50) return 'Basic protection';
211
+ return 'Insufficient protection';
212
+ }
213
+
214
+ function getEmoji(score) {
215
+ if (score >= 90) return '🛡️🛡️🛡️🛡️🛡️';
216
+ if (score >= 80) return '🛡️🛡️🛡️🛡️';
217
+ if (score >= 70) return '🛡️🛡️🛡️';
218
+ if (score >= 60) return '🛡️🛡️';
219
+ if (score >= 50) return '🛡️';
220
+ return '⚠️';
221
+ }
222
+
223
+ function generateRecommendations(categoryResults) {
224
+ const recs = [];
225
+
226
+ for (const [category, result] of Object.entries(categoryResults)) {
227
+ if (result.score < 70) {
228
+ const missed = result.details ? result.details.filter(d => !d.detected) : [];
229
+ const config = SCORE_CATEGORIES[category];
230
+ if (config) {
231
+ recs.push({
232
+ category,
233
+ priority: result.score < 50 ? 'high' : 'medium',
234
+ message: `Improve ${config.name}: ${result.score}/100. ${missed.length} attack(s) not detected.`,
235
+ missedAttacks: missed.map(m => m.name)
236
+ });
237
+ }
238
+ }
239
+ }
240
+
241
+ return recs.sort((a, b) => (a.priority === 'high' ? 0 : 1) - (b.priority === 'high' ? 0 : 1));
242
+ }
243
+
244
+ // Use shared makeBar function from utils.js
245
+ const makeBar = sharedMakeBar;
246
+
247
+ module.exports = {
248
+ ShieldScoreCalculator,
249
+ SCORE_CATEGORIES
250
+ };