@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 +9 -0
- package/dist/index.js +1 -1
- package/dist/src/config.d.ts +1 -0
- package/dist/src/config.js +23 -1
- package/dist/src/transformer.js +13 -15
- package/openclaw.plugin.json +1 -1
- package/package.json +1 -1
- package/skills/shield/SKILL.md +5 -1
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;
|
package/dist/src/config.d.ts
CHANGED
|
@@ -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;
|
package/dist/src/config.js
CHANGED
|
@@ -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
|
-
|
|
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;
|
package/dist/src/transformer.js
CHANGED
|
@@ -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 =
|
|
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
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
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
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
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);
|
package/openclaw.plugin.json
CHANGED
package/package.json
CHANGED
package/skills/shield/SKILL.md
CHANGED
|
@@ -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,
|
|
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
|
|