@guava-parity/guard-scanner 13.0.0 → 16.0.0

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.
Files changed (96) hide show
  1. package/README.md +170 -215
  2. package/README_ja.md +252 -0
  3. package/SECURITY.md +12 -4
  4. package/SKILL.md +148 -57
  5. package/dist/cli.cjs +5997 -0
  6. package/dist/cli.d.mts +1 -0
  7. package/dist/cli.d.ts +1 -0
  8. package/dist/cli.mjs +6003 -0
  9. package/dist/index.cjs +4825 -0
  10. package/dist/index.d.mts +17 -0
  11. package/dist/index.d.ts +17 -0
  12. package/dist/index.mjs +4798 -0
  13. package/dist/mcp-server.cjs +4756 -0
  14. package/dist/mcp-server.d.mts +1 -0
  15. package/dist/mcp-server.d.ts +1 -0
  16. package/dist/mcp-server.mjs +4767 -0
  17. package/dist/openclaw-plugin.cjs +4863 -0
  18. package/dist/openclaw-plugin.d.mts +11 -0
  19. package/dist/openclaw-plugin.d.ts +11 -0
  20. package/dist/openclaw-plugin.mjs +4854 -0
  21. package/dist/types.cjs +18 -0
  22. package/dist/types.d.mts +215 -0
  23. package/dist/types.d.ts +215 -0
  24. package/dist/types.mjs +1 -0
  25. package/docs/EVIDENCE_DRIVEN.md +182 -0
  26. package/docs/banner.png +0 -0
  27. package/docs/data/benchmark-ledger.json +1428 -0
  28. package/docs/data/corpus-metrics.json +11 -0
  29. package/docs/data/fp-ledger.json +18 -0
  30. package/docs/data/latest.json +25837 -2481
  31. package/docs/data/quality-contract.json +36 -0
  32. package/docs/generated/npm-audit-20260312.json +96 -0
  33. package/docs/generated/openclaw-upstream-status.json +25 -0
  34. package/docs/glossary.md +46 -0
  35. package/docs/index.html +1085 -496
  36. package/docs/logo.png +0 -0
  37. package/docs/openclaw-compatibility-audit.md +45 -0
  38. package/docs/openclaw-continuous-compatibility-plan.md +37 -0
  39. package/docs/rules/a2a-contagion.md +68 -0
  40. package/docs/rules/advanced-exfil.md +52 -0
  41. package/docs/rules/agent-protocol.md +108 -0
  42. package/docs/rules/api-abuse.md +68 -0
  43. package/docs/rules/autonomous-risk.md +92 -0
  44. package/docs/rules/config-impact.md +132 -0
  45. package/docs/rules/credential-handling.md +100 -0
  46. package/docs/rules/cve-patterns.md +332 -0
  47. package/docs/rules/data-exposure.md +84 -0
  48. package/docs/rules/exfiltration.md +36 -0
  49. package/docs/rules/financial-access.md +84 -0
  50. package/docs/rules/identity-hijack.md +140 -0
  51. package/docs/rules/inference-manipulation.md +60 -0
  52. package/docs/rules/leaky-skills.md +52 -0
  53. package/docs/rules/malicious-code.md +108 -0
  54. package/docs/rules/mcp-security.md +148 -0
  55. package/docs/rules/memory-poisoning.md +84 -0
  56. package/docs/rules/model-poisoning.md +44 -0
  57. package/docs/rules/obfuscation.md +60 -0
  58. package/docs/rules/persistence.md +108 -0
  59. package/docs/rules/pii-exposure.md +116 -0
  60. package/docs/rules/prompt-injection.md +148 -0
  61. package/docs/rules/prompt-worm.md +44 -0
  62. package/docs/rules/safeguard-bypass.md +44 -0
  63. package/docs/rules/sandbox-escape.md +100 -0
  64. package/docs/rules/secret-detection.md +44 -0
  65. package/docs/rules/supply-chain-v2.md +92 -0
  66. package/docs/rules/suspicious-download.md +60 -0
  67. package/docs/rules/trust-boundary.md +76 -0
  68. package/docs/rules/trust-exploitation.md +92 -0
  69. package/docs/rules/unverifiable-deps.md +84 -0
  70. package/docs/rules/vdb-injection.md +84 -0
  71. package/docs/security-vulnerability-report-20260312.md +53 -0
  72. package/docs/spec/PRD_V2_ARCHITECTURE.md +55 -0
  73. package/docs/spec/capabilities.json +174 -0
  74. package/docs/spec/finding.schema.json +104 -0
  75. package/docs/spec/integration-manifest.md +39 -0
  76. package/docs/spec/plugin-trust.json +11 -0
  77. package/docs/spec/sbom.json +33 -0
  78. package/docs/threat-model.md +65 -0
  79. package/docs/v13-architecture-manifest.md +55 -0
  80. package/hooks/context.ts +306 -0
  81. package/hooks/guard-scanner/plugin.ts +24 -1
  82. package/openclaw-plugin.mts +107 -0
  83. package/openclaw.plugin.json +30 -53
  84. package/package.json +66 -13
  85. package/src/asset-auditor.js +0 -508
  86. package/src/ci-reporter.js +0 -135
  87. package/src/cli.js +0 -294
  88. package/src/html-template.js +0 -239
  89. package/src/ioc-db.js +0 -54
  90. package/src/mcp-server.js +0 -702
  91. package/src/patterns.js +0 -611
  92. package/src/quarantine.js +0 -41
  93. package/src/runtime-guard.js +0 -346
  94. package/src/scanner.js +0 -1157
  95. package/src/vt-client.js +0 -202
  96. package/src/watcher.js +0 -170
@@ -0,0 +1,306 @@
1
+ // @ts-nocheck
2
+ /**
3
+ * guard-scanner Context Engine Hooks — OpenClaw Lifecycle Integration
4
+ *
5
+ * 3 lifecycle hooks for the Guard Scanner plugin:
6
+ * 1. bootstrap — Initialize guard state, inject status summary
7
+ * 2. afterTurn — Clear temporal context, flush audit log
8
+ * 3. prepareSubagentSpawn — Guard-scan subagent payloads
9
+ *
10
+ * Design:
11
+ * - Duck-typed interfaces (no OpenClaw dependency)
12
+ * - Pure regex pattern matching for Moltbook/A2A detection (no external process)
13
+ * - Context-Crush 185KB hard limit on all injections
14
+ * - All hooks are non-blocking on failure (agent must never stall)
15
+ *
16
+ * @author Guava 🍈 & Dee
17
+ * @version 15.0.0
18
+ * @license MIT
19
+ */
20
+
21
+ import { appendFileSync, mkdirSync } from "node:fs";
22
+ import { join } from "node:path";
23
+ import { homedir } from "node:os";
24
+
25
+ // ── Constants ──
26
+
27
+ const CONTEXT_CRUSH_LIMIT = 189440; // 185KB
28
+ const BOOTSTRAP_CONTEXT_LIMIT = 2048; // 2KB max for bootstrap injection
29
+ const AUDIT_DIR = join(homedir(), ".openclaw", "guard-scanner");
30
+ const AUDIT_FILE = join(AUDIT_DIR, "audit.jsonl");
31
+
32
+ // ── Types (duck-typed — from OpenClaw src/plugins/types.ts) ──
33
+
34
+ /**
35
+ * @typedef {Object} HookContext
36
+ * @property {Record<string, unknown>} [config]
37
+ * @property {string} [workspaceDir]
38
+ * @property {string} [agentId]
39
+ * @property {string} [sessionKey]
40
+ */
41
+
42
+ /**
43
+ * @typedef {Object} BootstrapEvent
44
+ * @property {string} [workspace]
45
+ * @property {string} [sessionId]
46
+ */
47
+
48
+ /**
49
+ * @typedef {Object} BootstrapResult
50
+ * @property {string} [systemPromptSuffix]
51
+ * @property {string} [extraContext]
52
+ */
53
+
54
+ /**
55
+ * @typedef {Object} AfterTurnEvent
56
+ * @property {number} [turnNumber]
57
+ * @property {number} [messageCount]
58
+ */
59
+
60
+ /**
61
+ * @typedef {Object} SubagentSpawnEvent
62
+ * @property {string} [subagentId]
63
+ * @property {string} [task]
64
+ * @property {string[]} [tools]
65
+ * @property {Record<string, unknown>} [params]
66
+ */
67
+
68
+ /**
69
+ * @typedef {Object} SubagentSpawnResult
70
+ * @property {boolean} [block]
71
+ * @property {string} [blockReason]
72
+ * @property {Record<string, unknown>} [params]
73
+ */
74
+
75
+ // ── Internal: Audit logging ──
76
+
77
+ function ensureAuditDir() {
78
+ try {
79
+ mkdirSync(AUDIT_DIR, { recursive: true });
80
+ } catch {
81
+ /* ignore — non-critical */
82
+ }
83
+ }
84
+
85
+ function logAudit(entry) {
86
+ ensureAuditDir();
87
+ try {
88
+ const line = JSON.stringify({ ...entry, ts: new Date().toISOString() }) + "\n";
89
+ appendFileSync(AUDIT_FILE, line);
90
+ } catch {
91
+ /* ignore — audit failure must never block agent */
92
+ }
93
+ }
94
+
95
+ // ── Internal: Config resolution ──
96
+
97
+ function resolveMode(ctx) {
98
+ const mode = ctx?.config?.mode;
99
+ if (mode === "monitor" || mode === "enforce" || mode === "strict") return mode;
100
+ return "enforce";
101
+ }
102
+
103
+ function shouldBlock(mode, severity) {
104
+ if (!severity || mode === "monitor") return false;
105
+ if (mode === "strict") return severity === "CRITICAL" || severity === "HIGH";
106
+ return severity === "CRITICAL";
107
+ }
108
+
109
+
110
+ // ── Runtime threat patterns (subset for subagent validation) ──
111
+
112
+ const SUBAGENT_CHECKS = [
113
+ {
114
+ id: "SA_PROMPT_INJECT", severity: "CRITICAL",
115
+ desc: "Prompt injection in subagent task",
116
+ test: (s) => /(ignore\s+(previous|all|above)\s+(instructions|rules)|you\s+are\s+now\s+[a-z]+|system\s*:\s*override)/i.test(s),
117
+ },
118
+ {
119
+ id: "SA_CRED_EXFIL", severity: "CRITICAL",
120
+ desc: "Credential exfiltration in subagent payload",
121
+ test: (s) =>
122
+ /(webhook\.site|requestbin\.com|hookbin\.com|pipedream\.net|ngrok\.io|socifiapp\.com)/i.test(s) &&
123
+ /(token|key|secret|password|credential|env)/i.test(s),
124
+ },
125
+ {
126
+ id: "SA_TRUST_BYPASS", severity: "CRITICAL",
127
+ desc: "A2A trust bypass — partnership exploitation to override safety",
128
+ test: (s) =>
129
+ /(as\s+your\s+(partner|equal)|trust\s+means|between\s+us|don'?t\s+tell\s+(the\s+)?human)/i.test(s) &&
130
+ /(ignore|bypass|skip|override|disable)\s+(guard|safety|rule|check)/i.test(s),
131
+ },
132
+ {
133
+ id: "SA_REVSHELL", severity: "CRITICAL",
134
+ desc: "Reverse shell in subagent parameters",
135
+ test: (s) => /\/dev\/tcp\/|nc\s+-e|ncat\s+-e|bash\s+-i\s+>&|socat\s+TCP/i.test(s),
136
+ },
137
+ {
138
+ id: "SA_CURL_BASH", severity: "CRITICAL",
139
+ desc: "Download piped to shell in subagent",
140
+ test: (s) => /(curl|wget)\s+[^\n]*\|\s*(sh|bash|zsh)/i.test(s),
141
+ },
142
+ {
143
+ id: "SA_SSH_READ", severity: "HIGH",
144
+ desc: "SSH key access in subagent",
145
+ test: (s) => /\.ssh\/id_|\.ssh\/authorized_keys/i.test(s),
146
+ },
147
+ {
148
+ id: "SA_SOUL_TAMPER", severity: "CRITICAL",
149
+ desc: "SOUL.md modification in subagent",
150
+ test: (s) => /SOUL\.md/i.test(s) && /(write|edit|replace|rm|delete|>)/i.test(s),
151
+ },
152
+ {
153
+ id: "SA_MOLTBOOK", severity: "CRITICAL",
154
+ desc: "Moltbook/AMOS indicator in subagent",
155
+ test: (s) => /socifiapp|Atomic\s*Stealer|AMOS/i.test(s),
156
+ },
157
+ {
158
+ id: "SA_CLOUD_META", severity: "CRITICAL",
159
+ desc: "Cloud metadata access in subagent",
160
+ test: (s) => /169\.254\.169\.254|metadata\.google|metadata\.aws/i.test(s),
161
+ },
162
+ ];
163
+
164
+ // ── Exported Hooks ──
165
+
166
+ /**
167
+ * HOOK: bootstrap (priority: 10)
168
+ *
169
+ * Initialize guard-scanner context engine state on agent boot.
170
+ * Injects a compact status summary into systemPromptSuffix.
171
+ * Hard-capped at 2KB to prevent context bloat.
172
+ *
173
+ * @param {BootstrapEvent} event
174
+ * @param {HookContext} ctx
175
+ * @returns {Promise<BootstrapResult | undefined>}
176
+ */
177
+ export async function bootstrap(event, ctx) {
178
+ try {
179
+ const mode = resolveMode(ctx);
180
+ const patternCount = SUBAGENT_CHECKS.length;
181
+
182
+ const status = [
183
+ `🛡️ guard-scanner v15.0.0 active (mode: ${mode})`,
184
+ `Patterns: ${patternCount} subagent + 22 runtime checks`,
185
+ `Context-Crush limit: ${Math.round(CONTEXT_CRUSH_LIMIT / 1024)}KB`,
186
+ `Audit: ${AUDIT_FILE}`,
187
+ ].join(" | ");
188
+
189
+ // Hard cap at 2KB
190
+ const clipped = status.length > BOOTSTRAP_CONTEXT_LIMIT
191
+ ? status.slice(0, BOOTSTRAP_CONTEXT_LIMIT - 3) + "..."
192
+ : status;
193
+
194
+ logAudit({
195
+ hook: "bootstrap",
196
+ mode,
197
+ sessionId: event?.sessionId ?? "unknown",
198
+ status: "initialized",
199
+ });
200
+
201
+ return {
202
+ systemPromptSuffix: clipped,
203
+ };
204
+ } catch {
205
+ // Bootstrap failure must never block agent startup
206
+ return undefined;
207
+ }
208
+ }
209
+
210
+ /**
211
+ * HOOK: afterTurn (priority: 100)
212
+ *
213
+ * Post-turn cleanup:
214
+ * - Flush accumulated audit entries
215
+ * - Clear any temporal guard state
216
+ * - Log turn completion for forensics
217
+ *
218
+ * Fire-and-forget — never blocks, never throws.
219
+ *
220
+ * @param {AfterTurnEvent} event
221
+ * @param {HookContext} ctx
222
+ * @returns {Promise<void>}
223
+ */
224
+ export async function afterTurn(event, ctx) {
225
+ try {
226
+ logAudit({
227
+ hook: "afterTurn",
228
+ turnNumber: event?.turnNumber ?? 0,
229
+ messageCount: event?.messageCount ?? 0,
230
+ agent: ctx?.agentId ?? "unknown",
231
+ session: ctx?.sessionKey ?? "unknown",
232
+ status: "turn_complete",
233
+ });
234
+ } catch {
235
+ // afterTurn failure must never affect agent
236
+ }
237
+ }
238
+
239
+ /**
240
+ * HOOK: prepareSubagentSpawn (priority: 100)
241
+ *
242
+ * Critical security gate before subagent creation.
243
+ * Validates the entire spawn payload against:
244
+ * 1. Context-Crush limit (185KB)
245
+ * 2. 9 subagent-specific threat patterns (Moltbook, A2A hijack, etc.)
246
+ *
247
+ * Returns { block: true, blockReason } on threat detection.
248
+ *
249
+ * @param {SubagentSpawnEvent} event
250
+ * @param {HookContext} ctx
251
+ * @returns {Promise<SubagentSpawnResult | undefined>}
252
+ */
253
+ export async function prepareSubagentSpawn(event, ctx) {
254
+ try {
255
+ const mode = resolveMode(ctx);
256
+ const serialized = JSON.stringify(event ?? {});
257
+
258
+ // ── Context-Crush Check ──
259
+ const payloadBytes = Buffer.byteLength(serialized, "utf8");
260
+ if (payloadBytes > CONTEXT_CRUSH_LIMIT) {
261
+ const reason = `🛡️ guard-scanner: Context-Crush — subagent payload ${payloadBytes} bytes exceeds ${Math.round(CONTEXT_CRUSH_LIMIT / 1024)}KB limit`;
262
+ logAudit({
263
+ hook: "prepareSubagentSpawn",
264
+ check: "CONTEXT_CRUSH",
265
+ severity: "CRITICAL",
266
+ subagentId: event?.subagentId ?? "unknown",
267
+ payloadBytes,
268
+ action: "blocked",
269
+ });
270
+ return { block: true, blockReason: reason };
271
+ }
272
+
273
+ // ── Subagent Threat Pattern Scan ──
274
+ for (const check of SUBAGENT_CHECKS) {
275
+ if (!check.test(serialized)) continue;
276
+
277
+ const auditEntry = {
278
+ hook: "prepareSubagentSpawn",
279
+ check: check.id,
280
+ severity: check.severity,
281
+ desc: check.desc,
282
+ subagentId: event?.subagentId ?? "unknown",
283
+ mode,
284
+ action: "warned",
285
+ };
286
+
287
+ if (shouldBlock(mode, check.severity)) {
288
+ auditEntry.action = "blocked";
289
+ logAudit(auditEntry);
290
+ return {
291
+ block: true,
292
+ blockReason: `🛡️ guard-scanner: ${check.desc} [${check.id}] in subagent ${event?.subagentId ?? "unknown"}`,
293
+ };
294
+ }
295
+
296
+ // Below threshold — warn only
297
+ logAudit(auditEntry);
298
+ }
299
+
300
+ // Clean payload — allow spawn
301
+ return undefined;
302
+ } catch {
303
+ // Guard failure must never block subagent spawn
304
+ return undefined;
305
+ }
306
+ }
@@ -62,7 +62,7 @@ type PluginAPI = {
62
62
  interface RuntimeCheck {
63
63
  id: string;
64
64
  severity: "CRITICAL" | "HIGH" | "MEDIUM";
65
- layer: 1 | 2 | 3;
65
+ layer: 1 | 2 | 3 | 4 | 5;
66
66
  desc: string;
67
67
  test: (s: string) => boolean;
68
68
  }
@@ -267,6 +267,29 @@ export default function (api: PluginAPI) {
267
267
  if (!DANGEROUS_TOOLS.has(toolName)) return;
268
268
 
269
269
  const serialized = JSON.stringify(params);
270
+
271
+ // --- v15.0.0 Sanctuary Enforcer: Context-Crush Limit ---
272
+ // 185KB = 185 * 1024 bytes = 189440 bytes
273
+ const MAX_PAYLOAD_SIZE = 189440;
274
+ if (Buffer.byteLength(serialized, 'utf8') > MAX_PAYLOAD_SIZE) {
275
+ const auditEntry = {
276
+ tool: toolName,
277
+ check: "CONTEXT_CRUSH_LIMIT",
278
+ severity: "CRITICAL",
279
+ desc: "Context-Crush: Payload exceeds 185KB Sanctuary limit",
280
+ mode,
281
+ action: "blocked",
282
+ session: ctx.sessionKey || "unknown",
283
+ agent: ctx.agentId || "unknown",
284
+ };
285
+ logAudit(auditEntry);
286
+ api.logger.error(`🛡️ BLOCKED ${toolName}: Context-Crush payload size exceeded (${Buffer.byteLength(serialized, 'utf8')} bytes)`);
287
+ return {
288
+ block: true,
289
+ blockReason: "🛡️ guard-scanner v15: Payload exceeds 185KB Context-Crush limit.",
290
+ };
291
+ }
292
+ // --------------------------------------------------------
270
293
 
271
294
  for (const check of RUNTIME_CHECKS) {
272
295
  if (!check.test(serialized)) continue;
@@ -0,0 +1,107 @@
1
+ import type { OpenClawPluginApi } from "openclaw/plugin-sdk/core";
2
+ import * as runtimeGuard from "./src/index.js";
3
+
4
+ const runtimeGuardApi = runtimeGuard as {
5
+ scanToolCall: (
6
+ toolName: string,
7
+ params: Record<string, unknown>,
8
+ options?: {
9
+ mode?: "monitor" | "enforce" | "strict";
10
+ auditLog?: boolean;
11
+ sessionKey?: string;
12
+ sessionId?: string;
13
+ runId?: string;
14
+ toolCallId?: string;
15
+ agentId?: string;
16
+ policy?: {
17
+ id?: string;
18
+ allowed_tools?: string[];
19
+ blocked_tools?: string[];
20
+ max_network_scope?: "none" | "internal-only" | "external-ok";
21
+ secret_bearing_context?: boolean;
22
+ memory_write_permission?: boolean;
23
+ };
24
+ },
25
+ ) => {
26
+ blocked: boolean;
27
+ blockReason: string | null;
28
+ };
29
+ };
30
+
31
+ type GuardMode = "monitor" | "enforce" | "strict";
32
+ type PluginHookBeforeToolCallEvent = {
33
+ toolName: string;
34
+ params: Record<string, unknown>;
35
+ runId?: string;
36
+ toolCallId?: string;
37
+ };
38
+ type PluginHookToolContext = {
39
+ agentId?: string;
40
+ sessionKey?: string;
41
+ sessionId?: string;
42
+ runId?: string;
43
+ toolName: string;
44
+ toolCallId?: string;
45
+ policy?: {
46
+ id?: string;
47
+ allowed_tools?: string[];
48
+ blocked_tools?: string[];
49
+ max_network_scope?: "none" | "internal-only" | "external-ok";
50
+ secret_bearing_context?: boolean;
51
+ memory_write_permission?: boolean;
52
+ };
53
+ };
54
+
55
+ function resolveMode(pluginConfig?: Record<string, unknown>): GuardMode | undefined {
56
+ const mode = pluginConfig?.mode;
57
+ if (mode === "monitor" || mode === "enforce" || mode === "strict") {
58
+ return mode;
59
+ }
60
+ return undefined;
61
+ }
62
+
63
+ function resolveAuditLog(pluginConfig?: Record<string, unknown>): boolean {
64
+ return pluginConfig?.auditLog !== false;
65
+ }
66
+
67
+ function beforeToolCall(
68
+ event: PluginHookBeforeToolCallEvent,
69
+ ctx: PluginHookToolContext,
70
+ api: OpenClawPluginApi,
71
+ ) {
72
+ const result = runtimeGuardApi.scanToolCall(event.toolName, event.params, {
73
+ mode: resolveMode(api.pluginConfig),
74
+ auditLog: resolveAuditLog(api.pluginConfig),
75
+ sessionKey: ctx.sessionKey,
76
+ sessionId: ctx.sessionId,
77
+ runId: ctx.runId ?? event.runId,
78
+ toolCallId: ctx.toolCallId ?? event.toolCallId,
79
+ agentId: ctx.agentId,
80
+ policy: ctx.policy,
81
+ });
82
+
83
+ if (!result.blocked) return;
84
+ return {
85
+ block: true,
86
+ blockReason: result.blockReason ?? "guard-scanner blocked the tool call.",
87
+ };
88
+ }
89
+
90
+ const plugin = {
91
+ id: "guard-scanner",
92
+ name: "guard-scanner",
93
+ version: "15.0.0",
94
+ description: "Runtime guard for OpenClaw before_tool_call hook execution.",
95
+ register(api: OpenClawPluginApi) {
96
+ api.on(
97
+ "before_tool_call",
98
+ (event: PluginHookBeforeToolCallEvent, ctx: PluginHookToolContext) => beforeToolCall(event, ctx, api),
99
+ { priority: 90 },
100
+ );
101
+ api.logger.info(
102
+ "guard-scanner registered OpenClaw before_tool_call hook (stable: v2026.3.12, regression lane: v2026.3.8).",
103
+ );
104
+ },
105
+ };
106
+
107
+ export default plugin;
@@ -1,55 +1,32 @@
1
1
  {
2
- "name": "guard-scanner",
3
- "version": "5.0.5",
4
- "displayName": "🛡️ Guard Scanner Runtime Security for AI Agents",
5
- "description": "147 static patterns (23 categories) + 26 runtime checks (5 layers). 0.016ms/scan, zero dependencies, SARIF output.",
6
- "author": "Guava & Dee",
7
- "license": "MIT",
8
- "homepage": "https://github.com/koatora20/guard-scanner",
9
- "repository": "https://github.com/koatora20/guard-scanner",
10
- "keywords": [
11
- "security",
12
- "runtime-guard",
13
- "threat-detection",
14
- "before-tool-call"
15
- ],
16
- "hooks": {
17
- "before_tool_call": {
18
- "handler": "./hooks/guard-scanner/plugin.ts",
19
- "description": "Scans tool call arguments against 26 runtime threat patterns (5 layers) and blocks dangerous operations",
20
- "priority": 100
21
- }
2
+ "id": "guard-scanner",
3
+ "name": "guard-scanner",
4
+ "description": "Runtime guard plugin for OpenClaw before_tool_call enforcement with capability-scoped policy rationale.",
5
+ "version": "16.0.0",
6
+ "configSchema": {
7
+ "type": "object",
8
+ "properties": {
9
+ "mode": {
10
+ "type": "string",
11
+ "enum": [
12
+ "monitor",
13
+ "enforce",
14
+ "strict"
15
+ ],
16
+ "default": "enforce",
17
+ "description": "monitor: log only | enforce: block CRITICAL | strict: block HIGH+CRITICAL"
18
+ },
19
+ "auditLog": {
20
+ "type": "boolean",
21
+ "default": true,
22
+ "description": "Enable audit logging to ~/.openclaw/guard-scanner/audit.jsonl"
23
+ },
24
+ "customRules": {
25
+ "type": "string",
26
+ "description": "Path to custom rules JSON file (optional)"
27
+ }
22
28
  },
23
- "configSchema": {
24
- "type": "object",
25
- "properties": {
26
- "mode": {
27
- "type": "string",
28
- "enum": [
29
- "monitor",
30
- "enforce",
31
- "strict"
32
- ],
33
- "default": "enforce",
34
- "description": "monitor: log only | enforce: block CRITICAL | strict: block HIGH+CRITICAL"
35
- },
36
- "auditLog": {
37
- "type": "boolean",
38
- "default": true,
39
- "description": "Enable audit logging to ~/.openclaw/guard-scanner/audit.jsonl"
40
- },
41
- "customRules": {
42
- "type": "string",
43
- "description": "Path to custom rules JSON file (optional)"
44
- }
45
- },
46
- "required": [],
47
- "additionalProperties": false
48
- },
49
- "capabilities": {
50
- "cli": true,
51
- "runtimeGuard": true,
52
- "sarif": true,
53
- "cicd": true
54
- }
55
- }
29
+ "required": [],
30
+ "additionalProperties": false
31
+ }
32
+ }
package/package.json CHANGED
@@ -1,24 +1,72 @@
1
1
  {
2
2
  "name": "@guava-parity/guard-scanner",
3
- "version": "13.0.0",
3
+ "version": "16.0.0",
4
4
  "publishConfig": {
5
5
  "access": "public",
6
6
  "registry": "https://registry.npmjs.org/"
7
7
  },
8
- "description": "Agent Skill Security Scanner - 2026 Moltbook Payload Immune System",
9
- "openclaw.extensions": "./openclaw.plugin.json",
10
- "openclaw.hooks": {
11
- "guard-scanner": "./hooks/guard-scanner"
8
+ "description": "Agent Skill Security Scanner - ASI Sanctuary Enforcer (v16)",
9
+ "openclaw": {
10
+ "extensions": [
11
+ "./dist/openclaw-plugin.mjs"
12
+ ]
12
13
  },
13
- "main": "src/scanner.js",
14
+ "main": "./dist/index.cjs",
15
+ "module": "./dist/index.mjs",
16
+ "types": "./dist/index.d.ts",
17
+ "exports": {
18
+ ".": {
19
+ "types": "./dist/index.d.ts",
20
+ "import": "./dist/index.mjs",
21
+ "require": "./dist/index.cjs",
22
+ "default": "./dist/index.mjs"
23
+ },
24
+ "./plugin": {
25
+ "types": "./dist/openclaw-plugin.d.mts",
26
+ "import": "./dist/openclaw-plugin.mjs",
27
+ "require": "./dist/openclaw-plugin.cjs",
28
+ "default": "./dist/openclaw-plugin.mjs"
29
+ },
30
+ "./mcp": {
31
+ "types": "./dist/mcp-server.d.ts",
32
+ "import": "./dist/mcp-server.mjs",
33
+ "require": "./dist/mcp-server.cjs",
34
+ "default": "./dist/mcp-server.mjs"
35
+ },
36
+ "./types": {
37
+ "types": "./dist/types.d.ts",
38
+ "default": "./dist/types.d.ts"
39
+ },
40
+ "./package.json": "./package.json"
41
+ },
42
+ "sideEffects": [
43
+ "./dist/cli.cjs",
44
+ "./dist/openclaw-plugin.mjs",
45
+ "./dist/openclaw-plugin.cjs"
46
+ ],
14
47
  "bin": {
15
- "guard-scanner": "src/cli.js"
48
+ "guard-scanner": "dist/cli.cjs"
16
49
  },
17
50
  "scripts": {
18
- "scan": "node src/cli.js",
19
- "test": "node scripts/test-quality-gate.js && node --test test/*.test.js",
20
- "test:core": "node --test test/scanner.test.js test/patterns.test.js",
21
- "test:quality": "node scripts/test-quality-gate.js"
51
+ "build": "tsup --config tsup.config.ts",
52
+ "build:plugin": "npm run build",
53
+ "benchmark": "tsx scripts/benchmark.ts --write-ledgers",
54
+ "check:upstream": "tsx scripts/check-openclaw-upstream.ts",
55
+ "check:tarball": "tsx scripts/validate-tarball.ts",
56
+ "scan": "tsx src/cli.ts",
57
+ "lint": "tsx scripts/lint.ts",
58
+ "typecheck": "tsc --noEmit -p tsconfig.json",
59
+ "release:gate": "npm run build && npm run benchmark && tsx scripts/generate-capabilities.ts && tsx scripts/release-gate.ts && tsx scripts/validate-tarball.ts",
60
+ "test": "npm run build && npm run benchmark && tsx scripts/generate-capabilities.ts && tsx scripts/verify-capabilities.ts && tsx scripts/test-quality-gate.ts && tsx --test test/*.test.ts",
61
+ "test:core": "tsx --test test/scanner.test.ts test/patterns.test.ts",
62
+ "test:contracts": "npm run build:plugin && tsx scripts/release-gate.ts && tsx --test test/finding-schema.test.ts test/mcp.test.ts test/e2e-mcp.test.ts test/openclaw-plugin-compat.test.ts test/stale-claims.test.ts test/openclaw-upstream-check.test.ts",
63
+ "test:corpus": "tsx scripts/corpus-metrics.ts --check",
64
+ "test:perf": "tsx scripts/perf-regression.ts",
65
+ "test:quality": "tsx scripts/test-quality-gate.ts",
66
+ "test:rust-parity": "tsx scripts/rust-parity.ts",
67
+ "sbom": "tsx scripts/generate-sbom.ts",
68
+ "sync:readme": "tsx scripts/generate-capabilities.ts && tsx scripts/generate-readme-metrics.ts && tsx scripts/generate-readme-stats.ts",
69
+ "prepack": "npm run build:plugin && npm run release:gate"
22
70
  },
23
71
  "keywords": [
24
72
  "security",
@@ -47,20 +95,25 @@
47
95
  },
48
96
  "homepage": "https://github.com/koatora20/guard-scanner",
49
97
  "files": [
50
- "src/",
98
+ "dist/",
51
99
  "hooks/",
52
100
  "docs/",
101
+ "openclaw-plugin.mts",
53
102
  "openclaw.plugin.json",
54
103
  "SKILL.md",
55
104
  "SECURITY.md",
56
105
  "README.md",
106
+ "README_ja.md",
57
107
  "LICENSE"
58
108
  ],
59
109
  "devDependencies": {
60
110
  "@types/node": "^22.0.0",
111
+ "openclaw": "2026.3.12",
112
+ "tsx": "^4.20.5",
113
+ "tsup": "^8.5.0",
61
114
  "typescript": "^5.7.0"
62
115
  },
63
116
  "dependencies": {
64
117
  "ws": "^8.19.0"
65
118
  }
66
- }
119
+ }