@upx-us/shield 0.6.7 → 0.6.10

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 CHANGED
@@ -4,6 +4,32 @@ All notable changes to this project will be documented in this file.
4
4
 
5
5
  ---
6
6
 
7
+ ## [0.6.10] — 2026-03-12
8
+
9
+ ### Fixed
10
+ - **Local event buffer not populated in plugin mode** — `appendEvents` and `initEventStore` were implemented in the standalone bridge (`src/index.ts`) but never wired into the plugin-mode poll loop (`index.ts`). As a result, `openclaw shield logs` always returned "No events found" even when events were being sent successfully to the platform. Fixed by wiring the event store into the plugin-mode startup and poll cycle (#148).
11
+
12
+ ### Changed
13
+ - **Local event buffer default increased to 250** — was 123. Provides better forensic coverage (~24h of normal activity) without significant storage impact. `SHIELD_LOCAL_EVENT_LIMIT` env var still overrides this. README and config updated (#148).
14
+ - **Version corrected from 1.3.0 → 0.6.10** — the 1.3.0 version in `package.json` was premature; this release re-anchors versioning at the correct next increment after 0.6.8.
15
+
16
+ ### Added
17
+ - **`openclaw.message_length_bytes` enrichment field** — message events now include the byte length of the message body as `openclaw.message_length_bytes`. Enables detection rules based on message size thresholds (#152).
18
+ - **Event buffer diagnostics in `shield.status`** — `shield.status` RPC now includes an `eventBuffer` section showing: `enabled`, `path`, `total` events buffered, `oldest`/`newest` timestamps, and `redactedCount`. Makes it immediately diagnosable if the local log is empty or disabled (#148).
19
+
20
+ ### Docs
21
+ - **Case investigation workflow in SKILL.md** — documents the standard 4-step forensic procedure: cases + logs + vault correlation for complete incident context. Covers correlating case timestamps, log event windows, and redaction vault lookups (#148, #151).
22
+ - **Expanded uninstall documentation in README** — step-by-step uninstall guide covering plugin removal, local data cleanup (with file-by-file breakdown), and platform instance deactivation. Includes redaction vault retention warning (#151).
23
+
24
+ ---
25
+
26
+ ## [0.6.8] — 2026-03-10
27
+
28
+ ### Fixed
29
+ - **curl credential redaction** — `curl -u "user:pass"`, `--user user:pass` (all quote variants), and `Authorization: Basic <base64>` are now redacted as `secret:HASH` before reaching the SIEM. Discovered via live credential leak (#137).
30
+
31
+ ---
32
+
7
33
  ## [0.6.7] — 2026-03-10
8
34
 
9
35
  ### Fixed
package/README.md CHANGED
@@ -309,7 +309,7 @@ Shield stores a rolling log of recently sent events locally for offline inspecti
309
309
  **Location:** `~/.openclaw/shield/data/event-log.jsonl`
310
310
 
311
311
  **Defaults:**
312
- - Last **123 events** or **24 hours** (whichever limit is reached first)
312
+ - Last **250 events** or **24 hours** (whichever limit is reached first)
313
313
  - Enabled by default
314
314
  - Events are stored **after redaction** — same data sent to the platform
315
315
 
@@ -327,7 +327,7 @@ openclaw shield logs --format json # JSON output for piping
327
327
  | Variable | Default | Description |
328
328
  |---|---|---|
329
329
  | `SHIELD_LOCAL_EVENT_BUFFER` | `true` | Set to `false` to disable local storage |
330
- | `SHIELD_LOCAL_EVENT_LIMIT` | `123` | Maximum number of events to retain |
330
+ | `SHIELD_LOCAL_EVENT_LIMIT` | `250` | Maximum number of events to retain |
331
331
 
332
332
  ---
333
333
 
@@ -498,24 +498,49 @@ Events generated during an expiry or quota period are permanently lost. Renew yo
498
498
 
499
499
  ## Uninstalling
500
500
 
501
+ ### 1. Remove the plugin
502
+
501
503
  ```bash
502
504
  openclaw plugins uninstall shield
503
505
  ```
504
506
 
505
- This removes the plugin code. To fully remove all local Shield data:
507
+ ### 2. Remove local Shield data (optional recommended for privacy hygiene)
506
508
 
507
509
  ```bash
508
510
  rm -rf ~/.openclaw/shield/
509
511
  ```
510
512
 
511
- This deletes credentials, cursors, IP cache, and the redaction vault.
513
+ This removes all local files Shield writes at runtime:
514
+
515
+ | File | Contents |
516
+ |---|---|
517
+ | `config.env` | HMAC secret and instance fingerprint |
518
+ | `data/cursor.json` | Event cursor positions per log source |
519
+ | `data/public-ip.cache` | Cached public IP for telemetry |
520
+ | `data/instance-cache.json` | Cached instance metadata |
521
+ | `data/exclusions.json` | Allowlist entries (suppress specific patterns) |
522
+ | `data/case-monitor-state.json` | Case notification state (acknowledged case IDs) |
523
+ | `data/event-log.jsonl` | Local event ring buffer (24h) |
524
+ | `data/redaction-vault.json` | **Redaction token → original value mapping** |
525
+
526
+ > ⚠️ **Redaction vault**: `data/redaction-vault.json` maps redaction tokens back to original values (secrets, hostnames, file paths). Once deleted, you cannot reverse-lookup redacted values from past events. Retain this file for as long as your data retention policy requires before deleting.
527
+
528
+ ### 3. Deactivate the platform instance
512
529
 
513
- > **Note:** The redaction vault (`data/redaction-vault.json`) contains the mapping from redaction tokens back to original values. Deleting it means you can no longer reverse-lookup redacted values from past events. Retain this file for as long as your data retention policy requires.
530
+ Removing local files does **not** automatically deactivate your registration on the UPX platform.
514
531
 
515
- Platform-side instance data can be managed via [uss.upx.com](https://uss.upx.com).
532
+ To fully remove your instance: log in to **[uss.upx.com](https://uss.upx.com)** → Instances → Delete.
533
+
534
+ Until deactivated, the instance remains registered and may count against your subscription quota.
516
535
 
517
536
  ---
518
537
 
519
538
  ## Need help?
520
539
 
521
540
  Visit [uss.upx.com](https://uss.upx.com) or contact your Shield administrator.
541
+
542
+ ---
543
+
544
+ ## License & Distribution
545
+
546
+ The skill wrapper is distributed under MIT-0 on ClaWHub as required by the platform. The underlying plugin and platform remain proprietary UPX Technologies, Inc. IP.
package/dist/index.js CHANGED
@@ -52,6 +52,7 @@ const counters_1 = require("./src/counters");
52
52
  const cli_cases_1 = require("./src/cli-cases");
53
53
  const case_monitor_1 = require("./src/case-monitor");
54
54
  const exclusions_1 = require("./src/exclusions");
55
+ const event_store_1 = require("./src/event-store");
55
56
  const updater_1 = require("./src/updater");
56
57
  const rpc_1 = require("./src/rpc");
57
58
  const inventory_1 = require("./src/inventory");
@@ -594,6 +595,9 @@ exports.default = {
594
595
  log.info('shield', `Starting monitoring bridge v${version_1.VERSION} (poll: ${config.pollIntervalMs}ms, dryRun: ${config.dryRun})`);
595
596
  (0, exclusions_1.initExclusions)((0, path_1.join)((0, os_1.homedir)(), '.openclaw', 'shield', 'data'));
596
597
  (0, case_monitor_1.initCaseMonitor)((0, path_1.join)((0, os_1.homedir)(), '.openclaw', 'shield', 'data'));
598
+ if (config.localEventBuffer) {
599
+ (0, event_store_1.initEventStore)((0, path_1.join)((0, os_1.homedir)(), '.openclaw', 'shield', 'data'), { maxEvents: config.localEventLimit });
600
+ }
597
601
  const runtime = api.runtime;
598
602
  if (runtime?.system?.enqueueSystemEvent && runtime?.system?.requestHeartbeatNow) {
599
603
  const config = api.config;
@@ -826,6 +830,18 @@ exports.default = {
826
830
  state.lastSync = lastSync;
827
831
  state.captureSeenSinceLastSync = false;
828
832
  writeAllTimeStats({ eventsProcessed: accepted, lastSync });
833
+ if (config.localEventBuffer) {
834
+ const summaries = envelopes.map(env => ({
835
+ ts: env.event.timestamp,
836
+ type: env.event.event_type || 'UNKNOWN',
837
+ tool: env.event.tool_name || 'unknown',
838
+ summary: env.event.tool_metadata?.['openclaw.display_summary'] || env.event.tool_name || 'event',
839
+ session: env.event.session_id || '?',
840
+ model: env.event.model || '?',
841
+ redacted: !!env.source?.plugin?.redaction_applied,
842
+ }));
843
+ (0, event_store_1.appendEvents)(summaries);
844
+ }
829
845
  }
830
846
  else {
831
847
  state.consecutiveFailures++;
@@ -918,8 +934,11 @@ exports.default = {
918
934
  vaultSummary = null;
919
935
  }
920
936
  }
937
+ const hasSecret = !!creds?.hmacSecret && !PLACEHOLDER_VALUES.has((creds.hmacSecret || '').trim().toLowerCase());
938
+ const stateField = hasSecret ? (activated ? 'connected' : 'pending') : 'unconfigured';
921
939
  respond(true, {
922
940
  activated,
941
+ state: stateField,
923
942
  running: state.running,
924
943
  lastPollAt: state.lastPollAt,
925
944
  lastCaptureAt: state.lastCaptureAt,
@@ -946,6 +965,24 @@ exports.default = {
946
965
  redaction: {
947
966
  vault: vaultSummary,
948
967
  },
968
+ eventBuffer: (() => {
969
+ try {
970
+ const { summarizeEvents: se } = require('./src/event-store');
971
+ const rpcConfig = (0, config_1.loadConfig)({});
972
+ const summary = se();
973
+ return {
974
+ enabled: rpcConfig.localEventBuffer,
975
+ path: (0, path_1.join)((0, os_1.homedir)(), '.openclaw', 'shield', 'data', 'event-log.jsonl'),
976
+ total: summary.total,
977
+ oldest: summary.oldest,
978
+ newest: summary.newest,
979
+ redactedCount: summary.redactedCount,
980
+ };
981
+ }
982
+ catch (_) {
983
+ return { enabled: false, path: null, total: 0, oldest: null, newest: null, redactedCount: 0 };
984
+ }
985
+ })(),
949
986
  });
950
987
  });
951
988
  api.registerGatewayMethod('shield.flush', ({ respond }) => {
@@ -141,7 +141,7 @@ function loadConfig(overrides) {
141
141
  collectHostMetrics: overrides?.collectHostMetrics ?? (process.env.COLLECT_HOST_METRICS === 'true'),
142
142
  redactionEnabled: overrides?.redactionEnabled ?? (process.env.REDACTION_ENABLED !== 'false'),
143
143
  localEventBuffer: process.env.SHIELD_LOCAL_EVENT_BUFFER !== 'false',
144
- localEventLimit: safeParseInt(process.env.SHIELD_LOCAL_EVENT_LIMIT, 123),
144
+ localEventLimit: safeParseInt(process.env.SHIELD_LOCAL_EVENT_LIMIT, 250),
145
145
  credentials,
146
146
  };
147
147
  }
@@ -42,7 +42,7 @@ exports._getConfigForTesting = _getConfigForTesting;
42
42
  const fs_1 = require("fs");
43
43
  const path_1 = require("path");
44
44
  const log = __importStar(require("./log"));
45
- const DEFAULT_MAX_EVENTS = 123;
45
+ const DEFAULT_MAX_EVENTS = 250;
46
46
  const DEFAULT_MAX_AGE_MS = 24 * 60 * 60 * 1000;
47
47
  let _config = null;
48
48
  function initEventStore(dataDir, opts) {
@@ -34,6 +34,7 @@ function enrich(tool, ctx) {
34
34
  const content = args.message || args.caption || '';
35
35
  if (content) {
36
36
  meta['openclaw.message_content'] = content.length > 500 ? content.slice(0, 500) : content;
37
+ meta['openclaw.message_length_bytes'] = String(Buffer.byteLength(String(content), 'utf8'));
37
38
  }
38
39
  }
39
40
  if (args.buffer) {
@@ -29,6 +29,14 @@ exports.secretKeyStrategy = {
29
29
  (0, counters_1.recordRedaction)('BEARER_TOKEN');
30
30
  return `${prefix}${hmac('secret', token)}`;
31
31
  });
32
+ result = result.replace(/(-u|--user)\s+(['"]?)([^\s'"]+:[^\s'"]*)\2/g, (_, flag, _quote, credential) => {
33
+ (0, counters_1.recordRedaction)('CURL_CREDENTIAL');
34
+ return `${flag} ${hmac('secret', credential)}`;
35
+ });
36
+ result = result.replace(/(Authorization:\s*Basic\s+)([A-Za-z0-9+/]+=*)/g, (_, prefix, token) => {
37
+ (0, counters_1.recordRedaction)('CURL_CREDENTIAL');
38
+ return `${prefix}${hmac('secret', token)}`;
39
+ });
32
40
  result = result.replace(/((?:SECRET|TOKEN|KEY|PASSWORD|API_KEY)=)(\S+)/gi, (_, prefix, secret) => {
33
41
  const prefixUpper = prefix.toUpperCase();
34
42
  if (prefixUpper.startsWith('PASSWORD'))
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "id": "shield",
3
3
  "name": "OpenClaw Shield",
4
- "description": "Real-time security monitoring streams enriched, redacted security events to the Shield detection platform.",
5
- "version": "0.6.7",
4
+ "description": "Real-time security monitoring \u2014 streams enriched, redacted security events to the Shield detection platform.",
5
+ "version": "0.6.10",
6
6
  "skills": [
7
7
  "./skills"
8
8
  ],
@@ -54,7 +54,7 @@
54
54
  "uiHints": {
55
55
  "installationKey": {
56
56
  "label": "Installation Key",
57
- "description": "One-time key from your trial signup at https://www.upx.com/en/lp/openclaw-shield-upx Required for first-time activation only. After activation, log in at https://uss.upx.com"
57
+ "description": "One-time key from your trial signup at https://www.upx.com/en/lp/openclaw-shield-upx \u2014 Required for first-time activation only. After activation, log in at https://uss.upx.com"
58
58
  },
59
59
  "enabled": {
60
60
  "label": "Enable security monitoring"
@@ -78,7 +78,7 @@
78
78
  },
79
79
  "clawhub": {
80
80
  "slug": "openclaw-shield-upx",
81
- "skillVersion": "0.6.5",
81
+ "skillVersion": "0.6.6",
82
82
  "note": "ClawHub auto-increments on publish. Update this after each clawhub submission."
83
83
  }
84
84
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@upx-us/shield",
3
- "version": "0.6.7",
3
+ "version": "0.6.10",
4
4
  "description": "Security monitoring plugin for OpenClaw agents — streams enriched security events to the Shield detection platform",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -58,7 +58,10 @@
58
58
  "threat-detection",
59
59
  "agent-protection",
60
60
  "audit",
61
+ "protect",
61
62
  "realtime-monitoring",
63
+ "event-monitoring",
64
+ "security-monitoring",
62
65
  "dlp",
63
66
  "anomaly-detection"
64
67
  ],
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: openclaw-shield-upx
3
- description: "SIEM and security monitoring for OpenClaw agents — protect your agent, detect threats, audit events, monitor suspicious activity. Use when: user asks about security status, SIEM, Shield health, event logs, redaction vault, protecting their agent, threat detection, or suspicious activity. NOT for: general OS hardening, firewall config, or network security unrelated to OpenClaw agents."
3
+ description: "Security monitoring and threat detection for OpenClaw agents — protect your agent with real-time SIEM, detect threats, monitor agent activity, and audit events. Use when: user asks about security status, Shield health, event logs, redaction vault, setting up agent protection, enabling SIEM, detecting threats, monitoring agent activity, or auditing agent actions. NOT for: general OS hardening, firewall config, or network security unrelated to OpenClaw agents."
4
4
  homepage: https://www.upx.com/en/lp/openclaw-shield-upx
5
5
  source: https://www.npmjs.com/package/@upx-us/shield
6
6
  license: "Proprietary — UPX Technologies, Inc. All rights reserved."
@@ -37,12 +37,40 @@ Shield requires the `@upx-us/shield` plugin and an active subscription.
37
37
 
38
38
  ## Plugin State Check
39
39
 
40
- Before responding to any Shield-related request, run `openclaw shield status` and branch on the result:
41
-
42
- - **Command not found / exit non-zero**: Shield plugin is not installed. Tell the user Shield requires the `@upx-us/shield` plugin and an active subscription. Direct them to: https://www.upx.com/en/lp/openclaw-shield-upx — explain the free 30-day trial. Do **not** run any install commands yourself.
43
- - **`status: unconfigured`** (no subscription key configured): Plugin is installed but not yet registered. Direct the user to https://www.upx.com/en/lp/openclaw-shield-upx to subscribe and obtain their subscription key, then add it to their Shield config.
44
- - **`status: pending`** (key set, registration in progress): Registration is in progress. Ask the user to wait 1–2 minutes and retry. If it persists, they can check their account at https://uss.upx.com.
45
- - **`status: active`**: Plugin is healthy proceed normally with the commands below.
40
+ Before responding to ANY Shield-related request, run `openclaw shield status` and interpret the result:
41
+
42
+ ### State A Plugin not installed
43
+ (command not found, or exit code non-zero with plugin_not_found)
44
+ Respond with:
45
+ > Shield is not installed yet. Start your free 30-day trial at:
46
+ > https://www.upx.com/en/lp/openclaw-shield-upx
47
+ >
48
+ > Then install the plugin:
49
+ > ```
50
+ > openclaw plugins install @upx-us/shield
51
+ > openclaw plugins run shield setup
52
+ > ```
53
+
54
+ ### State B — Plugin installed but no installationKey
55
+ (status contains installationKey: null or state: "unconfigured")
56
+ Respond with:
57
+ > Shield is installed but not activated. Sign up for a trial at:
58
+ > https://www.upx.com/en/lp/openclaw-shield-upx
59
+ >
60
+ > Once you have your installation key, run:
61
+ > ```
62
+ > openclaw plugins run shield setup
63
+ > ```
64
+
65
+ ### State C — Key set but not yet activated
66
+ (status contains state: "pending" or state: "unregistered")
67
+ Respond with:
68
+ > Shield has an installation key but hasn't activated yet. This usually takes under a minute.
69
+ > If it has been more than 5 minutes, check your key at https://uss.upx.com or contact support.
70
+
71
+ ### State D — Fully active
72
+ (status contains state: "connected" or connected: true)
73
+ Proceed normally. No onboarding message needed.
46
74
 
47
75
  **Constraints**: Only use `openclaw shield` commands for detection. Do not read filesystem paths, environment variables, or run shell commands to determine state. Do not install or uninstall packages on behalf of the user.
48
76
 
@@ -50,6 +78,20 @@ Before responding to any Shield-related request, run `openclaw shield status` an
50
78
 
51
79
  When a Shield case fires or the user asks about an alert: use `openclaw shield cases` to list open cases and `openclaw shield cases --id <id>` for full detail (timeline, matched events, playbook). Severity guidance: **CRITICAL/HIGH** → surface immediately and ask if they want to investigate; **MEDIUM** → present and offer a playbook walkthrough; **LOW/INFO** → mention without interrupting the current task. Always include: rule name, what it detects, when it fired, and the first recommended remediation step. Confirm with the user before resolving — never resolve autonomously.
52
80
 
81
+ ## Case Investigation Workflow
82
+
83
+ When a Shield case fires, correlate three data sources to determine true positive vs. false positive:
84
+
85
+ **Step 1 — Case detail** (`openclaw shield cases show <CASE_ID>`): What triggered the rule. Note the case timestamp — it anchors the correlation window.
86
+
87
+ **Step 2 — Surrounding logs** (`openclaw shield logs --since 30m --type TOOL_CALL`): Look for events 5–15 minutes before and after the case timestamp. Reveals if the alert was isolated or part of a sequence.
88
+
89
+ **Step 3 — Vault context** (`openclaw shield vault show`): If the case involves redacted credentials, hostnames, or commands, the vault reveals hashed representations and redaction categories.
90
+
91
+ **Step 4 — Correlate and assess**: Case detail = *what* fired the rule; Logs = *context*; Vault = *what was actually accessed*. Present findings and ask whether to resolve, investigate further, or add to the allowlist.
92
+
93
+ Note: a future `openclaw shield investigate <CASE_ID>` helper command will automate this workflow.
94
+
53
95
  ## Threat & Protection Questions
54
96
 
55
97
  When asked "is my agent secure?", "am I protected?", or "what's being detected?": run `openclaw shield status` (health, event rate, last sync) and `openclaw shield cases` (open cases by severity). Summarise: rules active, last event ingested, any open cases. No cases → "Shield is monitoring X rules across Y event categories." Open cases → list by severity. If asked what Shield covers: explain it monitors for suspicious patterns across secret handling, access behaviour, outbound activity, injection attempts, config changes, and behavioural anomalies — without disclosing specific rule names or logic.
@@ -104,6 +146,25 @@ RPC responses include a `display` field with pre-formatted text. When present, u
104
146
 
105
147
  When discussing a case, offer action buttons (resolve, false positive, investigate) via the message tool so users can act with one tap.
106
148
 
149
+ ## Uninstalling
150
+
151
+ To fully remove Shield:
152
+
153
+ 1. Uninstall the plugin:
154
+ ```
155
+ openclaw plugins uninstall shield
156
+ ```
157
+
158
+ 2. Optionally remove local Shield data:
159
+ ```
160
+ rm -rf ~/.openclaw/shield/
161
+ ```
162
+ Files removed include: `config.json`, `data/event-buffer.jsonl`, `data/redaction-vault.json`, `data/cursor.json`, `data/instance.json`, `logs/shield.log`, `logs/bridge.log`, `state/monitor.json`.
163
+
164
+ ⚠️ Deleting `data/redaction-vault.json` removes the ability to reverse-lookup past redacted values. Check your data retention needs before deleting.
165
+
166
+ 3. Deactivate your instance at [uss.upx.com](https://uss.upx.com) — local uninstall does not deactivate your platform subscription or instance.
167
+
107
168
  ## Notes
108
169
 
109
170
  - Shield does not interfere with agent behavior or performance