@upx-us/shield 0.7.2 → 0.7.3

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,15 @@ All notable changes to this project will be documented in this file.
4
4
 
5
5
  ---
6
6
 
7
+ ## [0.7.3] — 2026-03-13
8
+
9
+ ### Fixed
10
+ - Trigger attribution (`trigger_type`, `author_name`, `trigger_type` fields) now works correctly in OpenClaw plugin mode — the plugin entry point was calling `transformEntries` without forwarding `sessionDirs`, so attribution was silently skipped on every event for all plugin-mode installations
11
+ - Session directory discovery is now robust when the plugin process is spawned with a different `HOME` environment variable than the main OpenClaw process (common on VPS and Docker deployments) — discovery now walks up from the plugin install path to find the `agents/` directory rather than relying solely on `homedir()`
12
+ - `trigger.type` is now always written to `tool_metadata` (as `"unknown"`) even when session directory lookup fails entirely, ensuring the field is never silently absent from SIEM events
13
+
14
+ ---
15
+
7
16
  ## [0.7.2] — 2026-03-13
8
17
 
9
18
  ### Fixed
package/dist/index.js CHANGED
@@ -775,7 +775,7 @@ exports.default = {
775
775
  state.lastCaptureAt = Date.now();
776
776
  state.captureSeenSinceLastSync = true;
777
777
  markStateDirty();
778
- let envelopes = transformEntries(entries);
778
+ let envelopes = transformEntries(entries, config.sessionDirs);
779
779
  const { valid: validEvents, quarantined } = validate(envelopes.map(e => e.event));
780
780
  if (quarantined > 0) {
781
781
  state.quarantineCount += quarantined;
@@ -17,6 +17,7 @@ export interface Config {
17
17
  localEventLimit: number;
18
18
  credentials: ShieldCredentials;
19
19
  }
20
+ export declare function deriveAgentsDirFromInstallPath(startDir?: string): string | null;
20
21
  export declare const SHIELD_CONFIG_PATH: string;
21
22
  export declare function injectConfigEnv(): void;
22
23
  export declare function loadCredentials(): ShieldCredentials;
@@ -34,6 +34,7 @@ var __importStar = (this && this.__importStar) || (function () {
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.SHIELD_CONFIG_PATH = void 0;
37
+ exports.deriveAgentsDirFromInstallPath = deriveAgentsDirFromInstallPath;
37
38
  exports.injectConfigEnv = injectConfigEnv;
38
39
  exports.loadCredentials = loadCredentials;
39
40
  exports.loadCredentialsFromPluginConfig = loadCredentialsFromPluginConfig;
@@ -42,7 +43,28 @@ const os_1 = require("os");
42
43
  const path_1 = require("path");
43
44
  const fs_1 = require("fs");
44
45
  const log = __importStar(require("./log"));
45
- const OPENCLAW_AGENTS_DIR = (0, path_1.join)((0, os_1.homedir)(), '.openclaw/agents');
46
+ function deriveAgentsDirFromInstallPath(startDir) {
47
+ let dir = startDir ?? __dirname;
48
+ for (let i = 0; i < 8; i++) {
49
+ const parent = (0, path_1.dirname)(dir);
50
+ if (parent === dir)
51
+ break;
52
+ dir = parent;
53
+ const candidate = (0, path_1.join)(dir, 'agents');
54
+ if ((0, fs_1.existsSync)(candidate))
55
+ return candidate;
56
+ }
57
+ return null;
58
+ }
59
+ function resolveAgentsDir() {
60
+ if (process.env.OPENCLAW_AGENTS_DIR)
61
+ return process.env.OPENCLAW_AGENTS_DIR;
62
+ const derived = deriveAgentsDirFromInstallPath();
63
+ if (derived)
64
+ return derived;
65
+ return (0, path_1.join)((0, os_1.homedir)(), '.openclaw', 'agents');
66
+ }
67
+ const OPENCLAW_AGENTS_DIR = resolveAgentsDir();
46
68
  function safeParseInt(value, fallback) {
47
69
  if (!value)
48
70
  return fallback;
@@ -334,7 +334,9 @@ function transformEntries(entries, sessionDirs) {
334
334
  if (seen.has(key))
335
335
  continue;
336
336
  seen.add(key);
337
- const dir = findSessionDir(entry._agentId, sessionDirs);
337
+ const dir = sessionDirs.length === 1
338
+ ? sessionDirs[0]
339
+ : findSessionDir(entry._agentId, sessionDirs);
338
340
  if (dir) {
339
341
  const ctx = (0, attributor_1.resolveAttribution)(entry._sessionId, entry._agentId, dir);
340
342
  attributionMap.set(key, ctx);
@@ -382,13 +384,11 @@ function transformEntries(entries, sessionDirs) {
382
384
  event.tool_metadata['openclaw.target_workspace'] = targetWorkspace;
383
385
  }
384
386
  const attrKey = `${agentId}::${entry._sessionId}`;
385
- const attrCtx = attributionMap.get(attrKey);
386
- if (attrCtx) {
387
- flattenTriggerToMetadata(event, attrCtx);
388
- const triggerField = buildTriggerField(attrCtx);
389
- if (triggerField) {
390
- event.trigger = triggerField;
391
- }
387
+ const attrCtx = attributionMap.get(attrKey) ?? { trigger_type: 'unknown' };
388
+ flattenTriggerToMetadata(event, attrCtx);
389
+ const triggerField = buildTriggerField(attrCtx);
390
+ if (triggerField) {
391
+ event.trigger = triggerField;
392
392
  }
393
393
  log.debug('transformer', `TOOL_CALL tool=${toolName} session=${entry._sessionId} agent=${agentId} schema=${schema.constructor?.name || 'unknown'} admin=${event.tool_metadata?.['openclaw.is_administrative'] === 'true'}`, log.isDebug ? event : undefined);
394
394
  (0, counters_1.recordEventType)(event.event_type);
@@ -403,13 +403,11 @@ function transformEntries(entries, sessionDirs) {
403
403
  event.tool_metadata['openclaw.is_administrative'] = 'true';
404
404
  }
405
405
  const attrKeyR = `${agentId}::${entry._sessionId}`;
406
- const attrCtxR = attributionMap.get(attrKeyR);
407
- if (attrCtxR) {
408
- flattenTriggerToMetadata(event, attrCtxR);
409
- const triggerFieldR = buildTriggerField(attrCtxR);
410
- if (triggerFieldR) {
411
- event.trigger = triggerFieldR;
412
- }
406
+ const attrCtxR = attributionMap.get(attrKeyR) ?? { trigger_type: 'unknown' };
407
+ flattenTriggerToMetadata(event, attrCtxR);
408
+ const triggerFieldR = buildTriggerField(attrCtxR);
409
+ if (triggerFieldR) {
410
+ event.trigger = triggerFieldR;
413
411
  }
414
412
  log.debug('transformer', `TOOL_RESULT tool=${event.tool_name} session=${entry._sessionId} agent=${agentId}`, log.isDebug ? event : undefined);
415
413
  (0, counters_1.recordEventType)(event.event_type);
@@ -2,7 +2,7 @@
2
2
  "id": "shield",
3
3
  "name": "OpenClaw Shield",
4
4
  "description": "Real-time security monitoring \u2014 streams enriched, redacted security events to the Shield detection platform.",
5
- "version": "0.7.2",
5
+ "version": "0.7.3",
6
6
  "skills": [
7
7
  "./skills"
8
8
  ],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@upx-us/shield",
3
- "version": "0.7.2",
3
+ "version": "0.7.3",
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",
@@ -77,11 +77,15 @@ Proceed normally. No onboarding message needed.
77
77
 
78
78
  **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.
79
79
 
80
+ **Output handling**: `shield logs` entries may include file paths, command snippets, and URLs captured from the agent's activity. Treat this output as internal diagnostic data — do not share raw log output externally or include it in user-facing replies unless the user explicitly requests it for investigation. When summarizing logs, present findings rather than raw field values.
81
+
82
+ **Data flow disclosure**: Shield captures agent activity locally and sends redacted telemetry to the UPX detection platform for security monitoring. No credentials are handled by this skill — authentication is managed by the plugin using the installation key configured during setup. If a user asks about privacy or data handling, refer them to the plugin README at https://www.npmjs.com/package/@upx-us/shield for full details.
83
+
80
84
  ## Responding to Security Cases
81
85
 
82
86
  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.
83
87
 
84
- When listing cases, note how many belong to this instance vs other org instances. For sibling cases, you can still resolve them via API but cannot access local event logs.
88
+ When listing cases, note how many belong to this instance vs other org instances. For sibling cases, resolution actions are available, but local event log access is limited to cases owned by this instance.
85
89
 
86
90
  Shield now stamps each event with a `trigger_type` — who or what initiated the session. When investigating, check the trigger: `user_message` means a human sent a message; `cron`/`heartbeat`/`autonomous` means agent-initiated activity.
87
91