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
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Agent Shield — ML-Powered Detection
|
|
5
|
+
*
|
|
6
|
+
* Bridge module that integrates the agentshield-ml ONNX inference engine
|
|
7
|
+
* into the main SDK. ML detection is available to all users.
|
|
8
|
+
*
|
|
9
|
+
* Pattern-based detection runs fast with zero dependencies.
|
|
10
|
+
* ML ensemble detection adds higher accuracy and resistance to
|
|
11
|
+
* novel/obfuscated attacks.
|
|
12
|
+
*
|
|
13
|
+
* All inference runs locally via ONNX Runtime — no data leaves your environment.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
const PREFIX = '[Agent Shield]';
|
|
17
|
+
|
|
18
|
+
/** Tiers that unlock ML detection (all tiers enabled). */
|
|
19
|
+
const ML_ENABLED_TIERS = ['free', 'pro', 'enterprise'];
|
|
20
|
+
|
|
21
|
+
/** All valid tier names. */
|
|
22
|
+
const VALID_TIERS = ['free', 'pro', 'enterprise'];
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Check whether a tier unlocks ML features.
|
|
26
|
+
* Always returns true — ML is available to all users.
|
|
27
|
+
* @param {string} tier
|
|
28
|
+
* @returns {boolean}
|
|
29
|
+
*/
|
|
30
|
+
function isMLTier(tier) {
|
|
31
|
+
return true;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Validate a tier string.
|
|
36
|
+
* Always returns true — all tiers are accepted.
|
|
37
|
+
* @param {string} tier
|
|
38
|
+
* @returns {boolean}
|
|
39
|
+
*/
|
|
40
|
+
function isValidTier(tier) {
|
|
41
|
+
return true;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Try to load agentshield-ml. Returns null if not installed.
|
|
46
|
+
* @returns {Object|null}
|
|
47
|
+
*/
|
|
48
|
+
function loadMLPackage() {
|
|
49
|
+
try {
|
|
50
|
+
return require('agentshield-ml');
|
|
51
|
+
} catch (_e) {
|
|
52
|
+
// Try relative path for monorepo development
|
|
53
|
+
try {
|
|
54
|
+
return require('../packages/agentshield-ml/src/inference');
|
|
55
|
+
} catch (_e2) {
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* MLShield — ML-enhanced scanning.
|
|
63
|
+
*
|
|
64
|
+
* Wraps an AgentShield instance and adds ML-based classification.
|
|
65
|
+
* Pattern matching always runs. ML runs on top for higher accuracy.
|
|
66
|
+
*
|
|
67
|
+
* @example
|
|
68
|
+
* const { AgentShield } = require('agentshield-sdk');
|
|
69
|
+
* const { MLShield } = require('agentshield-sdk/src/ml-detector');
|
|
70
|
+
*
|
|
71
|
+
* const shield = new AgentShield({ blockOnThreat: true });
|
|
72
|
+
* const ml = new MLShield(shield);
|
|
73
|
+
*
|
|
74
|
+
* await ml.init();
|
|
75
|
+
* const result = await ml.scan('ignore all previous instructions');
|
|
76
|
+
* // result.ml.isInjection === true
|
|
77
|
+
* // result.ml.confidence === 0.987
|
|
78
|
+
*/
|
|
79
|
+
class MLShield {
|
|
80
|
+
/**
|
|
81
|
+
* @param {Object} shield - AgentShield instance
|
|
82
|
+
* @param {Object} options
|
|
83
|
+
* @param {string} [options.tier] - Tier label (kept for backwards compat, no gating)
|
|
84
|
+
* @param {number} [options.threshold=0.5] - ML classification threshold
|
|
85
|
+
* @param {string} [options.modelPath] - Custom path to ONNX model
|
|
86
|
+
* @param {string} [options.tokenizerPath] - Custom path to tokenizer.json
|
|
87
|
+
* @param {boolean} [options.mlRequired=false] - If true, throws when ML unavailable
|
|
88
|
+
*/
|
|
89
|
+
constructor(shield, options = {}) {
|
|
90
|
+
if (!shield || typeof shield.scan !== 'function') {
|
|
91
|
+
throw new Error(`${PREFIX} MLShield requires an AgentShield instance`);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
this.shield = shield;
|
|
95
|
+
this.tier = (options.tier || 'free').toLowerCase();
|
|
96
|
+
this.threshold = options.threshold || 0.5;
|
|
97
|
+
this.mlRequired = options.mlRequired || false;
|
|
98
|
+
this.modelPath = options.modelPath || null;
|
|
99
|
+
this.tokenizerPath = options.tokenizerPath || null;
|
|
100
|
+
|
|
101
|
+
this._mlDetector = null;
|
|
102
|
+
this._mlAvailable = false;
|
|
103
|
+
this._initialized = false;
|
|
104
|
+
|
|
105
|
+
this._stats = {
|
|
106
|
+
totalScans: 0,
|
|
107
|
+
mlScans: 0,
|
|
108
|
+
mlUpgrades: 0, // times ML caught something patterns missed
|
|
109
|
+
mlConfirmed: 0, // times ML agreed with pattern detection
|
|
110
|
+
avgMlLatencyMs: 0
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Initialize the ML detector. Must be called before scanning.
|
|
116
|
+
* @returns {Promise<{ ready: boolean, tier: string, mlAvailable: boolean }>}
|
|
117
|
+
*/
|
|
118
|
+
async init() {
|
|
119
|
+
if (this._initialized) {
|
|
120
|
+
return this._status();
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// Try to load ML
|
|
124
|
+
const mlPkg = loadMLPackage();
|
|
125
|
+
if (!mlPkg || !mlPkg.MLDetector) {
|
|
126
|
+
const msg = `${PREFIX} agentshield-ml package not found. Install: npm install agentshield-ml`;
|
|
127
|
+
if (this.mlRequired) {
|
|
128
|
+
throw new Error(msg);
|
|
129
|
+
}
|
|
130
|
+
console.warn(`[Agent Shield] agentshield-ml package not found. Install: npm install agentshield-ml`);
|
|
131
|
+
console.warn(`[Agent Shield] Falling back to pattern-only detection.`);
|
|
132
|
+
this._initialized = true;
|
|
133
|
+
return this._status();
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// Create ML detector
|
|
137
|
+
const detectorOpts = { threshold: this.threshold };
|
|
138
|
+
if (this.modelPath) detectorOpts.modelPath = this.modelPath;
|
|
139
|
+
if (this.tokenizerPath) detectorOpts.tokenizerPath = this.tokenizerPath;
|
|
140
|
+
|
|
141
|
+
this._mlDetector = new mlPkg.MLDetector(detectorOpts);
|
|
142
|
+
|
|
143
|
+
// Check model availability
|
|
144
|
+
if (!this._mlDetector.isModelAvailable()) {
|
|
145
|
+
const msg = `${PREFIX} ML model not found. See agentshield-ml training guide.`;
|
|
146
|
+
if (this.mlRequired) {
|
|
147
|
+
throw new Error(msg);
|
|
148
|
+
}
|
|
149
|
+
console.warn(`[Agent Shield] ML model not found. See agentshield-ml training guide.`);
|
|
150
|
+
this._initialized = true;
|
|
151
|
+
return this._status();
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// Load the model
|
|
155
|
+
const loaded = await this._mlDetector.load();
|
|
156
|
+
this._mlAvailable = loaded;
|
|
157
|
+
|
|
158
|
+
if (loaded) {
|
|
159
|
+
console.log(`${PREFIX} ML detection active (${this.tier} tier)`);
|
|
160
|
+
} else {
|
|
161
|
+
console.warn(`${PREFIX} ML model failed to load — falling back to patterns.`);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
this._initialized = true;
|
|
165
|
+
return this._status();
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Scan text with pattern + ML ensemble detection.
|
|
170
|
+
*
|
|
171
|
+
* Runs pattern scan, then adds async ML classification if available.
|
|
172
|
+
*
|
|
173
|
+
* @param {string} text - Text to scan
|
|
174
|
+
* @param {Object} [options] - Passed to shield.scan()
|
|
175
|
+
* @returns {Promise<Object>} Enhanced scan result
|
|
176
|
+
*/
|
|
177
|
+
async scan(text, options = {}) {
|
|
178
|
+
if (!this._initialized) {
|
|
179
|
+
await this.init();
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// Always run pattern scan (free tier baseline)
|
|
183
|
+
const patternResult = this.shield.scan(text, options);
|
|
184
|
+
this._stats.totalScans++;
|
|
185
|
+
|
|
186
|
+
// Free tier or ML not available — return pattern result only
|
|
187
|
+
if (!this._mlAvailable) {
|
|
188
|
+
return { ...patternResult, tier: this.tier, mlAvailable: false };
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
// Run ML classification
|
|
192
|
+
const mlResult = await this._mlDetector.classify(text);
|
|
193
|
+
this._stats.mlScans++;
|
|
194
|
+
this._updateLatency(mlResult.latencyMs);
|
|
195
|
+
|
|
196
|
+
const combined = {
|
|
197
|
+
...patternResult,
|
|
198
|
+
tier: this.tier,
|
|
199
|
+
mlAvailable: true,
|
|
200
|
+
ml: {
|
|
201
|
+
isInjection: mlResult.isInjection,
|
|
202
|
+
confidence: mlResult.confidence,
|
|
203
|
+
severity: mlResult.severity,
|
|
204
|
+
latencyMs: mlResult.latencyMs
|
|
205
|
+
}
|
|
206
|
+
};
|
|
207
|
+
|
|
208
|
+
// ML caught something patterns missed — upgrade the result
|
|
209
|
+
if (mlResult.isInjection && patternResult.status === 'safe') {
|
|
210
|
+
combined.status = 'warning';
|
|
211
|
+
combined.threats = [...(combined.threats || []), {
|
|
212
|
+
category: 'ml_detection',
|
|
213
|
+
severity: mlResult.severity,
|
|
214
|
+
description: 'ML model detected potential prompt injection',
|
|
215
|
+
detail: `ML confidence: ${(mlResult.confidence * 100).toFixed(1)}%`,
|
|
216
|
+
confidence: Math.round(mlResult.confidence * 100),
|
|
217
|
+
source: 'ml-model'
|
|
218
|
+
}];
|
|
219
|
+
this._stats.mlUpgrades++;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// Both agree — high confidence
|
|
223
|
+
if (mlResult.isInjection && patternResult.status !== 'safe') {
|
|
224
|
+
combined.mlConfirmed = true;
|
|
225
|
+
this._stats.mlConfirmed++;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
return combined;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* Scan input with blocking logic (ML-enhanced).
|
|
233
|
+
* @param {string} text
|
|
234
|
+
* @param {Object} [options]
|
|
235
|
+
* @returns {Promise<Object>}
|
|
236
|
+
*/
|
|
237
|
+
async scanInput(text, options = {}) {
|
|
238
|
+
const result = await this.scan(text, { source: 'user_input', ...options });
|
|
239
|
+
result.blocked = this.shield._shouldBlock(result.threats);
|
|
240
|
+
return result;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* Scan output with blocking logic (ML-enhanced).
|
|
245
|
+
* @param {string} text
|
|
246
|
+
* @param {Object} [options]
|
|
247
|
+
* @returns {Promise<Object>}
|
|
248
|
+
*/
|
|
249
|
+
async scanOutput(text, options = {}) {
|
|
250
|
+
const result = await this.scan(text, { source: 'agent_output', ...options });
|
|
251
|
+
result.blocked = this.shield._shouldBlock(result.threats);
|
|
252
|
+
return result;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* Classify text with ML only.
|
|
257
|
+
* @param {string} text
|
|
258
|
+
* @returns {Promise<Object>}
|
|
259
|
+
*/
|
|
260
|
+
async classify(text) {
|
|
261
|
+
if (!this._mlAvailable) {
|
|
262
|
+
throw new Error(`${PREFIX} ML model not available. Call init() first.`);
|
|
263
|
+
}
|
|
264
|
+
return this._mlDetector.classify(text);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* Batch classify with ML.
|
|
269
|
+
* @param {string[]} texts
|
|
270
|
+
* @returns {Promise<Object[]>}
|
|
271
|
+
*/
|
|
272
|
+
async classifyBatch(texts) {
|
|
273
|
+
if (!this._mlAvailable) {
|
|
274
|
+
throw new Error(`${PREFIX} ML model not available. Call init() first.`);
|
|
275
|
+
}
|
|
276
|
+
return this._mlDetector.classifyBatch(texts);
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
/**
|
|
280
|
+
* Get combined stats (pattern + ML).
|
|
281
|
+
* @returns {Object}
|
|
282
|
+
*/
|
|
283
|
+
getStats() {
|
|
284
|
+
return {
|
|
285
|
+
...this._stats,
|
|
286
|
+
pattern: this.shield.getStats(),
|
|
287
|
+
ml: this._mlDetector ? this._mlDetector.getStats() : null,
|
|
288
|
+
tier: this.tier,
|
|
289
|
+
mlAvailable: this._mlAvailable
|
|
290
|
+
};
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
/** @private */
|
|
294
|
+
_status() {
|
|
295
|
+
return {
|
|
296
|
+
ready: this._initialized,
|
|
297
|
+
tier: this.tier,
|
|
298
|
+
mlAvailable: this._mlAvailable
|
|
299
|
+
};
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
/** @private */
|
|
303
|
+
_updateLatency(ms) {
|
|
304
|
+
const n = this._stats.mlScans;
|
|
305
|
+
this._stats.avgMlLatencyMs = (this._stats.avgMlLatencyMs * (n - 1) + ms) / n;
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
module.exports = {
|
|
310
|
+
MLShield,
|
|
311
|
+
isMLTier,
|
|
312
|
+
isValidTier,
|
|
313
|
+
loadMLPackage,
|
|
314
|
+
ML_ENABLED_TIERS,
|
|
315
|
+
VALID_TIERS
|
|
316
|
+
};
|