shroud-privacy 2.2.11 → 2.2.12
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/README.md +5 -4
- package/openclaw.plugin.json +1 -1
- package/package.json +1 -1
- package/dist/agent-session.d.ts +0 -259
- package/dist/agent-session.js +0 -693
- package/dist/compliance.d.ts +0 -44
- package/dist/compliance.js +0 -76
- package/dist/dashboard.d.ts +0 -42
- package/dist/dashboard.js +0 -1558
- package/dist/detectors/injection-multilingual.d.ts +0 -27
- package/dist/detectors/injection-multilingual.js +0 -399
- package/dist/detectors/injection-signatures.d.ts +0 -26
- package/dist/detectors/injection-signatures.js +0 -508
- package/dist/detectors/injection.d.ts +0 -56
- package/dist/detectors/injection.js +0 -269
- package/dist/detectors/tool-guard.d.ts +0 -27
- package/dist/detectors/tool-guard.js +0 -418
- package/dist/event-grader.d.ts +0 -97
- package/dist/event-grader.js +0 -214
- package/dist/exposure.d.ts +0 -29
- package/dist/exposure.js +0 -72
- package/dist/policy.d.ts +0 -99
- package/dist/policy.js +0 -212
- package/dist/profiler-analysis.d.ts +0 -35
- package/dist/profiler-analysis.js +0 -230
- package/dist/profiler-store.d.ts +0 -33
- package/dist/profiler-store.js +0 -118
- package/dist/profiler-types.d.ts +0 -128
- package/dist/profiler-types.js +0 -16
- package/dist/profiler.d.ts +0 -81
- package/dist/profiler.js +0 -392
- package/dist/security-event.d.ts +0 -70
- package/dist/security-event.js +0 -80
- package/dist/siem.d.ts +0 -49
- package/dist/siem.js +0 -113
- package/dist/signature-loader.d.ts +0 -113
- package/dist/signature-loader.js +0 -255
- package/dist/store-file.d.ts +0 -26
- package/dist/store-file.js +0 -79
package/README.md
CHANGED
|
@@ -88,9 +88,10 @@ Shroud does not guarantee compliance — regex-based detection has limitations (
|
|
|
88
88
|
```bash
|
|
89
89
|
openclaw --version # ensure 2026.3.22+
|
|
90
90
|
openclaw plugins install shroud-privacy
|
|
91
|
+
openclaw gateway restart
|
|
91
92
|
```
|
|
92
93
|
|
|
93
|
-
|
|
94
|
+
That's it — Shroud is automatically enabled on install. All 100+ detectors are active with safe defaults, no configuration required. To customise, see [Configure](#configure).
|
|
94
95
|
|
|
95
96
|
### Any agent (via APP)
|
|
96
97
|
|
|
@@ -166,13 +167,13 @@ openclaw gateway restart
|
|
|
166
167
|
|
|
167
168
|
## Configure
|
|
168
169
|
|
|
169
|
-
|
|
170
|
+
Shroud works out of the box with zero configuration. `openclaw plugins install` sets `enabled: true` automatically. To customise, edit `~/.openclaw/openclaw.json` under `plugins.entries."shroud-privacy".config`:
|
|
170
171
|
|
|
171
172
|
```jsonc
|
|
172
173
|
"shroud-privacy": {
|
|
173
|
-
"enabled": true,
|
|
174
|
+
"enabled": true, // set automatically by plugins install
|
|
174
175
|
"config": {
|
|
175
|
-
"auditEnabled": true
|
|
176
|
+
"auditEnabled": true // audit log on — see what Shroud is doing
|
|
176
177
|
// "minConfidence": 0.0 // catch everything (default)
|
|
177
178
|
// "secretKey": "" // auto-generated if empty
|
|
178
179
|
// "persistentSalt": "" // set for cross-session consistency
|
package/openclaw.plugin.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"id": "shroud-privacy",
|
|
3
3
|
"name": "Shroud",
|
|
4
|
-
"version": "2.2.
|
|
4
|
+
"version": "2.2.12",
|
|
5
5
|
"description": "Privacy obfuscation with deterministic fake values and deobfuscation — PII never reaches the LLM, tool calls still work",
|
|
6
6
|
"configSchema": {
|
|
7
7
|
"type": "object",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "shroud-privacy",
|
|
3
|
-
"version": "2.2.
|
|
3
|
+
"version": "2.2.12",
|
|
4
4
|
"description": "Privacy and infrastructure protection for AI agents — detects sensitive data (PII, network topology, credentials, OT/SCADA) and replaces with deterministic fakes before anything reaches the LLM.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
package/dist/agent-session.d.ts
DELETED
|
@@ -1,259 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Agent session tracking — maps LLM API calls to local agent identities.
|
|
3
|
-
*
|
|
4
|
-
* Each agent has a unique identity derived from its system prompt, plugin set,
|
|
5
|
-
* and model. This module tracks which agent is making each LLM call, enabling:
|
|
6
|
-
* - Per-agent WAF rules (different injection policies per agent)
|
|
7
|
-
* - Per-agent behavioural baselines (Track 3)
|
|
8
|
-
* - Per-agent canary attribution (Track 2)
|
|
9
|
-
* - Multi-agent session correlation
|
|
10
|
-
*/
|
|
11
|
-
/** A logged LLM API call. */
|
|
12
|
-
export interface LlmCallRecord {
|
|
13
|
-
timestamp: number;
|
|
14
|
-
agentLabel: string;
|
|
15
|
-
url: string;
|
|
16
|
-
model: string;
|
|
17
|
-
inputTokens: number;
|
|
18
|
-
outputTokens: number;
|
|
19
|
-
cacheReadTokens: number;
|
|
20
|
-
cacheWriteTokens: number;
|
|
21
|
-
cacheHitPct: number;
|
|
22
|
-
responseTimeMs: number;
|
|
23
|
-
channel: string;
|
|
24
|
-
securityEvents: number;
|
|
25
|
-
/** Why the call was made (slack message, heartbeat, cron, tool call, etc.) */
|
|
26
|
-
reason: string;
|
|
27
|
-
}
|
|
28
|
-
/** Agent role classification derived from name, channel, and behaviour. */
|
|
29
|
-
export interface AgentClassification {
|
|
30
|
-
/** Primary role category. */
|
|
31
|
-
role: string;
|
|
32
|
-
/** Confidence percentage (0-100). */
|
|
33
|
-
confidencePct: number;
|
|
34
|
-
/** Confidence tier for display. */
|
|
35
|
-
confidence: "high" | "medium" | "low";
|
|
36
|
-
/** Colour code for dashboard rendering. */
|
|
37
|
-
colour: string;
|
|
38
|
-
/** Keywords that triggered the classification. */
|
|
39
|
-
signals: string[];
|
|
40
|
-
}
|
|
41
|
-
/** Agent health and behavioural compliance status. */
|
|
42
|
-
export interface AgentHealth {
|
|
43
|
-
/** Overall health: "healthy", "warning", "critical". */
|
|
44
|
-
status: "healthy" | "warning" | "critical";
|
|
45
|
-
/** Health colour for dashboard. */
|
|
46
|
-
colour: string;
|
|
47
|
-
/** Is the agent behaving according to its classification? */
|
|
48
|
-
compliant: boolean;
|
|
49
|
-
/** Compliance detail messages. */
|
|
50
|
-
issues: string[];
|
|
51
|
-
/** Last active relative indicator. */
|
|
52
|
-
lastActiveAgo: string;
|
|
53
|
-
/** Security event rate per 100 calls. */
|
|
54
|
-
eventRate: number;
|
|
55
|
-
}
|
|
56
|
-
/** Represents a tracked agent session. */
|
|
57
|
-
export interface AgentSession {
|
|
58
|
-
/** Stable identity hash: SHA256(systemPrompt + pluginList + modelId). */
|
|
59
|
-
agentBuildId: string;
|
|
60
|
-
/** Human-readable label extracted from system prompt (first 60 chars). */
|
|
61
|
-
agentLabel: string;
|
|
62
|
-
/** Session-scoped unique ID. */
|
|
63
|
-
sessionId: string;
|
|
64
|
-
/** When this session was first seen. */
|
|
65
|
-
startedAt: number;
|
|
66
|
-
/** Total LLM API calls made by this agent session. */
|
|
67
|
-
llmCallCount: number;
|
|
68
|
-
/** Total security events attributed to this agent. */
|
|
69
|
-
securityEventCount: number;
|
|
70
|
-
/** Last LLM call timestamp. */
|
|
71
|
-
lastCallAt: number;
|
|
72
|
-
/** LLM model ID detected from API calls (e.g. "claude-3-opus", "gpt-4"). */
|
|
73
|
-
detectedModel: string;
|
|
74
|
-
/** Channel source if detected (e.g. "slack:C00000001", "whatsapp:+353..."). */
|
|
75
|
-
channelSource: string;
|
|
76
|
-
/** Inferred role classification. */
|
|
77
|
-
classification: AgentClassification;
|
|
78
|
-
/** Tool names available to the agent (from body.tools). */
|
|
79
|
-
toolInventory: string[];
|
|
80
|
-
/** SOUL.md extract — agent's core identity/instructions from early messages. */
|
|
81
|
-
soulExtract: string;
|
|
82
|
-
/** Per-agent LLM cache stats. */
|
|
83
|
-
cache: AgentCacheStats;
|
|
84
|
-
/** Active channels this agent has been seen on. */
|
|
85
|
-
channels: string[];
|
|
86
|
-
/** Heartbeat tracking. */
|
|
87
|
-
heartbeat: AgentHeartbeat;
|
|
88
|
-
}
|
|
89
|
-
/** Per-agent heartbeat tracking. */
|
|
90
|
-
export interface AgentHeartbeat {
|
|
91
|
-
/** Whether heartbeat has been detected for this agent. */
|
|
92
|
-
enabled: boolean;
|
|
93
|
-
/** Timestamps of recent heartbeats (last 10). */
|
|
94
|
-
recent: number[];
|
|
95
|
-
/** Average interval between heartbeats (ms). -1 if not enough data. */
|
|
96
|
-
avgIntervalMs: number;
|
|
97
|
-
/** Last heartbeat timestamp. */
|
|
98
|
-
lastAt: number;
|
|
99
|
-
/** Status: "alive", "stale" (2x interval missed), "dead" (5x missed). */
|
|
100
|
-
status: "alive" | "stale" | "dead" | "unknown";
|
|
101
|
-
/** Last heartbeat response (HEARTBEAT_OK or alert text). */
|
|
102
|
-
lastResponse: string;
|
|
103
|
-
}
|
|
104
|
-
/** Per-agent LLM cache tracking for anomaly detection. */
|
|
105
|
-
export interface AgentCacheStats {
|
|
106
|
-
totalInputTokens: number;
|
|
107
|
-
totalOutputTokens: number;
|
|
108
|
-
totalCacheRead: number;
|
|
109
|
-
totalCacheWrite: number;
|
|
110
|
-
/** Running average cache hit ratio (0-1). */
|
|
111
|
-
avgHitRatio: number;
|
|
112
|
-
/** Baseline hit ratio (from first N calls). -1 if not established. */
|
|
113
|
-
baselineHitRatio: number;
|
|
114
|
-
/** Number of calls contributing to the baseline. */
|
|
115
|
-
baselineSamples: number;
|
|
116
|
-
/** Number of calls with cache data. */
|
|
117
|
-
callsWithCache: number;
|
|
118
|
-
}
|
|
119
|
-
/**
|
|
120
|
-
* Tracks agent sessions and maps LLM calls to agent identities.
|
|
121
|
-
* One instance shared via globalThis across all plugin loads.
|
|
122
|
-
*/
|
|
123
|
-
export declare class AgentSessionTracker {
|
|
124
|
-
/** Active sessions keyed by agent label (the stable identity). */
|
|
125
|
-
private _sessions;
|
|
126
|
-
/** Current active agent label. */
|
|
127
|
-
private _currentLabel;
|
|
128
|
-
/** LLM call log (ring buffer, last 200 calls). */
|
|
129
|
-
private _callLog;
|
|
130
|
-
/** Timestamp when the current LLM call started (for response time). */
|
|
131
|
-
private _callStartTime;
|
|
132
|
-
/**
|
|
133
|
-
* Register or update an agent session from system prompt content.
|
|
134
|
-
*
|
|
135
|
-
* Identity strategy: the extracted LABEL is the primary key, not the
|
|
136
|
-
* prompt skeleton hash. System prompts contain too much dynamic content
|
|
137
|
-
* (conversation context, RAG, tool results) to produce stable hashes.
|
|
138
|
-
* The label — extracted from "- Name: X", "You are X", etc. — is the
|
|
139
|
-
* stable identity that humans recognise.
|
|
140
|
-
*
|
|
141
|
-
* The buildId is still computed for fingerprinting but is NOT used as
|
|
142
|
-
* the session key.
|
|
143
|
-
*/
|
|
144
|
-
registerAgent(systemPrompt: string, pluginList?: string[], modelId?: string): AgentSession;
|
|
145
|
-
/** Update detected model from LLM API request body. */
|
|
146
|
-
updateModel(model: string): void;
|
|
147
|
-
/** Update channel source (e.g. "slack:C00000001"). */
|
|
148
|
-
updateChannel(source: string): void;
|
|
149
|
-
/**
|
|
150
|
-
* Update per-agent cache stats from an LLM response.
|
|
151
|
-
* Returns anomaly alerts if cache behaviour deviates from baseline.
|
|
152
|
-
*/
|
|
153
|
-
updateCache(usage: {
|
|
154
|
-
inputTokens: number;
|
|
155
|
-
outputTokens: number;
|
|
156
|
-
cacheReadTokens: number;
|
|
157
|
-
cacheWriteTokens: number;
|
|
158
|
-
}): {
|
|
159
|
-
alert: string;
|
|
160
|
-
severity: "medium" | "high";
|
|
161
|
-
} | null;
|
|
162
|
-
/** Record a heartbeat for the current agent. Returns alert if missed. */
|
|
163
|
-
recordHeartbeat(response?: string): {
|
|
164
|
-
alert: string;
|
|
165
|
-
severity: "medium" | "high";
|
|
166
|
-
} | null;
|
|
167
|
-
/** Check all agents for missed heartbeats. Call periodically. */
|
|
168
|
-
checkHeartbeatHealth(): Array<{
|
|
169
|
-
agentLabel: string;
|
|
170
|
-
status: string;
|
|
171
|
-
alert: string;
|
|
172
|
-
}>;
|
|
173
|
-
/** Detect and record the channel from prompt metadata. */
|
|
174
|
-
updateChannelFromPrompt(prompt: string): string | null;
|
|
175
|
-
/** Update tool inventory from body.tools array. Only sets once (first call). */
|
|
176
|
-
updateTools(tools: string[]): void;
|
|
177
|
-
/** Update SOUL extract from early messages. Only sets once. */
|
|
178
|
-
updateSoul(soul: string): void;
|
|
179
|
-
/** Record an LLM API call for the current agent. */
|
|
180
|
-
recordLlmCall(): AgentSession | null;
|
|
181
|
-
/** Record a security event for the current agent. */
|
|
182
|
-
recordSecurityEvent(count?: number): void;
|
|
183
|
-
/** Get the current active agent session. */
|
|
184
|
-
getCurrentSession(): AgentSession | null;
|
|
185
|
-
/** Get the current agent build ID. */
|
|
186
|
-
getCurrentBuildId(): string;
|
|
187
|
-
/** Get all tracked agent sessions. */
|
|
188
|
-
getAllSessions(): AgentSession[];
|
|
189
|
-
/** Get session by build ID. */
|
|
190
|
-
getSession(buildId: string): AgentSession | null;
|
|
191
|
-
/** Get session by label (primary key). */
|
|
192
|
-
getSessionByLabel(label: string): AgentSession | null;
|
|
193
|
-
/** Mark the start of an LLM call (for response time tracking). */
|
|
194
|
-
markCallStart(): void;
|
|
195
|
-
/** Log a completed LLM call with full details. */
|
|
196
|
-
logCall(details: {
|
|
197
|
-
url: string;
|
|
198
|
-
model: string;
|
|
199
|
-
inputTokens: number;
|
|
200
|
-
outputTokens: number;
|
|
201
|
-
cacheReadTokens: number;
|
|
202
|
-
cacheWriteTokens: number;
|
|
203
|
-
channel: string;
|
|
204
|
-
securityEvents: number;
|
|
205
|
-
reason: string;
|
|
206
|
-
}): void;
|
|
207
|
-
/** Get the LLM call log. */
|
|
208
|
-
getCallLog(): readonly LlmCallRecord[];
|
|
209
|
-
/** Reset all session tracking. */
|
|
210
|
-
reset(): void;
|
|
211
|
-
}
|
|
212
|
-
/**
|
|
213
|
-
* Compute a stable agent build ID.
|
|
214
|
-
*
|
|
215
|
-
* Uses a "skeleton" of the system prompt rather than the full text.
|
|
216
|
-
* This makes the ID resilient to:
|
|
217
|
-
* - Dynamic timestamps, dates, session IDs injected into prompts
|
|
218
|
-
* - User names or account-specific context
|
|
219
|
-
* - Retrieved RAG snippets appended to the base prompt
|
|
220
|
-
* - Minor wording tweaks during prompt iteration
|
|
221
|
-
*
|
|
222
|
-
* The skeleton is: first 500 chars of the prompt with numbers, dates,
|
|
223
|
-
* emails, UUIDs, and hex strings normalized to placeholders.
|
|
224
|
-
*/
|
|
225
|
-
export declare function computeBuildId(systemPrompt: string, pluginList: string[], modelId: string): string;
|
|
226
|
-
/**
|
|
227
|
-
* Extract a stable "skeleton" from a system prompt by normalizing
|
|
228
|
-
* dynamic content to placeholders.
|
|
229
|
-
*
|
|
230
|
-
* Normalizes: timestamps, dates, numbers >4 digits, emails, UUIDs,
|
|
231
|
-
* hex strings >8 chars, IP addresses, URLs with path components.
|
|
232
|
-
* Keeps: the structural words, role definitions, tool descriptions,
|
|
233
|
-
* behavioral instructions — the parts that define the agent's identity.
|
|
234
|
-
*/
|
|
235
|
-
export declare function extractPromptSkeleton(prompt: string): string;
|
|
236
|
-
/**
|
|
237
|
-
* Classify an agent's role from its label and system prompt content.
|
|
238
|
-
* Uses keyword matching against a role taxonomy — no LLM call needed.
|
|
239
|
-
*
|
|
240
|
-
* Confidence scoring:
|
|
241
|
-
* 90% — role keyword in agent label (explicit naming)
|
|
242
|
-
* 70% — role keyword in SOUL.md "You are a [role]" declaration
|
|
243
|
-
* 40% — role keyword found in general prompt metadata
|
|
244
|
-
* 10% — no match, "General Agent"
|
|
245
|
-
*
|
|
246
|
-
* Multiple signal matches boost confidence by 5% each (capped at 95%).
|
|
247
|
-
*/
|
|
248
|
-
export declare function classifyAgent(label: string, systemPrompt: string): AgentClassification;
|
|
249
|
-
/**
|
|
250
|
-
* Enhanced classifier that uses tools + SOUL.md + label.
|
|
251
|
-
* Called when new data (tools or SOUL) becomes available.
|
|
252
|
-
*/
|
|
253
|
-
export declare function classifyAgentWithTools(label: string, soulExtract: string, tools: string[]): AgentClassification;
|
|
254
|
-
/** Detect the channel type from OpenClaw prompt metadata. */
|
|
255
|
-
export declare function detectChannel(prompt: string): string | null;
|
|
256
|
-
/** Check if a prompt is a heartbeat prompt. */
|
|
257
|
-
export declare function isHeartbeatPrompt(prompt: string): boolean;
|
|
258
|
-
/** Check if a response is a heartbeat OK response. */
|
|
259
|
-
export declare function isHeartbeatOk(response: string): boolean;
|