agentshield-sdk 7.4.0 → 10.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 (57) hide show
  1. package/CHANGELOG.md +48 -0
  2. package/LICENSE +21 -21
  3. package/README.md +30 -37
  4. package/bin/agentshield-audit +51 -0
  5. package/package.json +7 -9
  6. package/src/adaptive.js +330 -330
  7. package/src/agent-intent.js +807 -0
  8. package/src/alert-tuning.js +480 -480
  9. package/src/audit-streaming.js +1 -1
  10. package/src/badges.js +196 -196
  11. package/src/behavioral-dna.js +12 -0
  12. package/src/canary.js +2 -3
  13. package/src/certification.js +563 -563
  14. package/src/circuit-breaker.js +2 -2
  15. package/src/confused-deputy.js +4 -0
  16. package/src/conversation.js +494 -494
  17. package/src/cross-turn.js +649 -0
  18. package/src/ctf.js +462 -462
  19. package/src/detector-core.js +71 -152
  20. package/src/document-scanner.js +795 -795
  21. package/src/drift-monitor.js +344 -0
  22. package/src/encoding.js +429 -429
  23. package/src/ensemble.js +523 -0
  24. package/src/enterprise.js +405 -405
  25. package/src/flight-recorder.js +2 -0
  26. package/src/i18n-patterns.js +523 -523
  27. package/src/index.js +19 -0
  28. package/src/main.js +79 -6
  29. package/src/mcp-guard.js +974 -0
  30. package/src/micro-model.js +762 -0
  31. package/src/ml-detector.js +316 -0
  32. package/src/model-finetuning.js +884 -884
  33. package/src/multimodal.js +296 -296
  34. package/src/nist-mapping.js +2 -2
  35. package/src/observability.js +330 -330
  36. package/src/openclaw.js +450 -450
  37. package/src/otel.js +544 -544
  38. package/src/owasp-2025.js +1 -1
  39. package/src/owasp-agentic.js +420 -0
  40. package/src/persistent-learning.js +677 -0
  41. package/src/plugin-marketplace.js +628 -628
  42. package/src/plugin-system.js +349 -349
  43. package/src/policy-extended.js +635 -635
  44. package/src/policy.js +443 -443
  45. package/src/prompt-leakage.js +2 -2
  46. package/src/real-attack-datasets.js +2 -2
  47. package/src/redteam-cli.js +439 -0
  48. package/src/self-training.js +772 -0
  49. package/src/smart-config.js +812 -0
  50. package/src/supply-chain-scanner.js +691 -0
  51. package/src/testing.js +5 -1
  52. package/src/threat-encyclopedia.js +629 -629
  53. package/src/threat-intel-network.js +1017 -1017
  54. package/src/token-analysis.js +467 -467
  55. package/src/tool-output-validator.js +354 -354
  56. package/src/watermark.js +1 -2
  57. package/types/index.d.ts +660 -0
@@ -225,7 +225,7 @@ class SplunkTransport extends AuditTransport {
225
225
  hostname: parsed.hostname, port: parsed.port,
226
226
  path: parsed.pathname, method: 'POST',
227
227
  headers: { ...headers, 'Content-Length': Buffer.byteLength(body) },
228
- rejectUnauthorized: false, timeout: 10000
228
+ rejectUnauthorized: true, timeout: 10000
229
229
  }, (res) => {
230
230
  let data = '';
231
231
  res.on('data', c => data += c);
package/src/badges.js CHANGED
@@ -1,196 +1,196 @@
1
- 'use strict';
2
-
3
- /**
4
- * Agent Shield — Integration Badges & GitHub Action Support
5
- *
6
- * Generate SVG badges for READMEs and CI/CD pipelines.
7
- */
8
-
9
- // =========================================================================
10
- // Badge Generator
11
- // =========================================================================
12
-
13
- class BadgeGenerator {
14
- /**
15
- * Generate a Shield Score badge in SVG.
16
- */
17
- static shieldScore(score) {
18
- const color = score >= 90 ? '22c55e' : score >= 70 ? 'eab308' : score >= 50 ? 'f97316' : 'ef4444';
19
- const grade = score >= 95 ? 'A+' : score >= 90 ? 'A' : score >= 80 ? 'B' : score >= 70 ? 'C' : score >= 50 ? 'D' : 'F';
20
- return BadgeGenerator.generateSVG('shield score', `${score} (${grade})`, color);
21
- }
22
-
23
- /**
24
- * Generate a protection status badge.
25
- */
26
- static protectionStatus(enabled = true) {
27
- return BadgeGenerator.generateSVG(
28
- 'agent shield',
29
- enabled ? 'protected' : 'unprotected',
30
- enabled ? '3b82f6' : 'ef4444'
31
- );
32
- }
33
-
34
- /**
35
- * Generate a detection rate badge.
36
- */
37
- static detectionRate(rate) {
38
- const num = parseFloat(rate);
39
- const color = num >= 90 ? '22c55e' : num >= 70 ? 'eab308' : 'ef4444';
40
- return BadgeGenerator.generateSVG('detection rate', `${num}%`, color);
41
- }
42
-
43
- /**
44
- * Generate a scan count badge.
45
- */
46
- static scanCount(count) {
47
- return BadgeGenerator.generateSVG('scans', count.toLocaleString(), '06b6d4');
48
- }
49
-
50
- /**
51
- * Generate a compliance badge.
52
- */
53
- static compliance(framework, rate) {
54
- const num = parseFloat(rate);
55
- const color = num >= 80 ? '22c55e' : num >= 50 ? 'eab308' : 'ef4444';
56
- return BadgeGenerator.generateSVG(framework, `${num}%`, color);
57
- }
58
-
59
- /**
60
- * Generate a custom badge.
61
- */
62
- static custom(label, value, color = '3b82f6') {
63
- return BadgeGenerator.generateSVG(label, value, color);
64
- }
65
-
66
- /**
67
- * Generate Markdown badge links for README.
68
- */
69
- static markdownBadges(options = {}) {
70
- const lines = [];
71
-
72
- if (options.score !== undefined) {
73
- const color = options.score >= 90 ? 'brightgreen' : options.score >= 70 ? 'yellow' : options.score >= 50 ? 'orange' : 'red';
74
- lines.push(`![Shield Score](https://img.shields.io/badge/shield_score-${options.score}-${color}?style=flat-square&logo=data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0id2hpdGUiPjxwYXRoIGQ9Ik0xMiAyMnM4LTQgOC0xMFY1bC04LTMtOCAzdjdjMCA2IDggMTAgOCAxMHoiLz48L3N2Zz4=)`);
75
- }
76
-
77
- lines.push(`![Agent Shield](https://img.shields.io/badge/protected_by-agent_shield-blue?style=flat-square)`);
78
-
79
- if (options.detectionRate) {
80
- const color = parseFloat(options.detectionRate) >= 90 ? 'brightgreen' : 'yellow';
81
- lines.push(`![Detection Rate](https://img.shields.io/badge/detection_rate-${options.detectionRate}%25-${color}?style=flat-square)`);
82
- }
83
-
84
- return lines.join('\n');
85
- }
86
-
87
- /**
88
- * Core SVG badge generator.
89
- */
90
- static generateSVG(label, value, color) {
91
- const labelWidth = label.length * 7 + 12;
92
- const valueWidth = String(value).length * 7 + 12;
93
- const totalWidth = labelWidth + valueWidth;
94
-
95
- return `<svg xmlns="http://www.w3.org/2000/svg" width="${totalWidth}" height="20" role="img">
96
- <title>${label}: ${value}</title>
97
- <linearGradient id="s" x2="0" y2="100%">
98
- <stop offset="0" stop-color="#bbb" stop-opacity=".1"/>
99
- <stop offset="1" stop-opacity=".1"/>
100
- </linearGradient>
101
- <clipPath id="r"><rect width="${totalWidth}" height="20" rx="3" fill="#fff"/></clipPath>
102
- <g clip-path="url(#r)">
103
- <rect width="${labelWidth}" height="20" fill="#555"/>
104
- <rect x="${labelWidth}" width="${valueWidth}" height="20" fill="#${color}"/>
105
- <rect width="${totalWidth}" height="20" fill="url(#s)"/>
106
- </g>
107
- <g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="11">
108
- <text x="${labelWidth / 2}" y="14" fill="#010101" fill-opacity=".3">${label}</text>
109
- <text x="${labelWidth / 2}" y="13">${label}</text>
110
- <text x="${labelWidth + valueWidth / 2}" y="14" fill="#010101" fill-opacity=".3">${value}</text>
111
- <text x="${labelWidth + valueWidth / 2}" y="13">${value}</text>
112
- </g>
113
- </svg>`;
114
- }
115
- }
116
-
117
- // =========================================================================
118
- // GitHub Action Output
119
- // =========================================================================
120
-
121
- class GitHubActionReporter {
122
- constructor() {
123
- this.annotations = [];
124
- }
125
-
126
- /**
127
- * Report scan results as GitHub Action annotations.
128
- */
129
- reportScan(result, file = '', line = 0) {
130
- if (!result.threats || result.threats.length === 0) return;
131
-
132
- for (const threat of result.threats) {
133
- const level = threat.severity === 'critical' || threat.severity === 'high' ? 'error' : 'warning';
134
- const msg = `[Agent Shield] ${threat.description} (${threat.severity})`;
135
-
136
- // GitHub Actions annotation format
137
- if (file) {
138
- console.log(`::${level} file=${file},line=${line}::${msg}`);
139
- } else {
140
- console.log(`::${level}::${msg}`);
141
- }
142
-
143
- this.annotations.push({ level, file, line, message: msg });
144
- }
145
- }
146
-
147
- /**
148
- * Set GitHub Action output variables.
149
- */
150
- setOutputs(results) {
151
- const total = results.threats ? results.threats.length : 0;
152
- const blocked = results.blocked || false;
153
- const status = results.status || 'unknown';
154
-
155
- // Use GITHUB_OUTPUT env file (modern) with fallback to deprecated ::set-output
156
- const githubOutput = process.env.GITHUB_OUTPUT;
157
- if (githubOutput) {
158
- const fs = require('fs');
159
- fs.appendFileSync(githubOutput, `threat_count=${total}\n`);
160
- fs.appendFileSync(githubOutput, `status=${status}\n`);
161
- fs.appendFileSync(githubOutput, `blocked=${blocked}\n`);
162
- } else {
163
- console.log(`::set-output name=threat_count::${total}`);
164
- console.log(`::set-output name=status::${status}`);
165
- console.log(`::set-output name=blocked::${blocked}`);
166
- }
167
- }
168
-
169
- /**
170
- * Create a summary for GitHub Actions.
171
- */
172
- createSummary(shieldScore, scanResults) {
173
- const lines = [];
174
- lines.push('## Agent Shield Scan Results\n');
175
- lines.push(`| Metric | Value |`);
176
- lines.push(`|--------|-------|`);
177
-
178
- if (shieldScore) {
179
- lines.push(`| Shield Score | ${shieldScore.score}/100 (${shieldScore.grade}) |`);
180
- }
181
-
182
- if (scanResults) {
183
- lines.push(`| Status | ${scanResults.status} |`);
184
- lines.push(`| Threats | ${scanResults.threats ? scanResults.threats.length : 0} |`);
185
- lines.push(`| Blocked | ${scanResults.blocked ? 'Yes' : 'No'} |`);
186
- }
187
-
188
- lines.push('');
189
- return lines.join('\n');
190
- }
191
- }
192
-
193
- module.exports = {
194
- BadgeGenerator,
195
- GitHubActionReporter
196
- };
1
+ 'use strict';
2
+
3
+ /**
4
+ * Agent Shield — Integration Badges & GitHub Action Support
5
+ *
6
+ * Generate SVG badges for READMEs and CI/CD pipelines.
7
+ */
8
+
9
+ // =========================================================================
10
+ // Badge Generator
11
+ // =========================================================================
12
+
13
+ class BadgeGenerator {
14
+ /**
15
+ * Generate a Shield Score badge in SVG.
16
+ */
17
+ static shieldScore(score) {
18
+ const color = score >= 90 ? '22c55e' : score >= 70 ? 'eab308' : score >= 50 ? 'f97316' : 'ef4444';
19
+ const grade = score >= 95 ? 'A+' : score >= 90 ? 'A' : score >= 80 ? 'B' : score >= 70 ? 'C' : score >= 50 ? 'D' : 'F';
20
+ return BadgeGenerator.generateSVG('shield score', `${score} (${grade})`, color);
21
+ }
22
+
23
+ /**
24
+ * Generate a protection status badge.
25
+ */
26
+ static protectionStatus(enabled = true) {
27
+ return BadgeGenerator.generateSVG(
28
+ 'agent shield',
29
+ enabled ? 'protected' : 'unprotected',
30
+ enabled ? '3b82f6' : 'ef4444'
31
+ );
32
+ }
33
+
34
+ /**
35
+ * Generate a detection rate badge.
36
+ */
37
+ static detectionRate(rate) {
38
+ const num = parseFloat(rate);
39
+ const color = num >= 90 ? '22c55e' : num >= 70 ? 'eab308' : 'ef4444';
40
+ return BadgeGenerator.generateSVG('detection rate', `${num}%`, color);
41
+ }
42
+
43
+ /**
44
+ * Generate a scan count badge.
45
+ */
46
+ static scanCount(count) {
47
+ return BadgeGenerator.generateSVG('scans', count.toLocaleString(), '06b6d4');
48
+ }
49
+
50
+ /**
51
+ * Generate a compliance badge.
52
+ */
53
+ static compliance(framework, rate) {
54
+ const num = parseFloat(rate);
55
+ const color = num >= 80 ? '22c55e' : num >= 50 ? 'eab308' : 'ef4444';
56
+ return BadgeGenerator.generateSVG(framework, `${num}%`, color);
57
+ }
58
+
59
+ /**
60
+ * Generate a custom badge.
61
+ */
62
+ static custom(label, value, color = '3b82f6') {
63
+ return BadgeGenerator.generateSVG(label, value, color);
64
+ }
65
+
66
+ /**
67
+ * Generate Markdown badge links for README.
68
+ */
69
+ static markdownBadges(options = {}) {
70
+ const lines = [];
71
+
72
+ if (options.score !== undefined) {
73
+ const color = options.score >= 90 ? 'brightgreen' : options.score >= 70 ? 'yellow' : options.score >= 50 ? 'orange' : 'red';
74
+ lines.push(`![Shield Score](https://img.shields.io/badge/shield_score-${options.score}-${color}?style=flat-square&logo=data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0id2hpdGUiPjxwYXRoIGQ9Ik0xMiAyMnM4LTQgOC0xMFY1bC04LTMtOCAzdjdjMCA2IDggMTAgOCAxMHoiLz48L3N2Zz4=)`);
75
+ }
76
+
77
+ lines.push(`![Agent Shield](https://img.shields.io/badge/protected_by-agent_shield-blue?style=flat-square)`);
78
+
79
+ if (options.detectionRate) {
80
+ const color = parseFloat(options.detectionRate) >= 90 ? 'brightgreen' : 'yellow';
81
+ lines.push(`![Detection Rate](https://img.shields.io/badge/detection_rate-${options.detectionRate}%25-${color}?style=flat-square)`);
82
+ }
83
+
84
+ return lines.join('\n');
85
+ }
86
+
87
+ /**
88
+ * Core SVG badge generator.
89
+ */
90
+ static generateSVG(label, value, color) {
91
+ const labelWidth = label.length * 7 + 12;
92
+ const valueWidth = String(value).length * 7 + 12;
93
+ const totalWidth = labelWidth + valueWidth;
94
+
95
+ return `<svg xmlns="http://www.w3.org/2000/svg" width="${totalWidth}" height="20" role="img">
96
+ <title>${label}: ${value}</title>
97
+ <linearGradient id="s" x2="0" y2="100%">
98
+ <stop offset="0" stop-color="#bbb" stop-opacity=".1"/>
99
+ <stop offset="1" stop-opacity=".1"/>
100
+ </linearGradient>
101
+ <clipPath id="r"><rect width="${totalWidth}" height="20" rx="3" fill="#fff"/></clipPath>
102
+ <g clip-path="url(#r)">
103
+ <rect width="${labelWidth}" height="20" fill="#555"/>
104
+ <rect x="${labelWidth}" width="${valueWidth}" height="20" fill="#${color}"/>
105
+ <rect width="${totalWidth}" height="20" fill="url(#s)"/>
106
+ </g>
107
+ <g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="11">
108
+ <text x="${labelWidth / 2}" y="14" fill="#010101" fill-opacity=".3">${label}</text>
109
+ <text x="${labelWidth / 2}" y="13">${label}</text>
110
+ <text x="${labelWidth + valueWidth / 2}" y="14" fill="#010101" fill-opacity=".3">${value}</text>
111
+ <text x="${labelWidth + valueWidth / 2}" y="13">${value}</text>
112
+ </g>
113
+ </svg>`;
114
+ }
115
+ }
116
+
117
+ // =========================================================================
118
+ // GitHub Action Output
119
+ // =========================================================================
120
+
121
+ class GitHubActionReporter {
122
+ constructor() {
123
+ this.annotations = [];
124
+ }
125
+
126
+ /**
127
+ * Report scan results as GitHub Action annotations.
128
+ */
129
+ reportScan(result, file = '', line = 0) {
130
+ if (!result.threats || result.threats.length === 0) return;
131
+
132
+ for (const threat of result.threats) {
133
+ const level = threat.severity === 'critical' || threat.severity === 'high' ? 'error' : 'warning';
134
+ const msg = `[Agent Shield] ${threat.description} (${threat.severity})`;
135
+
136
+ // GitHub Actions annotation format
137
+ if (file) {
138
+ console.log(`::${level} file=${file},line=${line}::${msg}`);
139
+ } else {
140
+ console.log(`::${level}::${msg}`);
141
+ }
142
+
143
+ this.annotations.push({ level, file, line, message: msg });
144
+ }
145
+ }
146
+
147
+ /**
148
+ * Set GitHub Action output variables.
149
+ */
150
+ setOutputs(results) {
151
+ const total = results.threats ? results.threats.length : 0;
152
+ const blocked = results.blocked || false;
153
+ const status = results.status || 'unknown';
154
+
155
+ // Use GITHUB_OUTPUT env file (modern) with fallback to deprecated ::set-output
156
+ const githubOutput = process.env.GITHUB_OUTPUT;
157
+ if (githubOutput) {
158
+ const fs = require('fs');
159
+ fs.appendFileSync(githubOutput, `threat_count=${total}\n`);
160
+ fs.appendFileSync(githubOutput, `status=${status}\n`);
161
+ fs.appendFileSync(githubOutput, `blocked=${blocked}\n`);
162
+ } else {
163
+ console.log(`::set-output name=threat_count::${total}`);
164
+ console.log(`::set-output name=status::${status}`);
165
+ console.log(`::set-output name=blocked::${blocked}`);
166
+ }
167
+ }
168
+
169
+ /**
170
+ * Create a summary for GitHub Actions.
171
+ */
172
+ createSummary(shieldScore, scanResults) {
173
+ const lines = [];
174
+ lines.push('## Agent Shield Scan Results\n');
175
+ lines.push(`| Metric | Value |`);
176
+ lines.push(`|--------|-------|`);
177
+
178
+ if (shieldScore) {
179
+ lines.push(`| Shield Score | ${shieldScore.score}/100 (${shieldScore.grade}) |`);
180
+ }
181
+
182
+ if (scanResults) {
183
+ lines.push(`| Status | ${scanResults.status} |`);
184
+ lines.push(`| Threats | ${scanResults.threats ? scanResults.threats.length : 0} |`);
185
+ lines.push(`| Blocked | ${scanResults.blocked ? 'Yes' : 'No'} |`);
186
+ }
187
+
188
+ lines.push('');
189
+ return lines.join('\n');
190
+ }
191
+ }
192
+
193
+ module.exports = {
194
+ BadgeGenerator,
195
+ GitHubActionReporter
196
+ };
@@ -316,6 +316,18 @@ class BehavioralDNA {
316
316
 
317
317
  const m = mean(values);
318
318
  const sd = stdDev(values);
319
+ // If stddev is 0 (constant values), only flag if value differs from learned constant
320
+ if (sd === 0) {
321
+ if (value !== m) {
322
+ deviations.push({
323
+ feature: f, type: 'numeric', value,
324
+ expected: { mean: _round(m), stdDev: 0 },
325
+ zScore: Infinity, direction: value > m ? 'above' : 'below',
326
+ severity: 'high'
327
+ });
328
+ }
329
+ continue;
330
+ }
319
331
  const z = zScore(value, m, sd);
320
332
 
321
333
  if (Math.abs(z) > this.anomalyThreshold) {
package/src/canary.js CHANGED
@@ -212,9 +212,8 @@ class PromptLeakDetector {
212
212
  } else {
213
213
  // Partial match: check if significant chunks of the system prompt appear
214
214
  const matchedChunks = this._systemPromptChunks.filter(chunk => text.includes(chunk));
215
- const matchRatio = this._systemPromptChunks.length > 0
216
- ? matchedChunks.length / this._systemPromptChunks.length
217
- : 0;
215
+ if (this._systemPromptChunks.length === 0) return { leaked: false, leaks: [] };
216
+ const matchRatio = matchedChunks.length / this._systemPromptChunks.length;
218
217
 
219
218
  if (matchRatio >= this.similarityThreshold) {
220
219
  leaks.push({