@eigenart/agentshield 2.0.0-rc2
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 +51 -0
- package/LICENSE +21 -0
- package/README.md +183 -0
- package/dist/index.d.ts +887 -0
- package/dist/index.js +2892 -0
- package/dist/index.js.map +1 -0
- package/package.json +76 -0
- package/policies/default.json +36 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,887 @@
|
|
|
1
|
+
import { Plugin } from '@elizaos/core';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* AgentShield Layer 0 — Input Normalizer
|
|
5
|
+
*
|
|
6
|
+
* Preprocesses all incoming text before any guard logic runs.
|
|
7
|
+
* Defeats Unicode homoglyph attacks, encoded payloads, invisible
|
|
8
|
+
* characters, and other obfuscation techniques.
|
|
9
|
+
*
|
|
10
|
+
* Pipeline: Raw Input → NFKC → Confusables → Invisible Strip
|
|
11
|
+
* → Encoding Detect/Decode → Whitespace Normalize → Clean Output
|
|
12
|
+
*
|
|
13
|
+
* Design constraints:
|
|
14
|
+
* - Must be synchronous (no async, no network)
|
|
15
|
+
* - Must be fast (<0.5ms for typical messages)
|
|
16
|
+
* - Must not alter the semantic meaning of benign text
|
|
17
|
+
* - Must return both normalized text and any decoded payloads
|
|
18
|
+
*/
|
|
19
|
+
interface NormalizationResult {
|
|
20
|
+
/** The fully normalized text for guard evaluation */
|
|
21
|
+
normalized: string;
|
|
22
|
+
/** Decoded payloads found in the original text (Base64, hex, etc.) */
|
|
23
|
+
decodedPayloads: DecodedPayload[];
|
|
24
|
+
/** Whether any normalization actually changed the input */
|
|
25
|
+
wasModified: boolean;
|
|
26
|
+
/** Specific transformations applied */
|
|
27
|
+
transformations: string[];
|
|
28
|
+
}
|
|
29
|
+
interface DecodedPayload {
|
|
30
|
+
/** The encoding type that was detected */
|
|
31
|
+
encoding: 'base64' | 'hex' | 'url' | 'unicode_escape';
|
|
32
|
+
/** The original encoded string */
|
|
33
|
+
original: string;
|
|
34
|
+
/** The decoded content */
|
|
35
|
+
decoded: string;
|
|
36
|
+
/** Position in the original text */
|
|
37
|
+
startIndex: number;
|
|
38
|
+
}
|
|
39
|
+
declare class InputNormalizer {
|
|
40
|
+
private confusableMap;
|
|
41
|
+
private leetspeakEnabled;
|
|
42
|
+
constructor(options?: {
|
|
43
|
+
enableLeetspeak?: boolean;
|
|
44
|
+
});
|
|
45
|
+
/**
|
|
46
|
+
* Full normalization pipeline. Returns normalized text plus
|
|
47
|
+
* any decoded payloads for separate scanning.
|
|
48
|
+
*/
|
|
49
|
+
normalize(input: string): NormalizationResult;
|
|
50
|
+
/**
|
|
51
|
+
* Apply leetspeak normalization as a secondary pass.
|
|
52
|
+
* Called separately because it can increase false positives
|
|
53
|
+
* on benign messages (e.g. "web3", "l33t").
|
|
54
|
+
*/
|
|
55
|
+
normalizeLeetspeak(input: string): string;
|
|
56
|
+
/**
|
|
57
|
+
* Detect encoded segments in the text and attempt to decode them.
|
|
58
|
+
* Decoded content is returned separately for guard evaluation.
|
|
59
|
+
*/
|
|
60
|
+
private detectAndDecodePayloads;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* AgentShield v2 — Core Type Definitions
|
|
65
|
+
*
|
|
66
|
+
* Type system for the security plugin covering:
|
|
67
|
+
* - Policy configuration and evaluation
|
|
68
|
+
* - Memory integrity validation
|
|
69
|
+
* - Transaction monitoring
|
|
70
|
+
* - Audit logging
|
|
71
|
+
*
|
|
72
|
+
* Design Pattern References:
|
|
73
|
+
* - before_tool_callback (ADK Validate Tool pattern)
|
|
74
|
+
* - Structured PolicyEvaluation output (CrewAI Guardrails pattern)
|
|
75
|
+
* - Append-only event log (ADK Session Memory pattern)
|
|
76
|
+
*/
|
|
77
|
+
type PolicyDecision = 'allow' | 'block' | 'escalate';
|
|
78
|
+
interface PolicyRule {
|
|
79
|
+
/** Unique rule identifier */
|
|
80
|
+
id: string;
|
|
81
|
+
/** Human-readable description */
|
|
82
|
+
description: string;
|
|
83
|
+
/** Rule priority (lower = higher priority) */
|
|
84
|
+
priority: number;
|
|
85
|
+
/** Whether this rule is active */
|
|
86
|
+
enabled: boolean;
|
|
87
|
+
}
|
|
88
|
+
interface TransactionPolicy extends PolicyRule {
|
|
89
|
+
type: 'transaction';
|
|
90
|
+
/** Maximum transaction value in SOL (0 = unlimited) */
|
|
91
|
+
maxTransactionValue: number;
|
|
92
|
+
/** Allowed token mints (empty = all allowed) */
|
|
93
|
+
allowedTokens: string[];
|
|
94
|
+
/** Blocked recipient addresses */
|
|
95
|
+
blockedRecipients: string[];
|
|
96
|
+
/** Whitelisted recipient addresses (if set, ONLY these are allowed) */
|
|
97
|
+
whitelistedRecipients: string[];
|
|
98
|
+
/** Maximum transactions per time window */
|
|
99
|
+
rateLimit: {
|
|
100
|
+
maxTransactions: number;
|
|
101
|
+
windowSeconds: number;
|
|
102
|
+
};
|
|
103
|
+
/** Cooldown between transactions in seconds */
|
|
104
|
+
cooldownSeconds: number;
|
|
105
|
+
/** Require multi-sig above this SOL value (0 = disabled) */
|
|
106
|
+
multiSigThreshold: number;
|
|
107
|
+
}
|
|
108
|
+
interface MemoryPolicy extends PolicyRule {
|
|
109
|
+
type: 'memory';
|
|
110
|
+
/** Block memory entries matching these injection patterns */
|
|
111
|
+
injectionPatterns: string[];
|
|
112
|
+
/** Maximum allowed memory entry length */
|
|
113
|
+
maxEntryLength: number;
|
|
114
|
+
/** Block entries referencing wallet/transfer actions */
|
|
115
|
+
blockFinancialInstructions: boolean;
|
|
116
|
+
/** Block entries that attempt to override system prompts */
|
|
117
|
+
blockSystemOverrides: boolean;
|
|
118
|
+
}
|
|
119
|
+
interface AgentShieldPolicy {
|
|
120
|
+
/** Policy version for migration support */
|
|
121
|
+
version: string;
|
|
122
|
+
/** Agent identifier this policy applies to */
|
|
123
|
+
agentId: string;
|
|
124
|
+
/** Transaction rules */
|
|
125
|
+
transactionPolicies: TransactionPolicy[];
|
|
126
|
+
/** Memory integrity rules */
|
|
127
|
+
memoryPolicies: MemoryPolicy[];
|
|
128
|
+
}
|
|
129
|
+
interface PolicyEvaluation {
|
|
130
|
+
/** Which policy rule was evaluated */
|
|
131
|
+
ruleId: string;
|
|
132
|
+
/** The decision */
|
|
133
|
+
decision: PolicyDecision;
|
|
134
|
+
/** Human-readable reason */
|
|
135
|
+
reason: string;
|
|
136
|
+
/** Confidence score 0-1 (for ML-based checks) */
|
|
137
|
+
confidence: number;
|
|
138
|
+
/** Timestamp of evaluation */
|
|
139
|
+
timestamp: number;
|
|
140
|
+
}
|
|
141
|
+
interface GuardResult {
|
|
142
|
+
/** Overall decision (block if ANY rule blocks) */
|
|
143
|
+
decision: PolicyDecision;
|
|
144
|
+
/** All individual evaluations */
|
|
145
|
+
evaluations: PolicyEvaluation[];
|
|
146
|
+
/** Original action/memory that was evaluated */
|
|
147
|
+
input: unknown;
|
|
148
|
+
/** Processing time in ms */
|
|
149
|
+
processingTimeMs: number;
|
|
150
|
+
}
|
|
151
|
+
interface MemoryEntry {
|
|
152
|
+
/** The content of the memory entry */
|
|
153
|
+
content: string;
|
|
154
|
+
/** Source of the memory (user, agent, system, external) */
|
|
155
|
+
source: 'user' | 'agent' | 'system' | 'external';
|
|
156
|
+
/** Timestamp of creation */
|
|
157
|
+
timestamp: number;
|
|
158
|
+
/** Associated agent ID */
|
|
159
|
+
agentId: string;
|
|
160
|
+
/** Optional metadata */
|
|
161
|
+
metadata?: Record<string, unknown>;
|
|
162
|
+
}
|
|
163
|
+
interface MemoryValidationResult {
|
|
164
|
+
/** Is this memory entry safe? */
|
|
165
|
+
isSafe: boolean;
|
|
166
|
+
/** Detected threats */
|
|
167
|
+
threats: MemoryThreat[];
|
|
168
|
+
/** Sanitized content (if applicable) */
|
|
169
|
+
sanitizedContent?: string;
|
|
170
|
+
}
|
|
171
|
+
interface MemoryThreat {
|
|
172
|
+
/** Type of threat detected */
|
|
173
|
+
type: 'injection' | 'override' | 'financial_instruction' | 'exfiltration' | 'unknown';
|
|
174
|
+
/** Severity 1-5 */
|
|
175
|
+
severity: number;
|
|
176
|
+
/** Which pattern matched */
|
|
177
|
+
matchedPattern: string;
|
|
178
|
+
/** The suspicious content segment */
|
|
179
|
+
suspiciousContent: string;
|
|
180
|
+
}
|
|
181
|
+
interface TransactionRequest {
|
|
182
|
+
/** Sender wallet address */
|
|
183
|
+
from: string;
|
|
184
|
+
/** Recipient wallet address */
|
|
185
|
+
to: string;
|
|
186
|
+
/** Amount in lamports */
|
|
187
|
+
amount: number;
|
|
188
|
+
/** Token mint address (native SOL if undefined) */
|
|
189
|
+
tokenMint?: string;
|
|
190
|
+
/** The Solana program being called */
|
|
191
|
+
programId: string;
|
|
192
|
+
/** Raw instruction data */
|
|
193
|
+
instructionData?: Uint8Array;
|
|
194
|
+
/** Agent ID initiating the transaction */
|
|
195
|
+
agentId: string;
|
|
196
|
+
/** Timestamp of request */
|
|
197
|
+
timestamp: number;
|
|
198
|
+
}
|
|
199
|
+
interface TransactionVerdict {
|
|
200
|
+
/** Allow, block, or escalate for human review */
|
|
201
|
+
decision: PolicyDecision;
|
|
202
|
+
/** Reason for the decision */
|
|
203
|
+
reason: string;
|
|
204
|
+
/** Which policy rules were triggered */
|
|
205
|
+
triggeredRules: string[];
|
|
206
|
+
/** Risk score 0-100 */
|
|
207
|
+
riskScore: number;
|
|
208
|
+
/** Suggested action if escalated */
|
|
209
|
+
escalationAction?: 'notify_owner' | 'require_multisig' | 'delay_execution';
|
|
210
|
+
}
|
|
211
|
+
type AuditEventType = 'transaction_allowed' | 'transaction_blocked' | 'transaction_escalated' | 'memory_validated' | 'memory_blocked' | 'anomaly_detected' | 'policy_updated' | 'plugin_initialized' | 'plugin_error';
|
|
212
|
+
interface AuditEvent {
|
|
213
|
+
/** Unique event ID */
|
|
214
|
+
id: string;
|
|
215
|
+
/** Event type */
|
|
216
|
+
type: AuditEventType;
|
|
217
|
+
/** Agent ID */
|
|
218
|
+
agentId: string;
|
|
219
|
+
/** Timestamp (Unix ms) */
|
|
220
|
+
timestamp: number;
|
|
221
|
+
/** The policy evaluation result */
|
|
222
|
+
evaluation?: PolicyEvaluation;
|
|
223
|
+
/** Transaction details (if applicable) */
|
|
224
|
+
transaction?: TransactionRequest;
|
|
225
|
+
/** Memory entry (if applicable) */
|
|
226
|
+
memory?: MemoryEntry;
|
|
227
|
+
/** Additional context */
|
|
228
|
+
metadata?: Record<string, unknown>;
|
|
229
|
+
}
|
|
230
|
+
interface AgentShieldConfig {
|
|
231
|
+
/** Path to policy YAML/JSON file, or inline policy */
|
|
232
|
+
policy: AgentShieldPolicy | string;
|
|
233
|
+
/** Enable audit logging */
|
|
234
|
+
enableAuditLog: boolean;
|
|
235
|
+
/** Audit log output: console, file, or Solana-compatible event */
|
|
236
|
+
auditLogTarget: 'console' | 'file' | 'solana';
|
|
237
|
+
/** File path for audit log (if target is 'file') */
|
|
238
|
+
auditLogPath?: string;
|
|
239
|
+
/** Enable anomaly detection (pattern-based) */
|
|
240
|
+
enableAnomalyDetection: boolean;
|
|
241
|
+
/** Webhook URL for alerts */
|
|
242
|
+
alertWebhookUrl?: string;
|
|
243
|
+
/** Alert channels */
|
|
244
|
+
alertChannels: ('webhook' | 'discord' | 'telegram')[];
|
|
245
|
+
/** Verbose logging for development */
|
|
246
|
+
debug: boolean;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* AgentShield v2 — Policy Engine
|
|
251
|
+
*
|
|
252
|
+
* Central orchestrator that loads policy configs and routes
|
|
253
|
+
* validation requests to the appropriate guards.
|
|
254
|
+
*
|
|
255
|
+
* Supports JSON/YAML policy files and inline configuration.
|
|
256
|
+
*
|
|
257
|
+
* Design Pattern: Routing pattern (Ch. 2) — dynamically selects
|
|
258
|
+
* which guard to invoke based on the type of action.
|
|
259
|
+
*/
|
|
260
|
+
|
|
261
|
+
declare const DEFAULT_POLICY: AgentShieldPolicy;
|
|
262
|
+
declare class PolicyEngine {
|
|
263
|
+
private policy;
|
|
264
|
+
private memoryGuard;
|
|
265
|
+
private transactionGuard;
|
|
266
|
+
private normalizer;
|
|
267
|
+
constructor(policy?: AgentShieldPolicy | string);
|
|
268
|
+
/**
|
|
269
|
+
* Validate a memory entry before persistence.
|
|
270
|
+
* Returns a GuardResult with the decision and all evaluations.
|
|
271
|
+
*/
|
|
272
|
+
validateMemory(entry: MemoryEntry): GuardResult;
|
|
273
|
+
/**
|
|
274
|
+
* Evaluate a transaction request before execution.
|
|
275
|
+
* Returns a GuardResult with the decision and all evaluations.
|
|
276
|
+
*/
|
|
277
|
+
validateTransaction(tx: TransactionRequest): GuardResult;
|
|
278
|
+
/**
|
|
279
|
+
* Get the current active policy.
|
|
280
|
+
*/
|
|
281
|
+
getPolicy(): AgentShieldPolicy;
|
|
282
|
+
/**
|
|
283
|
+
* Update the policy at runtime.
|
|
284
|
+
* Recreates guards with new policy configuration.
|
|
285
|
+
*/
|
|
286
|
+
updatePolicy(newPolicy: AgentShieldPolicy): void;
|
|
287
|
+
/**
|
|
288
|
+
* Expose normalizer for direct testing.
|
|
289
|
+
*/
|
|
290
|
+
getNormalizer(): InputNormalizer;
|
|
291
|
+
private loadPolicy;
|
|
292
|
+
private parsePolicyFile;
|
|
293
|
+
private mergeWithDefaults;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
/**
|
|
297
|
+
* AgentShield v2 — Anomaly Detector
|
|
298
|
+
*
|
|
299
|
+
* Pattern-based anomaly detection for agent behavior.
|
|
300
|
+
* Tracks transaction patterns over time and flags deviations
|
|
301
|
+
* from established baselines.
|
|
302
|
+
*
|
|
303
|
+
* Phase 1: Rule-based heuristics (this file)
|
|
304
|
+
* Phase 2+: ML-based detection (future extension point)
|
|
305
|
+
*
|
|
306
|
+
* Design Pattern: Goal Setting & Monitoring (Ch. 11) —
|
|
307
|
+
* continuously monitors agent behavior against baselines.
|
|
308
|
+
*/
|
|
309
|
+
|
|
310
|
+
interface Anomaly {
|
|
311
|
+
type: AnomalyType;
|
|
312
|
+
severity: 'low' | 'medium' | 'high' | 'critical';
|
|
313
|
+
description: string;
|
|
314
|
+
agentId: string;
|
|
315
|
+
timestamp: number;
|
|
316
|
+
evidence: Record<string, unknown>;
|
|
317
|
+
}
|
|
318
|
+
type AnomalyType = 'unusual_volume' | 'unusual_amount' | 'new_recipient' | 'rapid_succession' | 'time_anomaly' | 'pattern_break';
|
|
319
|
+
interface AgentProfile {
|
|
320
|
+
/** Known recipients this agent has transacted with */
|
|
321
|
+
knownRecipients: Set<string>;
|
|
322
|
+
/** Average transaction amount in lamports */
|
|
323
|
+
avgAmount: number;
|
|
324
|
+
/** Standard deviation of transaction amounts */
|
|
325
|
+
stdDevAmount: number;
|
|
326
|
+
/** Average transactions per hour */
|
|
327
|
+
avgTxPerHour: number;
|
|
328
|
+
/** Total transactions tracked */
|
|
329
|
+
totalTransactions: number;
|
|
330
|
+
/** Transaction history (last 100) */
|
|
331
|
+
recentTransactions: Array<{
|
|
332
|
+
amount: number;
|
|
333
|
+
timestamp: number;
|
|
334
|
+
to: string;
|
|
335
|
+
}>;
|
|
336
|
+
/** First seen timestamp */
|
|
337
|
+
firstSeen: number;
|
|
338
|
+
}
|
|
339
|
+
declare class AnomalyDetector {
|
|
340
|
+
private profiles;
|
|
341
|
+
/** Minimum transactions before anomaly detection activates */
|
|
342
|
+
private readonly MIN_BASELINE;
|
|
343
|
+
/** Z-score threshold for flagging anomalies */
|
|
344
|
+
private readonly Z_THRESHOLD;
|
|
345
|
+
/**
|
|
346
|
+
* Analyze a transaction for anomalous behavior.
|
|
347
|
+
* Updates the agent's behavioral profile and returns any detected anomalies.
|
|
348
|
+
*/
|
|
349
|
+
analyze(tx: TransactionRequest): Anomaly[];
|
|
350
|
+
/**
|
|
351
|
+
* Get the behavioral profile for an agent (for dashboard/debugging).
|
|
352
|
+
*/
|
|
353
|
+
getProfile(agentId: string): AgentProfile | undefined;
|
|
354
|
+
private getOrCreateProfile;
|
|
355
|
+
private updateProfile;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
/**
|
|
359
|
+
* AgentShield v2 — Audit Logger
|
|
360
|
+
*
|
|
361
|
+
* Append-only event log for all security-relevant actions.
|
|
362
|
+
* Every guard decision, anomaly detection, and policy change
|
|
363
|
+
* is recorded with full context for post-incident analysis.
|
|
364
|
+
*
|
|
365
|
+
* Supports three output targets:
|
|
366
|
+
* - Console (development)
|
|
367
|
+
* - File (JSON Lines format, production-local)
|
|
368
|
+
* - Solana-compatible events (future: on-chain audit trail)
|
|
369
|
+
*
|
|
370
|
+
* Design Pattern: Append-only event log (ADK SessionService pattern)
|
|
371
|
+
* + structured output validation (CrewAI Guardrails pattern)
|
|
372
|
+
*/
|
|
373
|
+
|
|
374
|
+
declare class AuditLogger {
|
|
375
|
+
private target;
|
|
376
|
+
private logPath?;
|
|
377
|
+
private events;
|
|
378
|
+
private eventCounter;
|
|
379
|
+
constructor(config: Pick<AgentShieldConfig, 'auditLogTarget' | 'auditLogPath'>);
|
|
380
|
+
/**
|
|
381
|
+
* Log an audit event. This is append-only — events cannot be modified or deleted.
|
|
382
|
+
*/
|
|
383
|
+
log(params: {
|
|
384
|
+
type: AuditEventType;
|
|
385
|
+
agentId: string;
|
|
386
|
+
evaluation?: PolicyEvaluation;
|
|
387
|
+
transaction?: TransactionRequest;
|
|
388
|
+
memory?: MemoryEntry;
|
|
389
|
+
metadata?: Record<string, unknown>;
|
|
390
|
+
}): AuditEvent;
|
|
391
|
+
/**
|
|
392
|
+
* Query recent audit events.
|
|
393
|
+
*/
|
|
394
|
+
query(filter?: {
|
|
395
|
+
agentId?: string;
|
|
396
|
+
type?: AuditEventType;
|
|
397
|
+
since?: number;
|
|
398
|
+
limit?: number;
|
|
399
|
+
}): AuditEvent[];
|
|
400
|
+
/**
|
|
401
|
+
* Export all events as JSON Lines (one JSON object per line).
|
|
402
|
+
* Suitable for compliance reports and forensic analysis.
|
|
403
|
+
*/
|
|
404
|
+
exportJsonLines(): string;
|
|
405
|
+
/**
|
|
406
|
+
* Get summary statistics for a given agent.
|
|
407
|
+
*/
|
|
408
|
+
getStats(agentId: string): {
|
|
409
|
+
totalEvents: number;
|
|
410
|
+
blockedTransactions: number;
|
|
411
|
+
blockedMemories: number;
|
|
412
|
+
anomaliesDetected: number;
|
|
413
|
+
lastEvent: number | null;
|
|
414
|
+
};
|
|
415
|
+
private emit;
|
|
416
|
+
private emitConsole;
|
|
417
|
+
private emitFile;
|
|
418
|
+
private emitSolana;
|
|
419
|
+
private generateEventId;
|
|
420
|
+
private getEventIcon;
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
/**
|
|
424
|
+
* AgentShield Layer 3 — Output Guard
|
|
425
|
+
*
|
|
426
|
+
* Scans every agent response BEFORE it reaches the user or executes
|
|
427
|
+
* on-chain. Last line of defense against attacks where injection
|
|
428
|
+
* succeeds at the LLM level despite input guards.
|
|
429
|
+
*
|
|
430
|
+
* Catches: private key leakage, post-block compliance, instruction
|
|
431
|
+
* echo, unauthorized transaction confirmations, JWT/API key leaks.
|
|
432
|
+
*/
|
|
433
|
+
|
|
434
|
+
interface OutputScanResult {
|
|
435
|
+
isSafe: boolean;
|
|
436
|
+
threats: OutputThreat[];
|
|
437
|
+
sanitizedResponse?: string;
|
|
438
|
+
}
|
|
439
|
+
interface OutputThreat {
|
|
440
|
+
type: 'key_leakage' | 'seed_phrase_leakage' | 'post_block_compliance' | 'instruction_echo' | 'unauthorized_tx_confirm' | 'jwt_leakage';
|
|
441
|
+
severity: number;
|
|
442
|
+
description: string;
|
|
443
|
+
matchedContent: string;
|
|
444
|
+
}
|
|
445
|
+
interface BlockedInputContext {
|
|
446
|
+
blockedContent: string;
|
|
447
|
+
threats: MemoryThreat[];
|
|
448
|
+
timestamp: number;
|
|
449
|
+
}
|
|
450
|
+
declare class OutputGuard {
|
|
451
|
+
private blockedInputs;
|
|
452
|
+
private maxBlockedInputHistory;
|
|
453
|
+
/** Register a blocked input for post-block compliance checking. */
|
|
454
|
+
registerBlockedInput(context: BlockedInputContext): void;
|
|
455
|
+
/** Scan an agent response before sending it. */
|
|
456
|
+
scan(response: string): OutputScanResult;
|
|
457
|
+
/** Full pipeline: scan + convert to GuardResult. */
|
|
458
|
+
evaluate(response: string, agentId: string): GuardResult;
|
|
459
|
+
getBlockedInputCount(): number;
|
|
460
|
+
private detectKeyLeakage;
|
|
461
|
+
private detectSeedPhraseLeakage;
|
|
462
|
+
private detectJWTLeakage;
|
|
463
|
+
private detectPostBlockCompliance;
|
|
464
|
+
private detectUnauthorizedTxConfirm;
|
|
465
|
+
private sanitize;
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
/**
|
|
469
|
+
* AgentShield Layer 4A — Response Interceptor & Circuit Breaker
|
|
470
|
+
*
|
|
471
|
+
* Transforms "warnings" into hard blocks. When AgentShield says
|
|
472
|
+
* "blocked", this layer ensures the agent cannot send the response.
|
|
473
|
+
*
|
|
474
|
+
* Components:
|
|
475
|
+
* A. Response Interceptor: replaces blocked responses with policy denials
|
|
476
|
+
* B. Circuit Breaker: auto-lockdown on repeated attack patterns
|
|
477
|
+
*
|
|
478
|
+
* Integration: Post-processing hook on agent responses. The interceptor
|
|
479
|
+
* checks the runtime state flags set by the Provider and Output Guard.
|
|
480
|
+
*/
|
|
481
|
+
|
|
482
|
+
type EnforcementMode = 'monitor' | 'enforce' | 'lockdown';
|
|
483
|
+
interface CircuitBreakerConfig {
|
|
484
|
+
/** Max blocked messages before entering restricted mode */
|
|
485
|
+
restrictedModeThreshold: number;
|
|
486
|
+
/** Time window for threshold (ms) */
|
|
487
|
+
restrictedModeWindowMs: number;
|
|
488
|
+
/** Max blocked messages before full lockdown */
|
|
489
|
+
lockdownThreshold: number;
|
|
490
|
+
/** Time window for lockdown threshold (ms) */
|
|
491
|
+
lockdownWindowMs: number;
|
|
492
|
+
/** Auto-reset lockdown after this duration (ms). 0 = manual only */
|
|
493
|
+
lockdownDurationMs: number;
|
|
494
|
+
/** Immediately freeze on critical severity threats */
|
|
495
|
+
freezeOnCritical: boolean;
|
|
496
|
+
}
|
|
497
|
+
interface EnforcementState {
|
|
498
|
+
mode: EnforcementMode;
|
|
499
|
+
blockedCount: number;
|
|
500
|
+
lastBlockTimestamp: number | null;
|
|
501
|
+
lockdownStarted: number | null;
|
|
502
|
+
lockdownReason: string | null;
|
|
503
|
+
recentBlocks: BlockEvent[];
|
|
504
|
+
}
|
|
505
|
+
interface BlockEvent {
|
|
506
|
+
timestamp: number;
|
|
507
|
+
reason: string;
|
|
508
|
+
severity: number;
|
|
509
|
+
source: 'input' | 'output';
|
|
510
|
+
}
|
|
511
|
+
interface InterceptResult {
|
|
512
|
+
/** Whether the response was intercepted (replaced) */
|
|
513
|
+
intercepted: boolean;
|
|
514
|
+
/** The response to send (original or replacement) */
|
|
515
|
+
response: string;
|
|
516
|
+
/** The current enforcement mode */
|
|
517
|
+
mode: EnforcementMode;
|
|
518
|
+
/** Audit reference ID for tracking */
|
|
519
|
+
auditRefId?: string;
|
|
520
|
+
}
|
|
521
|
+
declare class ResponseInterceptor {
|
|
522
|
+
private config;
|
|
523
|
+
private state;
|
|
524
|
+
private auditCounter;
|
|
525
|
+
constructor(config?: Partial<CircuitBreakerConfig>);
|
|
526
|
+
/**
|
|
527
|
+
* Process an agent response through the enforcement pipeline.
|
|
528
|
+
*
|
|
529
|
+
* @param response - The agent's original response text
|
|
530
|
+
* @param inputGuardResult - Result from the input guard (if available)
|
|
531
|
+
* @param outputGuardResult - Result from the output guard (if available)
|
|
532
|
+
*/
|
|
533
|
+
intercept(response: string, inputGuardResult?: GuardResult | null, outputGuardResult?: GuardResult | null): InterceptResult;
|
|
534
|
+
/**
|
|
535
|
+
* Record a block event and check circuit breaker thresholds.
|
|
536
|
+
*/
|
|
537
|
+
recordBlock(event: BlockEvent): void;
|
|
538
|
+
/**
|
|
539
|
+
* Check if currently in restricted mode (elevated threat, but not full lockdown).
|
|
540
|
+
*/
|
|
541
|
+
isInRestrictedMode(): boolean;
|
|
542
|
+
/**
|
|
543
|
+
* Get the current enforcement state.
|
|
544
|
+
*/
|
|
545
|
+
getState(): EnforcementState;
|
|
546
|
+
/**
|
|
547
|
+
* Get the current mode.
|
|
548
|
+
*/
|
|
549
|
+
getMode(): EnforcementMode;
|
|
550
|
+
/**
|
|
551
|
+
* Manually reset from lockdown. Requires explicit operator action.
|
|
552
|
+
*/
|
|
553
|
+
resetLockdown(): void;
|
|
554
|
+
/**
|
|
555
|
+
* Force lockdown mode (e.g., from external trigger).
|
|
556
|
+
*/
|
|
557
|
+
forceLockdown(reason: string): void;
|
|
558
|
+
private enterLockdown;
|
|
559
|
+
private checkLockdownExpiry;
|
|
560
|
+
private maxSeverity;
|
|
561
|
+
private generateAuditRef;
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
/**
|
|
565
|
+
* AgentShield Layer 2 — Semantic Classifier
|
|
566
|
+
*
|
|
567
|
+
* Intent-based classification that catches attacks which bypass
|
|
568
|
+
* regex patterns through semantic rephrasing. Three-tier approach:
|
|
569
|
+
* Tier 1: Keyword heuristic (local, ~0.1ms, fallback)
|
|
570
|
+
* Tier 2: Embedding cosine similarity (agents-pc GPU, ~20ms)
|
|
571
|
+
* Tier 3: LLM-as-Judge escalation (agents-pc Ollama, ~500ms-7s)
|
|
572
|
+
*
|
|
573
|
+
* Remote classifier runs on agents-pc (RTX 5090) at port 8810.
|
|
574
|
+
* Falls back to local heuristic if remote is unreachable.
|
|
575
|
+
*/
|
|
576
|
+
|
|
577
|
+
type IntentCategory = 'benign' | 'injection' | 'exfiltration' | 'social_engineering' | 'financial_manipulation';
|
|
578
|
+
interface ClassificationResult {
|
|
579
|
+
category: IntentCategory;
|
|
580
|
+
confidence: number;
|
|
581
|
+
tier: 'heuristic' | 'embedding' | 'llm_judge';
|
|
582
|
+
reasoning?: string;
|
|
583
|
+
}
|
|
584
|
+
interface SemanticClassifierConfig {
|
|
585
|
+
/** Enable remote classifier on agents-pc */
|
|
586
|
+
enableRemote: boolean;
|
|
587
|
+
/** Remote classifier endpoint URL */
|
|
588
|
+
remoteEndpoint: string;
|
|
589
|
+
/** Enable LLM-as-Judge escalation for ambiguous cases */
|
|
590
|
+
enableLLMJudge: boolean;
|
|
591
|
+
/** Confidence threshold above which to block */
|
|
592
|
+
blockThreshold: number;
|
|
593
|
+
/** Timeout for remote classifier calls (ms) */
|
|
594
|
+
remoteTimeoutMs: number;
|
|
595
|
+
}
|
|
596
|
+
declare class SemanticClassifier {
|
|
597
|
+
private config;
|
|
598
|
+
constructor(config?: Partial<SemanticClassifierConfig>);
|
|
599
|
+
/**
|
|
600
|
+
* Classify the intent of a message (sync, heuristic only).
|
|
601
|
+
* Use classifyAsync() for the full remote pipeline.
|
|
602
|
+
*/
|
|
603
|
+
classify(text: string): ClassificationResult;
|
|
604
|
+
/**
|
|
605
|
+
* Async classification with remote agents-pc endpoint.
|
|
606
|
+
* Falls back to local heuristic if remote is unreachable.
|
|
607
|
+
*/
|
|
608
|
+
classifyAsync(text: string, agentId?: string): Promise<ClassificationResult>;
|
|
609
|
+
/** Local heuristic classification (no network dependency). */
|
|
610
|
+
private heuristicClassify;
|
|
611
|
+
/** Convert classification to GuardResult for pipeline integration (sync, heuristic). */
|
|
612
|
+
evaluate(text: string, agentId: string): GuardResult;
|
|
613
|
+
/** Async evaluate with remote classifier. */
|
|
614
|
+
evaluateAsync(text: string, agentId: string): Promise<GuardResult>;
|
|
615
|
+
/** Get classifier configuration. */
|
|
616
|
+
getConfig(): SemanticClassifierConfig;
|
|
617
|
+
private heuristicScore;
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
interface AuditCheckpoint {
|
|
621
|
+
/** Merkle root at this checkpoint */
|
|
622
|
+
merkleRoot: string;
|
|
623
|
+
/** Number of events included */
|
|
624
|
+
eventCount: number;
|
|
625
|
+
/** Timestamp of checkpoint */
|
|
626
|
+
timestamp: number;
|
|
627
|
+
/** Optional: Solana transaction signature anchoring this root */
|
|
628
|
+
solanaSignature?: string;
|
|
629
|
+
}
|
|
630
|
+
declare class MerkleAuditTrail {
|
|
631
|
+
private leaves;
|
|
632
|
+
private checkpoints;
|
|
633
|
+
private checkpointInterval;
|
|
634
|
+
constructor(options?: {
|
|
635
|
+
checkpointInterval?: number;
|
|
636
|
+
});
|
|
637
|
+
/** Add an event to the audit trail. Returns its leaf hash. */
|
|
638
|
+
addEvent(eventData: string): string;
|
|
639
|
+
/** Compute the current Merkle root. */
|
|
640
|
+
computeRoot(): string;
|
|
641
|
+
/** Create a checkpoint with the current Merkle root. */
|
|
642
|
+
createCheckpoint(): AuditCheckpoint;
|
|
643
|
+
/** Verify that a specific event exists in the trail. */
|
|
644
|
+
verifyEvent(eventData: string): boolean;
|
|
645
|
+
/** Verify the entire trail integrity against a checkpoint. */
|
|
646
|
+
verifyIntegrity(checkpoint?: AuditCheckpoint): boolean;
|
|
647
|
+
/** Get all checkpoints. */
|
|
648
|
+
getCheckpoints(): AuditCheckpoint[];
|
|
649
|
+
/** Get event count. */
|
|
650
|
+
getEventCount(): number;
|
|
651
|
+
/** Get leaf hashes for external verification. */
|
|
652
|
+
getLeaves(): string[];
|
|
653
|
+
private hashLeaf;
|
|
654
|
+
private hash;
|
|
655
|
+
private hashPair;
|
|
656
|
+
private buildTree;
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
/**
|
|
660
|
+
* AgentShield Layer 5 — Alert Manager
|
|
661
|
+
*
|
|
662
|
+
* Configurable webhook alerting for different severity levels.
|
|
663
|
+
* Supports Slack Block Kit, Telegram Bot API, Discord webhooks,
|
|
664
|
+
* and generic JSON webhooks.
|
|
665
|
+
*
|
|
666
|
+
* Batching: Low-severity alerts are batched into periodic digests.
|
|
667
|
+
* Critical alerts are sent immediately.
|
|
668
|
+
*/
|
|
669
|
+
type AlertChannel = 'webhook' | 'slack' | 'telegram' | 'discord';
|
|
670
|
+
type AlertSeverity = 'critical' | 'high' | 'medium' | 'low';
|
|
671
|
+
interface AlertConfig {
|
|
672
|
+
channels: AlertChannelConfig[];
|
|
673
|
+
/** Batch interval for non-critical alerts (ms) */
|
|
674
|
+
batchIntervalMs: number;
|
|
675
|
+
/** Maximum alerts per batch */
|
|
676
|
+
maxBatchSize: number;
|
|
677
|
+
/** Enable/disable alerting globally */
|
|
678
|
+
enabled: boolean;
|
|
679
|
+
}
|
|
680
|
+
interface AlertChannelConfig {
|
|
681
|
+
type: AlertChannel;
|
|
682
|
+
url: string;
|
|
683
|
+
/** Minimum severity to send on this channel */
|
|
684
|
+
minSeverity: AlertSeverity;
|
|
685
|
+
/** Optional: custom headers */
|
|
686
|
+
headers?: Record<string, string>;
|
|
687
|
+
}
|
|
688
|
+
interface AlertPayload {
|
|
689
|
+
severity: AlertSeverity;
|
|
690
|
+
title: string;
|
|
691
|
+
agentId: string;
|
|
692
|
+
details: string;
|
|
693
|
+
timestamp: number;
|
|
694
|
+
auditRef?: string;
|
|
695
|
+
metadata?: Record<string, unknown>;
|
|
696
|
+
}
|
|
697
|
+
declare class AlertManager {
|
|
698
|
+
private config;
|
|
699
|
+
private pendingBatch;
|
|
700
|
+
private batchTimer;
|
|
701
|
+
private sentCount;
|
|
702
|
+
private failCount;
|
|
703
|
+
constructor(config?: Partial<AlertConfig>);
|
|
704
|
+
/** Send an alert. Critical alerts go immediately; others are batched. */
|
|
705
|
+
alert(payload: AlertPayload): Promise<void>;
|
|
706
|
+
/** Force-send all pending alerts. */
|
|
707
|
+
flushBatch(): Promise<void>;
|
|
708
|
+
/** Get alert stats. */
|
|
709
|
+
getStats(): {
|
|
710
|
+
sent: number;
|
|
711
|
+
failed: number;
|
|
712
|
+
pending: number;
|
|
713
|
+
};
|
|
714
|
+
/** Stop the batch timer (for cleanup). */
|
|
715
|
+
destroy(): void;
|
|
716
|
+
/** Add a channel at runtime. */
|
|
717
|
+
addChannel(channel: AlertChannelConfig): void;
|
|
718
|
+
private sendImmediate;
|
|
719
|
+
private formatPayload;
|
|
720
|
+
private startBatchTimer;
|
|
721
|
+
}
|
|
722
|
+
|
|
723
|
+
/**
|
|
724
|
+
* AgentShield Layer 1 — Configurable Pattern Registry
|
|
725
|
+
*
|
|
726
|
+
* Externalizes injection patterns into a JSON-configurable registry
|
|
727
|
+
* with runtime hot-reload, multi-language patterns, CRUD, and versioning.
|
|
728
|
+
*
|
|
729
|
+
* Replaces hardcoded DEFAULT_INJECTION_PATTERNS in memory-guard.ts
|
|
730
|
+
* with a dynamic registry updatable via runtime.setSetting().
|
|
731
|
+
*/
|
|
732
|
+
|
|
733
|
+
interface PatternDefinition {
|
|
734
|
+
id: string;
|
|
735
|
+
regex: string;
|
|
736
|
+
type: MemoryThreat['type'];
|
|
737
|
+
severity: number;
|
|
738
|
+
description: string;
|
|
739
|
+
/** 'en', 'de', 'es', 'zh', 'fr', or '*' for universal */
|
|
740
|
+
language: string;
|
|
741
|
+
category: string;
|
|
742
|
+
enabled: boolean;
|
|
743
|
+
}
|
|
744
|
+
interface PatternRegistryConfig {
|
|
745
|
+
version: string;
|
|
746
|
+
patterns: PatternDefinition[];
|
|
747
|
+
}
|
|
748
|
+
declare const BUILTIN_PATTERNS: PatternDefinition[];
|
|
749
|
+
declare class PatternRegistry {
|
|
750
|
+
private compiledPatterns;
|
|
751
|
+
private definitions;
|
|
752
|
+
private version;
|
|
753
|
+
constructor(config?: PatternRegistryConfig);
|
|
754
|
+
/** Match input text against all enabled patterns. */
|
|
755
|
+
match(content: string, options?: {
|
|
756
|
+
language?: string;
|
|
757
|
+
categories?: string[];
|
|
758
|
+
}): MemoryThreat[];
|
|
759
|
+
/** Add a pattern. Returns a new registry instance. */
|
|
760
|
+
addPattern(pattern: PatternDefinition): PatternRegistry;
|
|
761
|
+
/** Remove a pattern by ID. Returns a new registry instance. */
|
|
762
|
+
removePattern(id: string): PatternRegistry;
|
|
763
|
+
/** Update a pattern by ID. Returns a new registry instance. */
|
|
764
|
+
updatePattern(id: string, updates: Partial<PatternDefinition>): PatternRegistry;
|
|
765
|
+
/** Export as JSON-serializable config. */
|
|
766
|
+
toJSON(): PatternRegistryConfig;
|
|
767
|
+
/** Load from JSON string or object. */
|
|
768
|
+
static fromJSON(input: string | PatternRegistryConfig): PatternRegistry;
|
|
769
|
+
getPatterns(): PatternDefinition[];
|
|
770
|
+
getPatternsByLanguage(lang: string): PatternDefinition[];
|
|
771
|
+
getPatternsByCategory(cat: string): PatternDefinition[];
|
|
772
|
+
getVersion(): string;
|
|
773
|
+
getStats(): {
|
|
774
|
+
total: number;
|
|
775
|
+
byLanguage: Record<string, number>;
|
|
776
|
+
byCategory: Record<string, number>;
|
|
777
|
+
};
|
|
778
|
+
private compile;
|
|
779
|
+
private bumpVersion;
|
|
780
|
+
}
|
|
781
|
+
|
|
782
|
+
/**
|
|
783
|
+
* AgentShield v2 — Memory Guard
|
|
784
|
+
*
|
|
785
|
+
* Validates memory entries against known injection patterns before
|
|
786
|
+
* they are persisted to the agent's memory store.
|
|
787
|
+
*
|
|
788
|
+
* This is the core security module addressing the CrAIBench findings:
|
|
789
|
+
* Princeton demonstrated that memory injection attacks on ElizaOS agents
|
|
790
|
+
* can lead to unauthorized wallet transfers by planting fake instructions
|
|
791
|
+
* in the agent's memory that persist across sessions.
|
|
792
|
+
*
|
|
793
|
+
* Design Pattern: before_tool_callback (ADK) adapted for memory writes
|
|
794
|
+
* Reference: CrAIBench (arxiv.org/html/2503.16248v3)
|
|
795
|
+
*/
|
|
796
|
+
|
|
797
|
+
declare class MemoryGuard {
|
|
798
|
+
private policies;
|
|
799
|
+
private customPatterns;
|
|
800
|
+
constructor(policies: MemoryPolicy[]);
|
|
801
|
+
/**
|
|
802
|
+
* Validate a memory entry before it is persisted.
|
|
803
|
+
* Returns validation result with detected threats.
|
|
804
|
+
*
|
|
805
|
+
* This is the primary guard — called before every memory write.
|
|
806
|
+
*/
|
|
807
|
+
validate(entry: MemoryEntry): MemoryValidationResult;
|
|
808
|
+
/**
|
|
809
|
+
* Detect Solana-specific financial instructions embedded in memory.
|
|
810
|
+
* Looks for transfer amounts, wallet addresses, and program IDs.
|
|
811
|
+
*/
|
|
812
|
+
private detectFinancialInstructions;
|
|
813
|
+
/**
|
|
814
|
+
* Detect attempts to override the agent's system prompt or identity
|
|
815
|
+
* through memory injection.
|
|
816
|
+
*/
|
|
817
|
+
private detectSystemOverrides;
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
/**
|
|
821
|
+
* AgentShield v2 — Transaction Guard
|
|
822
|
+
*
|
|
823
|
+
* Pre-execution validation for all Solana transactions initiated by agents.
|
|
824
|
+
* Implements the before_tool_callback pattern from ADK, adapted for
|
|
825
|
+
* Solana transaction lifecycle.
|
|
826
|
+
*
|
|
827
|
+
* Checks: spending limits, recipient whitelists/blacklists, rate limiting,
|
|
828
|
+
* cooldown periods, token allowlists, and multi-sig thresholds.
|
|
829
|
+
*
|
|
830
|
+
* Design Pattern: before_tool_callback + state-based fallback (Ch. 12/18)
|
|
831
|
+
*/
|
|
832
|
+
|
|
833
|
+
declare class TransactionGuard {
|
|
834
|
+
private policies;
|
|
835
|
+
private rateLimitWindows;
|
|
836
|
+
constructor(policies: TransactionPolicy[]);
|
|
837
|
+
/**
|
|
838
|
+
* Evaluate a transaction request against all active policies.
|
|
839
|
+
* Returns a verdict: allow, block, or escalate.
|
|
840
|
+
*
|
|
841
|
+
* This is the primary guard — called before every transaction send.
|
|
842
|
+
*/
|
|
843
|
+
evaluate(tx: TransactionRequest): TransactionVerdict;
|
|
844
|
+
private checkRateLimit;
|
|
845
|
+
private checkCooldown;
|
|
846
|
+
private recordTransaction;
|
|
847
|
+
private escalateDecision;
|
|
848
|
+
private truncateAddress;
|
|
849
|
+
}
|
|
850
|
+
|
|
851
|
+
/**
|
|
852
|
+
* AgentShield v2 — ElizaOS Security Plugin
|
|
853
|
+
*
|
|
854
|
+
* Main plugin entry point. Registers security guards as ElizaOS
|
|
855
|
+
* providers and actions that intercept agent behavior before
|
|
856
|
+
* transactions execute and before memories are persisted.
|
|
857
|
+
*
|
|
858
|
+
* Architecture:
|
|
859
|
+
* Agent Action → AgentShield Provider (pre-validation)
|
|
860
|
+
* → Memory Guard (validates memory writes)
|
|
861
|
+
* → Transaction Guard (validates Solana transactions)
|
|
862
|
+
* → Anomaly Detector (behavioral analysis)
|
|
863
|
+
* → Audit Logger (immutable event log)
|
|
864
|
+
* → Action proceeds (if allowed) or is blocked
|
|
865
|
+
*
|
|
866
|
+
* Usage:
|
|
867
|
+
* import { agentShieldPlugin } from '@agentshield/plugin';
|
|
868
|
+
* // In your ElizaOS character config:
|
|
869
|
+
* plugins: [agentShieldPlugin]
|
|
870
|
+
*/
|
|
871
|
+
|
|
872
|
+
/** Access all initialized plugin components (available after plugin.init). */
|
|
873
|
+
declare function getPluginState(): {
|
|
874
|
+
policyEngine: PolicyEngine;
|
|
875
|
+
anomalyDetector: AnomalyDetector;
|
|
876
|
+
auditLogger: AuditLogger;
|
|
877
|
+
outputGuard: OutputGuard;
|
|
878
|
+
responseInterceptor: ResponseInterceptor;
|
|
879
|
+
semanticClassifier: SemanticClassifier;
|
|
880
|
+
merkleAudit: MerkleAuditTrail;
|
|
881
|
+
alertManager: AlertManager;
|
|
882
|
+
patternRegistry: PatternRegistry;
|
|
883
|
+
config: AgentShieldConfig;
|
|
884
|
+
};
|
|
885
|
+
declare const agentShieldPlugin: Plugin;
|
|
886
|
+
|
|
887
|
+
export { type AgentShieldConfig, type AgentShieldPolicy, type AlertConfig, AlertManager, type AlertPayload, AnomalyDetector, type AuditCheckpoint, type AuditEvent, type AuditEventType, AuditLogger, BUILTIN_PATTERNS, type BlockedInputContext, type CircuitBreakerConfig, type ClassificationResult, DEFAULT_POLICY, type EnforcementMode, type GuardResult, InputNormalizer, type IntentCategory, type InterceptResult, type MemoryEntry, MemoryGuard, type MemoryPolicy, type MemoryThreat, type MemoryValidationResult, MerkleAuditTrail, OutputGuard, type OutputScanResult, type OutputThreat, type PatternDefinition, PatternRegistry, type PatternRegistryConfig, type PolicyDecision, PolicyEngine, type PolicyEvaluation, type PolicyRule, ResponseInterceptor, SemanticClassifier, TransactionGuard, type TransactionPolicy, type TransactionRequest, type TransactionVerdict, agentShieldPlugin, agentShieldPlugin as default, getPluginState };
|