@drakon-systems/shieldcortex-realtime 4.54.12 → 4.54.14
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/dist/interceptor.js +12 -4
- package/dist/openclaw.plugin.json +1 -1
- package/interceptor.ts +12 -4
- package/openclaw.plugin.json +1 -1
- package/package.json +2 -2
package/dist/interceptor.js
CHANGED
|
@@ -897,7 +897,14 @@ export function createInterceptor(config, pipeline, options) {
|
|
|
897
897
|
const base = { ...guardAuditBase(context.toolName, v, preview), ...(escalation ? { escalated: escalation } : {}) };
|
|
898
898
|
const severity = v.severity === 'catastrophic' ? 'critical' : 'high';
|
|
899
899
|
// Catastrophic / exfil — hard block, always enforced when the guard is enabled.
|
|
900
|
-
|
|
900
|
+
// #436: the door-less throw is for that tier only. A sub-catastrophic `block`
|
|
901
|
+
// (schema rejection) falls through to requireApproval so the operator can
|
|
902
|
+
// still say yes. autoApprove and enforce:false must not widen an unscanned
|
|
903
|
+
// call — they skip below.
|
|
904
|
+
const terminalBlock = v.decision === 'block'
|
|
905
|
+
&& (v.severity === 'catastrophic' || v.severity === 'critical');
|
|
906
|
+
const unscannedBlock = v.decision === 'block' && !terminalBlock;
|
|
907
|
+
if (terminalBlock) {
|
|
901
908
|
// #227: release any lease this call minted early — a blocked action must
|
|
902
909
|
// not leave a hold on that scope (self-heals at TTL if release fails).
|
|
903
910
|
if (leaseGate?.acquired) {
|
|
@@ -919,7 +926,7 @@ export function createInterceptor(config, pipeline, options) {
|
|
|
919
926
|
// legitimate dangerous work. It NEVER applies to catastrophic ops — those
|
|
920
927
|
// hard-block above, before this branch is reached.
|
|
921
928
|
const autoApprove = actionGuardCfg.autoApprove ?? [];
|
|
922
|
-
if (autoApprove.length > 0) {
|
|
929
|
+
if (autoApprove.length > 0 && !unscannedBlock) {
|
|
923
930
|
const hay = [v.family, v.action, ...v.signals].map(s => String(s).toLowerCase());
|
|
924
931
|
const matched = autoApprove.some(a => {
|
|
925
932
|
const n = a.toLowerCase();
|
|
@@ -932,7 +939,8 @@ export function createInterceptor(config, pipeline, options) {
|
|
|
932
939
|
}
|
|
933
940
|
// require_approval — ENFORCED by default (P1/WS1). `enforce:false` opts back
|
|
934
941
|
// down to warn-and-allow (advisory) for operators who want the old behaviour.
|
|
935
|
-
|
|
942
|
+
// #436: an unscanned schema rejection must not become an advisory allow.
|
|
943
|
+
if (!actionGuardCfg.enforce && !unscannedBlock) {
|
|
936
944
|
log.warn(`[shieldcortex] ⚠️ Action Guard: ${context.toolName} — ${v.reason}`);
|
|
937
945
|
emitAudit({ ...base, action: 'warn', outcome: 'warned' });
|
|
938
946
|
return;
|
|
@@ -953,7 +961,7 @@ export function createInterceptor(config, pipeline, options) {
|
|
|
953
961
|
log.warn(`[shieldcortex] approval broker HARDENED ${context.toolName} to a denial: ${brokered.reason}`);
|
|
954
962
|
throw new Error(`ShieldCortex: tool call blocked — ${brokered.reason}`);
|
|
955
963
|
}
|
|
956
|
-
if (brokered?.outcome === 'pre_clear') {
|
|
964
|
+
if (brokered?.outcome === 'pre_clear' && !unscannedBlock) {
|
|
957
965
|
// Reversible, on-host, in-context, judge-confident: proceed without
|
|
958
966
|
// waiting. Loud on purpose — a release nobody approved must never be a
|
|
959
967
|
// silent one, because the audit row is the only thing that will ever tell
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"id": "shieldcortex-realtime",
|
|
3
|
-
"version": "4.54.
|
|
3
|
+
"version": "4.54.14",
|
|
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,
|
package/interceptor.ts
CHANGED
|
@@ -1322,7 +1322,14 @@ export function createInterceptor(
|
|
|
1322
1322
|
const severity: Severity = v.severity === 'catastrophic' ? 'critical' : 'high';
|
|
1323
1323
|
|
|
1324
1324
|
// Catastrophic / exfil — hard block, always enforced when the guard is enabled.
|
|
1325
|
-
|
|
1325
|
+
// #436: the door-less throw is for that tier only. A sub-catastrophic `block`
|
|
1326
|
+
// (schema rejection) falls through to requireApproval so the operator can
|
|
1327
|
+
// still say yes. autoApprove and enforce:false must not widen an unscanned
|
|
1328
|
+
// call — they skip below.
|
|
1329
|
+
const terminalBlock = v.decision === 'block'
|
|
1330
|
+
&& (v.severity === 'catastrophic' || v.severity === 'critical');
|
|
1331
|
+
const unscannedBlock = v.decision === 'block' && !terminalBlock;
|
|
1332
|
+
if (terminalBlock) {
|
|
1326
1333
|
// #227: release any lease this call minted early — a blocked action must
|
|
1327
1334
|
// not leave a hold on that scope (self-heals at TTL if release fails).
|
|
1328
1335
|
if (leaseGate?.acquired) {
|
|
@@ -1342,7 +1349,7 @@ export function createInterceptor(
|
|
|
1342
1349
|
// legitimate dangerous work. It NEVER applies to catastrophic ops — those
|
|
1343
1350
|
// hard-block above, before this branch is reached.
|
|
1344
1351
|
const autoApprove = actionGuardCfg.autoApprove ?? [];
|
|
1345
|
-
if (autoApprove.length > 0) {
|
|
1352
|
+
if (autoApprove.length > 0 && !unscannedBlock) {
|
|
1346
1353
|
const hay = [v.family, v.action, ...v.signals].map(s => String(s).toLowerCase());
|
|
1347
1354
|
const matched = autoApprove.some(a => {
|
|
1348
1355
|
const n = a.toLowerCase();
|
|
@@ -1356,7 +1363,8 @@ export function createInterceptor(
|
|
|
1356
1363
|
|
|
1357
1364
|
// require_approval — ENFORCED by default (P1/WS1). `enforce:false` opts back
|
|
1358
1365
|
// down to warn-and-allow (advisory) for operators who want the old behaviour.
|
|
1359
|
-
|
|
1366
|
+
// #436: an unscanned schema rejection must not become an advisory allow.
|
|
1367
|
+
if (!actionGuardCfg.enforce && !unscannedBlock) {
|
|
1360
1368
|
log.warn(`[shieldcortex] ⚠️ Action Guard: ${context.toolName} — ${v.reason}`);
|
|
1361
1369
|
emitAudit({ ...base, action: 'warn', outcome: 'warned' });
|
|
1362
1370
|
return;
|
|
@@ -1380,7 +1388,7 @@ export function createInterceptor(
|
|
|
1380
1388
|
throw new Error(`ShieldCortex: tool call blocked — ${brokered.reason}`);
|
|
1381
1389
|
}
|
|
1382
1390
|
|
|
1383
|
-
if (brokered?.outcome === 'pre_clear') {
|
|
1391
|
+
if (brokered?.outcome === 'pre_clear' && !unscannedBlock) {
|
|
1384
1392
|
// Reversible, on-host, in-context, judge-confident: proceed without
|
|
1385
1393
|
// waiting. Loud on purpose — a release nobody approved must never be a
|
|
1386
1394
|
// silent one, because the audit row is the only thing that will ever tell
|
package/openclaw.plugin.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"id": "shieldcortex-realtime",
|
|
3
|
-
"version": "4.54.
|
|
3
|
+
"version": "4.54.14",
|
|
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,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@drakon-systems/shieldcortex-realtime",
|
|
3
|
-
"version": "4.54.
|
|
3
|
+
"version": "4.54.14",
|
|
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",
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
],
|
|
25
25
|
"scripts": {
|
|
26
26
|
"pack:verify": "npm pack --dry-run",
|
|
27
|
-
"prepublishOnly": "node -e \"if(!require('fs').existsSync('dist/index.js'))throw new Error('plugin dist/index.js missing
|
|
27
|
+
"prepublishOnly": "node -e \"if(!require('fs').existsSync('dist/index.js'))throw new Error('plugin dist/index.js missing \u2014 run `npm run build:ts` from the repo root before publishing')\""
|
|
28
28
|
},
|
|
29
29
|
"peerDependencies": {
|
|
30
30
|
"shieldcortex": "^4.54.8",
|