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.
- package/CHANGELOG.md +48 -0
- package/LICENSE +21 -21
- package/README.md +30 -37
- package/bin/agentshield-audit +51 -0
- package/package.json +7 -9
- package/src/adaptive.js +330 -330
- package/src/agent-intent.js +807 -0
- package/src/alert-tuning.js +480 -480
- package/src/audit-streaming.js +1 -1
- package/src/badges.js +196 -196
- package/src/behavioral-dna.js +12 -0
- package/src/canary.js +2 -3
- package/src/certification.js +563 -563
- package/src/circuit-breaker.js +2 -2
- package/src/confused-deputy.js +4 -0
- package/src/conversation.js +494 -494
- package/src/cross-turn.js +649 -0
- package/src/ctf.js +462 -462
- package/src/detector-core.js +71 -152
- package/src/document-scanner.js +795 -795
- package/src/drift-monitor.js +344 -0
- package/src/encoding.js +429 -429
- package/src/ensemble.js +523 -0
- package/src/enterprise.js +405 -405
- package/src/flight-recorder.js +2 -0
- package/src/i18n-patterns.js +523 -523
- package/src/index.js +19 -0
- package/src/main.js +79 -6
- package/src/mcp-guard.js +974 -0
- package/src/micro-model.js +762 -0
- package/src/ml-detector.js +316 -0
- package/src/model-finetuning.js +884 -884
- package/src/multimodal.js +296 -296
- package/src/nist-mapping.js +2 -2
- package/src/observability.js +330 -330
- package/src/openclaw.js +450 -450
- package/src/otel.js +544 -544
- package/src/owasp-2025.js +1 -1
- package/src/owasp-agentic.js +420 -0
- package/src/persistent-learning.js +677 -0
- package/src/plugin-marketplace.js +628 -628
- package/src/plugin-system.js +349 -349
- package/src/policy-extended.js +635 -635
- package/src/policy.js +443 -443
- package/src/prompt-leakage.js +2 -2
- package/src/real-attack-datasets.js +2 -2
- package/src/redteam-cli.js +439 -0
- package/src/self-training.js +772 -0
- package/src/smart-config.js +812 -0
- package/src/supply-chain-scanner.js +691 -0
- package/src/testing.js +5 -1
- package/src/threat-encyclopedia.js +629 -629
- package/src/threat-intel-network.js +1017 -1017
- package/src/token-analysis.js +467 -467
- package/src/tool-output-validator.js +354 -354
- package/src/watermark.js +1 -2
- package/types/index.d.ts +660 -0
package/src/audit-streaming.js
CHANGED
|
@@ -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:
|
|
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(``);
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
lines.push(``);
|
|
78
|
-
|
|
79
|
-
if (options.detectionRate) {
|
|
80
|
-
const color = parseFloat(options.detectionRate) >= 90 ? 'brightgreen' : 'yellow';
|
|
81
|
-
lines.push(``);
|
|
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(``);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
lines.push(``);
|
|
78
|
+
|
|
79
|
+
if (options.detectionRate) {
|
|
80
|
+
const color = parseFloat(options.detectionRate) >= 90 ? 'brightgreen' : 'yellow';
|
|
81
|
+
lines.push(``);
|
|
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
|
+
};
|
package/src/behavioral-dna.js
CHANGED
|
@@ -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
|
-
|
|
216
|
-
|
|
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({
|