agentshield-sdk 8.0.0 → 11.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 (60) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/LICENSE +21 -21
  3. package/README.md +257 -50
  4. package/bin/agentshield-audit +51 -0
  5. package/package.json +7 -10
  6. package/src/adaptive.js +330 -330
  7. package/src/alert-tuning.js +480 -480
  8. package/src/attack-surface.js +408 -0
  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/continuous-security.js +237 -0
  17. package/src/conversation.js +494 -494
  18. package/src/cross-turn.js +3 -17
  19. package/src/ctf.js +462 -462
  20. package/src/detector-core.js +845 -105
  21. package/src/document-scanner.js +795 -795
  22. package/src/drift-monitor.js +356 -0
  23. package/src/encoding.js +429 -429
  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/intent-binding.js +314 -0
  29. package/src/intent-graph.js +381 -0
  30. package/src/main.js +134 -41
  31. package/src/mcp-guard.js +1532 -0
  32. package/src/message-integrity.js +226 -0
  33. package/src/micro-model.js +939 -0
  34. package/src/ml-detector.js +316 -0
  35. package/src/model-finetuning.js +884 -884
  36. package/src/multimodal.js +296 -296
  37. package/src/nist-mapping.js +2 -2
  38. package/src/observability.js +330 -330
  39. package/src/openclaw.js +450 -450
  40. package/src/otel.js +544 -544
  41. package/src/owasp-2025.js +1 -1
  42. package/src/owasp-agentic.js +420 -0
  43. package/src/plugin-marketplace.js +628 -628
  44. package/src/plugin-system.js +349 -349
  45. package/src/policy-extended.js +635 -635
  46. package/src/policy.js +443 -443
  47. package/src/prompt-hardening.js +195 -0
  48. package/src/prompt-leakage.js +2 -2
  49. package/src/real-attack-datasets.js +2 -2
  50. package/src/redteam-cli.js +440 -0
  51. package/src/self-training.js +586 -631
  52. package/src/semantic-isolation.js +303 -0
  53. package/src/sota-benchmark.js +491 -0
  54. package/src/supply-chain-scanner.js +889 -0
  55. package/src/testing.js +5 -1
  56. package/src/threat-encyclopedia.js +629 -629
  57. package/src/threat-intel-network.js +1017 -1017
  58. package/src/token-analysis.js +467 -467
  59. package/src/tool-output-validator.js +354 -354
  60. package/src/watermark.js +1 -2
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({