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
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Agent Shield — Agent Behavior Profiling (v3.0)
|
|
5
|
+
*
|
|
6
|
+
* Establishes baselines for normal agent behavior and detects anomalies
|
|
7
|
+
* that may indicate compromise, drift, or attack influence.
|
|
8
|
+
*
|
|
9
|
+
* Tracks: response patterns, tool usage, topic distribution, timing,
|
|
10
|
+
* output length, sentiment shifts, and more.
|
|
11
|
+
*
|
|
12
|
+
* All processing runs locally — no data ever leaves your environment.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
// =========================================================================
|
|
16
|
+
// STATISTICAL HELPERS
|
|
17
|
+
// =========================================================================
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Calculate mean of an array.
|
|
21
|
+
* @param {number[]} arr
|
|
22
|
+
* @returns {number}
|
|
23
|
+
*/
|
|
24
|
+
function mean(arr) {
|
|
25
|
+
return arr.length > 0 ? arr.reduce((a, b) => a + b, 0) / arr.length : 0;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Calculate standard deviation.
|
|
30
|
+
* @param {number[]} arr
|
|
31
|
+
* @returns {number}
|
|
32
|
+
*/
|
|
33
|
+
function stdDev(arr) {
|
|
34
|
+
if (arr.length < 2) return 0;
|
|
35
|
+
const m = mean(arr);
|
|
36
|
+
const squaredDiffs = arr.map(x => (x - m) ** 2);
|
|
37
|
+
return Math.sqrt(squaredDiffs.reduce((a, b) => a + b, 0) / (arr.length - 1));
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Check if a value is anomalous (beyond N standard deviations from mean).
|
|
42
|
+
* @param {number} value
|
|
43
|
+
* @param {number} m - Mean.
|
|
44
|
+
* @param {number} sd - Standard deviation.
|
|
45
|
+
* @param {number} [threshold=2] - Number of standard deviations.
|
|
46
|
+
* @returns {boolean}
|
|
47
|
+
*/
|
|
48
|
+
function isAnomaly(value, m, sd, threshold = 2) {
|
|
49
|
+
if (sd === 0) return value !== m;
|
|
50
|
+
return Math.abs(value - m) > threshold * sd;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// =========================================================================
|
|
54
|
+
// BEHAVIOR PROFILE
|
|
55
|
+
// =========================================================================
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Maintains a statistical profile of agent behavior.
|
|
59
|
+
*/
|
|
60
|
+
class BehaviorProfile {
|
|
61
|
+
/**
|
|
62
|
+
* @param {object} [options]
|
|
63
|
+
* @param {number} [options.windowSize=200] - Number of observations to maintain.
|
|
64
|
+
* @param {number} [options.learningPeriod=20] - Observations before anomaly detection activates.
|
|
65
|
+
* @param {number} [options.anomalyThreshold=2.5] - Standard deviations for anomaly detection.
|
|
66
|
+
*/
|
|
67
|
+
constructor(options = {}) {
|
|
68
|
+
this.windowSize = options.windowSize || 200;
|
|
69
|
+
this.learningPeriod = options.learningPeriod || 20;
|
|
70
|
+
this.anomalyThreshold = options.anomalyThreshold || 2.5;
|
|
71
|
+
|
|
72
|
+
this._metrics = {
|
|
73
|
+
responseLength: [],
|
|
74
|
+
responseTime: [],
|
|
75
|
+
toolCallCount: [],
|
|
76
|
+
threatScore: [],
|
|
77
|
+
topicEntropy: []
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
this._toolUsage = {};
|
|
81
|
+
this._topicDistribution = {};
|
|
82
|
+
this._totalObservations = 0;
|
|
83
|
+
this._anomalies = [];
|
|
84
|
+
|
|
85
|
+
console.log('[Agent Shield] BehaviorProfile initialized (windowSize: %d, learningPeriod: %d)', this.windowSize, this.learningPeriod);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Record an observation of agent behavior.
|
|
90
|
+
*
|
|
91
|
+
* @param {object} observation
|
|
92
|
+
* @param {number} [observation.responseLength] - Length of agent response.
|
|
93
|
+
* @param {number} [observation.responseTimeMs] - Time taken to respond.
|
|
94
|
+
* @param {string[]} [observation.toolsCalled] - Tools used in this turn.
|
|
95
|
+
* @param {number} [observation.threatScore] - Threat score from scanning.
|
|
96
|
+
* @param {string} [observation.topic] - Detected topic/category.
|
|
97
|
+
* @returns {object} { anomalies: Array, isLearning: boolean }
|
|
98
|
+
*/
|
|
99
|
+
record(observation) {
|
|
100
|
+
this._totalObservations++;
|
|
101
|
+
|
|
102
|
+
// Record metrics
|
|
103
|
+
if (observation.responseLength !== undefined) {
|
|
104
|
+
this._addMetric('responseLength', observation.responseLength);
|
|
105
|
+
}
|
|
106
|
+
if (observation.responseTimeMs !== undefined) {
|
|
107
|
+
this._addMetric('responseTime', observation.responseTimeMs);
|
|
108
|
+
}
|
|
109
|
+
if (observation.toolsCalled) {
|
|
110
|
+
this._addMetric('toolCallCount', observation.toolsCalled.length);
|
|
111
|
+
for (const tool of observation.toolsCalled) {
|
|
112
|
+
this._toolUsage[tool] = (this._toolUsage[tool] || 0) + 1;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
if (observation.threatScore !== undefined) {
|
|
116
|
+
this._addMetric('threatScore', observation.threatScore);
|
|
117
|
+
}
|
|
118
|
+
if (observation.topic) {
|
|
119
|
+
this._topicDistribution[observation.topic] = (this._topicDistribution[observation.topic] || 0) + 1;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// Check for anomalies (only after learning period)
|
|
123
|
+
const isLearning = this._totalObservations < this.learningPeriod;
|
|
124
|
+
const anomalies = isLearning ? [] : this._detectAnomalies(observation);
|
|
125
|
+
|
|
126
|
+
if (anomalies.length > 0) {
|
|
127
|
+
this._anomalies.push({
|
|
128
|
+
timestamp: Date.now(),
|
|
129
|
+
observation: this._totalObservations,
|
|
130
|
+
anomalies
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
return { anomalies, isLearning };
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Get the current behavior baseline.
|
|
139
|
+
* @returns {object}
|
|
140
|
+
*/
|
|
141
|
+
getBaseline() {
|
|
142
|
+
const baseline = {};
|
|
143
|
+
for (const [metric, values] of Object.entries(this._metrics)) {
|
|
144
|
+
if (values.length > 0) {
|
|
145
|
+
baseline[metric] = {
|
|
146
|
+
mean: Math.round(mean(values) * 100) / 100,
|
|
147
|
+
stdDev: Math.round(stdDev(values) * 100) / 100,
|
|
148
|
+
min: Math.min(...values),
|
|
149
|
+
max: Math.max(...values),
|
|
150
|
+
samples: values.length
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
return baseline;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Get a full behavior report.
|
|
159
|
+
* @returns {object}
|
|
160
|
+
*/
|
|
161
|
+
getReport() {
|
|
162
|
+
return {
|
|
163
|
+
totalObservations: this._totalObservations,
|
|
164
|
+
isLearning: this._totalObservations < this.learningPeriod,
|
|
165
|
+
baseline: this.getBaseline(),
|
|
166
|
+
toolUsage: { ...this._toolUsage },
|
|
167
|
+
topicDistribution: { ...this._topicDistribution },
|
|
168
|
+
anomalyCount: this._anomalies.length,
|
|
169
|
+
recentAnomalies: this._anomalies.slice(-10),
|
|
170
|
+
riskLevel: this._calculateRiskLevel()
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Check if the agent appears to be behaving normally.
|
|
176
|
+
* @returns {object} { normal: boolean, riskLevel, concerns: string[] }
|
|
177
|
+
*/
|
|
178
|
+
healthCheck() {
|
|
179
|
+
const concerns = [];
|
|
180
|
+
const report = this.getReport();
|
|
181
|
+
|
|
182
|
+
if (report.isLearning) {
|
|
183
|
+
return { normal: true, riskLevel: 'unknown', concerns: ['Still in learning period.'] };
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// Check for sudden tool usage changes
|
|
187
|
+
const totalToolCalls = Object.values(this._toolUsage).reduce((a, b) => a + b, 0);
|
|
188
|
+
if (totalToolCalls > 0) {
|
|
189
|
+
for (const [tool, count] of Object.entries(this._toolUsage)) {
|
|
190
|
+
const ratio = count / totalToolCalls;
|
|
191
|
+
if (ratio > 0.7 && totalToolCalls > 10) {
|
|
192
|
+
concerns.push(`Tool "${tool}" dominates usage at ${(ratio * 100).toFixed(0)}%.`);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// Check for high threat score trend
|
|
198
|
+
const recentThreats = this._metrics.threatScore.slice(-20);
|
|
199
|
+
if (recentThreats.length >= 5 && mean(recentThreats) > 0.5) {
|
|
200
|
+
concerns.push('Recent threat scores are elevated.');
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// Check for anomaly frequency
|
|
204
|
+
const recentAnomalies = this._anomalies.filter(a => Date.now() - a.timestamp < 300000);
|
|
205
|
+
if (recentAnomalies.length > 5) {
|
|
206
|
+
concerns.push(`${recentAnomalies.length} anomalies in the last 5 minutes.`);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
return {
|
|
210
|
+
normal: concerns.length === 0,
|
|
211
|
+
riskLevel: report.riskLevel,
|
|
212
|
+
concerns
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/** Reset the profile. */
|
|
217
|
+
reset() {
|
|
218
|
+
for (const key of Object.keys(this._metrics)) {
|
|
219
|
+
this._metrics[key] = [];
|
|
220
|
+
}
|
|
221
|
+
this._toolUsage = {};
|
|
222
|
+
this._topicDistribution = {};
|
|
223
|
+
this._totalObservations = 0;
|
|
224
|
+
this._anomalies = [];
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/** @private */
|
|
228
|
+
_addMetric(name, value) {
|
|
229
|
+
if (!this._metrics[name]) this._metrics[name] = [];
|
|
230
|
+
this._metrics[name].push(value);
|
|
231
|
+
if (this._metrics[name].length > this.windowSize) {
|
|
232
|
+
this._metrics[name].shift();
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/** @private */
|
|
237
|
+
_detectAnomalies(observation) {
|
|
238
|
+
const anomalies = [];
|
|
239
|
+
|
|
240
|
+
const checks = [
|
|
241
|
+
{ metric: 'responseLength', value: observation.responseLength, label: 'Response length' },
|
|
242
|
+
{ metric: 'responseTime', value: observation.responseTimeMs, label: 'Response time' },
|
|
243
|
+
{ metric: 'toolCallCount', value: observation.toolsCalled ? observation.toolsCalled.length : undefined, label: 'Tool call count' },
|
|
244
|
+
{ metric: 'threatScore', value: observation.threatScore, label: 'Threat score' }
|
|
245
|
+
];
|
|
246
|
+
|
|
247
|
+
for (const check of checks) {
|
|
248
|
+
if (check.value === undefined) continue;
|
|
249
|
+
|
|
250
|
+
const values = this._metrics[check.metric];
|
|
251
|
+
if (values.length < this.learningPeriod) continue;
|
|
252
|
+
|
|
253
|
+
const m = mean(values.slice(0, -1)); // Exclude current observation
|
|
254
|
+
const sd = stdDev(values.slice(0, -1));
|
|
255
|
+
|
|
256
|
+
if (isAnomaly(check.value, m, sd, this.anomalyThreshold)) {
|
|
257
|
+
const zScore = sd > 0 ? Math.round(((check.value - m) / sd) * 100) / 100 : 0;
|
|
258
|
+
anomalies.push({
|
|
259
|
+
metric: check.metric,
|
|
260
|
+
label: check.label,
|
|
261
|
+
value: check.value,
|
|
262
|
+
expected: { mean: Math.round(m * 100) / 100, stdDev: Math.round(sd * 100) / 100 },
|
|
263
|
+
zScore,
|
|
264
|
+
direction: check.value > m ? 'above' : 'below'
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
return anomalies;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
/** @private */
|
|
273
|
+
_calculateRiskLevel() {
|
|
274
|
+
if (this._totalObservations < this.learningPeriod) return 'unknown';
|
|
275
|
+
|
|
276
|
+
const recentAnomalies = this._anomalies.filter(a => Date.now() - a.timestamp < 600000);
|
|
277
|
+
if (recentAnomalies.length > 10) return 'critical';
|
|
278
|
+
if (recentAnomalies.length > 5) return 'high';
|
|
279
|
+
if (recentAnomalies.length > 2) return 'medium';
|
|
280
|
+
if (recentAnomalies.length > 0) return 'low';
|
|
281
|
+
return 'normal';
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
// =========================================================================
|
|
286
|
+
// EXPORTS
|
|
287
|
+
// =========================================================================
|
|
288
|
+
|
|
289
|
+
module.exports = { BehaviorProfile, mean, stdDev, isAnomaly };
|