@drakon-systems/shieldcortex-realtime 4.47.5 → 4.47.6

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 CHANGED
@@ -4,9 +4,9 @@ OpenClaw plugin for ShieldCortex real-time defence scanning and optional memory
4
4
 
5
5
  ## Compatibility
6
6
 
7
- - **Node.js** — ≥ 18 required
7
+ - **Node.js** — ≥ 20 required (the `shieldcortex` peer ships `better-sqlite3` ^12, which needs Node 20+)
8
8
  - **OpenClaw** — ≥ 2026.3.22 required, **≥ 2026.4.23 recommended** — 2026.4.23 added host-package linking for plugins that declare `openclaw` as a peer dependency ([#70462](https://github.com/openclaw/openclaw/pull/70462)), which lets any future `openclaw/plugin-sdk/*` imports resolve without a duplicate runtime bundle
9
- - **ShieldCortex** — ≥ 4.11.1 required
9
+ - **ShieldCortex** — ≥ 4.18.3 required (matches the declared peer dependency; ship both packages at the same version)
10
10
 
11
11
  OpenClaw is declared as an **optional** peer dependency, so installs on older OpenClaw keep working but miss the linking benefit.
12
12
 
@@ -29,9 +29,11 @@ The defensive root `openclaw.plugin.json` is kept for one release on the main pa
29
29
  |------|--------|
30
30
  | `llm_input` | Scans prompts and history through the ShieldCortex defence pipeline. Threats are logged to audit and can forward to ShieldCortex Cloud. |
31
31
  | `llm_output` | Extracts high-signal memories from assistant replies and writes them into ShieldCortex with novelty filtering and dedupe. |
32
- | `before_tool_call` | Runs the Action Guard before tools execute. Catastrophic shell/file/network/git actions are blocked; dangerous actions warn by default or request approval when enforcement is enabled. |
32
+ | `before_tool_call` | Runs the Action Guard before tools execute. Catastrophic shell/file/network/git actions are always blocked. Recognised-dangerous actions are **enforced by default**: attended sessions get an approval prompt, unattended sessions fail closed per `failurePolicy`. Set `actionGuard.enforce: false` to opt down to warn-and-allow, or pre-approve specific operations with `actionGuard.autoApprove`. |
33
+ | `session_end` | Resets the interceptor's per-session caches. |
34
+ | `/shieldcortex-status` | Slash command reporting the plugin's runtime state. |
33
35
 
34
- The plugin is intentionally fire-and-forget: it should not stall the OpenClaw turn loop if ShieldCortex is unavailable.
36
+ The scanning and memory paths are fire-and-forget: they do not stall the OpenClaw turn loop if ShieldCortex is unavailable. The Action Guard is the deliberate exception — it gates tool calls inline, and since 4.47.5 a guard that fails to load falls back to a dependency-free scanner that still denies unambiguous catastrophic operations (fail-closed) rather than allowing everything.
35
37
 
36
38
  ## Installation
37
39
 
@@ -108,6 +110,10 @@ Supported plugin config keys:
108
110
  - `openclawAutoMemoryDedupe`: enable or disable duplicate suppression
109
111
  - `openclawAutoMemoryNoveltyThreshold`: dedupe similarity threshold, `0.6` to `0.99`
110
112
  - `openclawAutoMemoryMaxRecent`: dedupe cache size, `50` to `1000`
113
+ - `actionGuard.enabled`: turn the before-tool-call Action Guard on or off (default `true`)
114
+ - `actionGuard.enforce`: enforce dangerous-operation gating (default `true`); `false` opts down to warn-and-allow. Catastrophic operations are blocked regardless.
115
+ - `actionGuard.autoApprove`: array of operation allowlist entries for unattended agents that legitimately need specific dangerous operations
116
+ - `failurePolicy`: per-severity verdict when a decision can't be obtained unattended (defaults: `low`/`medium` allow, `high`/`critical` deny)
111
117
 
112
118
  ## Auto-memory
113
119
 
package/dist/index.js CHANGED
@@ -798,9 +798,22 @@ export default {
798
798
  const autoMemory = isAutoMemoryEnabled(cfg) ? "on" : "off";
799
799
  const dedupe = isAutoMemoryDedupeEnabled(cfg) ? "on" : "off";
800
800
  const cloud = cfg.cloudApiKey ? "configured" : "not configured";
801
+ // Resolve the Action Guard state the same way initInterceptor() does,
802
+ // so the status line reflects what before_tool_call will actually do.
803
+ const rawInterceptor = cfg.interceptor;
804
+ const guardCfg = {
805
+ ...(DEFAULT_INTERCEPTOR_CONFIG.actionGuard ?? { enabled: true, enforce: true, autoApprove: [] }),
806
+ ...(rawInterceptor && typeof rawInterceptor === 'object' ? rawInterceptor.actionGuard ?? {} : {}),
807
+ };
808
+ const interceptorOn = (rawInterceptor && typeof rawInterceptor === 'object' ? rawInterceptor.enabled : undefined) ?? DEFAULT_INTERCEPTOR_CONFIG.enabled;
809
+ const autoApproved = Array.isArray(guardCfg.autoApprove) ? guardCfg.autoApprove.length : 0;
810
+ const guardState = !interceptorOn || !guardCfg.enabled
811
+ ? "off"
812
+ : `${guardCfg.enforce ? "enforce" : "warn"}${autoApproved > 0 ? ` (${autoApproved} auto-approved)` : ""}${interceptorReady ? "" : " — not yet initialised this session"}`;
801
813
  return {
802
814
  text: `ShieldCortex v${_version}\n` +
803
- ` Hooks: llm_input (scan), llm_output (memory)\n` +
815
+ ` Hooks: llm_input (scan), llm_output (memory), before_tool_call (action guard), session_end (cache reset)\n` +
816
+ ` Action guard: ${guardState}\n` +
804
817
  ` Auto memory: ${autoMemory} | Dedupe: ${dedupe}\n` +
805
818
  ` Cloud sync: ${cloud}`,
806
819
  };
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "id": "shieldcortex-realtime",
3
- "version": "4.47.5",
3
+ "version": "4.47.6",
4
4
  "name": "ShieldCortex Real-time Scanner",
5
5
  "description": "Real-time defence scanning on LLM input, memory extraction on LLM output, and active tool call interception with approval gating.",
6
6
  "kind": null,
@@ -77,6 +77,22 @@
77
77
  "label": "Critical Severity Action",
78
78
  "description": "Action for critical-severity threats (log, warn, require_approval)",
79
79
  "type": "string"
80
+ },
81
+ "interceptor.actionGuard.enabled": {
82
+ "label": "Action Guard",
83
+ "description": "Gate dangerous shell/file/network/git tool calls before they execute. Catastrophic operations are always blocked while enabled.",
84
+ "type": "boolean"
85
+ },
86
+ "interceptor.actionGuard.enforce": {
87
+ "label": "Enforce Action Guard",
88
+ "description": "Enforce dangerous-operation gating (attended: approval prompt; unattended: failurePolicy). Off = warn-and-allow (advisory). Catastrophic operations block regardless.",
89
+ "type": "boolean"
90
+ },
91
+ "interceptor.actionGuard.autoApprove": {
92
+ "label": "Action Guard Auto-approve List",
93
+ "description": "Family/action/signal names pre-approved for unattended agents that legitimately need specific dangerous operations (case-insensitive substring match). Never applies to catastrophic operations.",
94
+ "type": "array",
95
+ "advanced": true
80
96
  }
81
97
  },
82
98
  "configSchema": {
@@ -197,6 +213,27 @@
197
213
  "default": "deny"
198
214
  }
199
215
  }
216
+ },
217
+ "actionGuard": {
218
+ "type": "object",
219
+ "additionalProperties": false,
220
+ "properties": {
221
+ "enabled": {
222
+ "type": "boolean",
223
+ "default": true
224
+ },
225
+ "enforce": {
226
+ "type": "boolean",
227
+ "default": true
228
+ },
229
+ "autoApprove": {
230
+ "type": "array",
231
+ "items": {
232
+ "type": "string"
233
+ },
234
+ "default": []
235
+ }
236
+ }
200
237
  }
201
238
  }
202
239
  }
package/index.ts CHANGED
@@ -946,10 +946,23 @@ export default {
946
946
  const autoMemory = isAutoMemoryEnabled(cfg) ? "on" : "off";
947
947
  const dedupe = isAutoMemoryDedupeEnabled(cfg) ? "on" : "off";
948
948
  const cloud = cfg.cloudApiKey ? "configured" : "not configured";
949
+ // Resolve the Action Guard state the same way initInterceptor() does,
950
+ // so the status line reflects what before_tool_call will actually do.
951
+ const rawInterceptor = (cfg as any).interceptor;
952
+ const guardCfg = {
953
+ ...(DEFAULT_INTERCEPTOR_CONFIG.actionGuard ?? { enabled: true, enforce: true, autoApprove: [] }),
954
+ ...(rawInterceptor && typeof rawInterceptor === 'object' ? rawInterceptor.actionGuard ?? {} : {}),
955
+ };
956
+ const interceptorOn = (rawInterceptor && typeof rawInterceptor === 'object' ? rawInterceptor.enabled : undefined) ?? DEFAULT_INTERCEPTOR_CONFIG.enabled;
957
+ const autoApproved = Array.isArray(guardCfg.autoApprove) ? guardCfg.autoApprove.length : 0;
958
+ const guardState = !interceptorOn || !guardCfg.enabled
959
+ ? "off"
960
+ : `${guardCfg.enforce ? "enforce" : "warn"}${autoApproved > 0 ? ` (${autoApproved} auto-approved)` : ""}${interceptorReady ? "" : " — not yet initialised this session"}`;
949
961
  return {
950
962
  text:
951
963
  `ShieldCortex v${_version}\n` +
952
- ` Hooks: llm_input (scan), llm_output (memory)\n` +
964
+ ` Hooks: llm_input (scan), llm_output (memory), before_tool_call (action guard), session_end (cache reset)\n` +
965
+ ` Action guard: ${guardState}\n` +
953
966
  ` Auto memory: ${autoMemory} | Dedupe: ${dedupe}\n` +
954
967
  ` Cloud sync: ${cloud}`,
955
968
  };
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "id": "shieldcortex-realtime",
3
- "version": "4.47.5",
3
+ "version": "4.47.6",
4
4
  "name": "ShieldCortex Real-time Scanner",
5
5
  "description": "Real-time defence scanning on LLM input, memory extraction on LLM output, and active tool call interception with approval gating.",
6
6
  "kind": null,
@@ -77,6 +77,22 @@
77
77
  "label": "Critical Severity Action",
78
78
  "description": "Action for critical-severity threats (log, warn, require_approval)",
79
79
  "type": "string"
80
+ },
81
+ "interceptor.actionGuard.enabled": {
82
+ "label": "Action Guard",
83
+ "description": "Gate dangerous shell/file/network/git tool calls before they execute. Catastrophic operations are always blocked while enabled.",
84
+ "type": "boolean"
85
+ },
86
+ "interceptor.actionGuard.enforce": {
87
+ "label": "Enforce Action Guard",
88
+ "description": "Enforce dangerous-operation gating (attended: approval prompt; unattended: failurePolicy). Off = warn-and-allow (advisory). Catastrophic operations block regardless.",
89
+ "type": "boolean"
90
+ },
91
+ "interceptor.actionGuard.autoApprove": {
92
+ "label": "Action Guard Auto-approve List",
93
+ "description": "Family/action/signal names pre-approved for unattended agents that legitimately need specific dangerous operations (case-insensitive substring match). Never applies to catastrophic operations.",
94
+ "type": "array",
95
+ "advanced": true
80
96
  }
81
97
  },
82
98
  "configSchema": {
@@ -197,6 +213,27 @@
197
213
  "default": "deny"
198
214
  }
199
215
  }
216
+ },
217
+ "actionGuard": {
218
+ "type": "object",
219
+ "additionalProperties": false,
220
+ "properties": {
221
+ "enabled": {
222
+ "type": "boolean",
223
+ "default": true
224
+ },
225
+ "enforce": {
226
+ "type": "boolean",
227
+ "default": true
228
+ },
229
+ "autoApprove": {
230
+ "type": "array",
231
+ "items": {
232
+ "type": "string"
233
+ },
234
+ "default": []
235
+ }
236
+ }
200
237
  }
201
238
  }
202
239
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@drakon-systems/shieldcortex-realtime",
3
- "version": "4.47.5",
3
+ "version": "4.47.6",
4
4
  "description": "OpenClaw plugin for ShieldCortex real-time defence scanning and optional memory extraction.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -36,7 +36,7 @@
36
36
  }
37
37
  },
38
38
  "engines": {
39
- "node": ">=18.0.0",
39
+ "node": ">=20.0.0",
40
40
  "openclaw": ">=2026.4.23"
41
41
  },
42
42
  "publishConfig": {