@clawdstrike/openclaw 0.1.2 → 0.2.1

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 (136) hide show
  1. package/README.md +88 -3
  2. package/dist/audit/adapter-logger.d.ts +3 -3
  3. package/dist/audit/adapter-logger.d.ts.map +1 -1
  4. package/dist/audit/adapter-logger.js +3 -3
  5. package/dist/audit/adapter-logger.js.map +1 -1
  6. package/dist/audit/store.d.ts +2 -2
  7. package/dist/audit/store.d.ts.map +1 -1
  8. package/dist/audit/store.js +13 -13
  9. package/dist/audit/store.js.map +1 -1
  10. package/dist/classification.d.ts +2 -2
  11. package/dist/classification.d.ts.map +1 -1
  12. package/dist/classification.js +96 -28
  13. package/dist/classification.js.map +1 -1
  14. package/dist/cli/bin.js +1 -1
  15. package/dist/cli/commands/audit.d.ts.map +1 -1
  16. package/dist/cli/commands/audit.js +29 -29
  17. package/dist/cli/commands/audit.js.map +1 -1
  18. package/dist/cli/commands/policy.d.ts.map +1 -1
  19. package/dist/cli/commands/policy.js +33 -33
  20. package/dist/cli/commands/policy.js.map +1 -1
  21. package/dist/cli/index.d.ts +1 -1
  22. package/dist/cli/index.d.ts.map +1 -1
  23. package/dist/cli/index.js +45 -56
  24. package/dist/cli/index.js.map +1 -1
  25. package/dist/config.d.ts +1 -1
  26. package/dist/config.d.ts.map +1 -1
  27. package/dist/config.js +9 -9
  28. package/dist/config.js.map +1 -1
  29. package/dist/e2e/openclaw-e2e.js +58 -49
  30. package/dist/e2e/openclaw-e2e.js.map +1 -1
  31. package/dist/engine-holder.d.ts +2 -2
  32. package/dist/engine-holder.js +1 -1
  33. package/dist/guards/egress.d.ts +2 -2
  34. package/dist/guards/egress.d.ts.map +1 -1
  35. package/dist/guards/egress.js +71 -73
  36. package/dist/guards/egress.js.map +1 -1
  37. package/dist/guards/forbidden-path.d.ts +2 -2
  38. package/dist/guards/forbidden-path.d.ts.map +1 -1
  39. package/dist/guards/forbidden-path.js +41 -43
  40. package/dist/guards/forbidden-path.js.map +1 -1
  41. package/dist/guards/index.d.ts +6 -6
  42. package/dist/guards/index.d.ts.map +1 -1
  43. package/dist/guards/index.js +5 -5
  44. package/dist/guards/index.js.map +1 -1
  45. package/dist/guards/patch-integrity.d.ts +2 -2
  46. package/dist/guards/patch-integrity.d.ts.map +1 -1
  47. package/dist/guards/patch-integrity.js +69 -70
  48. package/dist/guards/patch-integrity.js.map +1 -1
  49. package/dist/guards/secret-leak.d.ts +2 -2
  50. package/dist/guards/secret-leak.d.ts.map +1 -1
  51. package/dist/guards/secret-leak.js +81 -82
  52. package/dist/guards/secret-leak.js.map +1 -1
  53. package/dist/guards/types.d.ts +2 -2
  54. package/dist/guards/types.d.ts.map +1 -1
  55. package/dist/guards/types.js +4 -4
  56. package/dist/guards/types.js.map +1 -1
  57. package/dist/hooks/agent-bootstrap/handler.d.ts +1 -1
  58. package/dist/hooks/agent-bootstrap/handler.d.ts.map +1 -1
  59. package/dist/hooks/agent-bootstrap/handler.js +5 -5
  60. package/dist/hooks/agent-bootstrap/handler.js.map +1 -1
  61. package/dist/hooks/approval-state.d.ts +1 -1
  62. package/dist/hooks/approval-state.d.ts.map +1 -1
  63. package/dist/hooks/approval-state.js +15 -15
  64. package/dist/hooks/approval-state.js.map +1 -1
  65. package/dist/hooks/approval-utils.d.ts +1 -1
  66. package/dist/hooks/approval-utils.d.ts.map +1 -1
  67. package/dist/hooks/approval-utils.js +41 -20
  68. package/dist/hooks/approval-utils.js.map +1 -1
  69. package/dist/hooks/audit-logger/handler.d.ts +1 -1
  70. package/dist/hooks/audit-logger/handler.d.ts.map +1 -1
  71. package/dist/hooks/audit-logger/handler.js +9 -9
  72. package/dist/hooks/audit-logger/handler.js.map +1 -1
  73. package/dist/hooks/cua-bridge/handler.d.ts +4 -4
  74. package/dist/hooks/cua-bridge/handler.d.ts.map +1 -1
  75. package/dist/hooks/cua-bridge/handler.js +85 -70
  76. package/dist/hooks/cua-bridge/handler.js.map +1 -1
  77. package/dist/hooks/tool-guard/handler.d.ts +1 -1
  78. package/dist/hooks/tool-guard/handler.d.ts.map +1 -1
  79. package/dist/hooks/tool-guard/handler.js +112 -101
  80. package/dist/hooks/tool-guard/handler.js.map +1 -1
  81. package/dist/hooks/tool-preflight/handler.d.ts +2 -2
  82. package/dist/hooks/tool-preflight/handler.d.ts.map +1 -1
  83. package/dist/hooks/tool-preflight/handler.js +115 -91
  84. package/dist/hooks/tool-preflight/handler.js.map +1 -1
  85. package/dist/index.d.ts +16 -16
  86. package/dist/index.d.ts.map +1 -1
  87. package/dist/index.js +18 -18
  88. package/dist/index.js.map +1 -1
  89. package/dist/openclaw-adapter.d.ts +2 -2
  90. package/dist/openclaw-adapter.d.ts.map +1 -1
  91. package/dist/openclaw-adapter.js +4 -4
  92. package/dist/openclaw-adapter.js.map +1 -1
  93. package/dist/plugin.d.ts.map +1 -1
  94. package/dist/plugin.js +39 -40
  95. package/dist/plugin.js.map +1 -1
  96. package/dist/policy/engine.d.ts +1 -1
  97. package/dist/policy/engine.d.ts.map +1 -1
  98. package/dist/policy/engine.js +237 -221
  99. package/dist/policy/engine.js.map +1 -1
  100. package/dist/policy/index.d.ts +3 -3
  101. package/dist/policy/index.d.ts.map +1 -1
  102. package/dist/policy/index.js +3 -3
  103. package/dist/policy/index.js.map +1 -1
  104. package/dist/policy/loader.d.ts +1 -1
  105. package/dist/policy/loader.d.ts.map +1 -1
  106. package/dist/policy/loader.js +76 -63
  107. package/dist/policy/loader.js.map +1 -1
  108. package/dist/policy/validator.d.ts +1 -1
  109. package/dist/policy/validator.d.ts.map +1 -1
  110. package/dist/policy/validator.js +158 -151
  111. package/dist/policy/validator.js.map +1 -1
  112. package/dist/receipt/signer.d.ts +2 -2
  113. package/dist/receipt/signer.d.ts.map +1 -1
  114. package/dist/receipt/signer.js +12 -12
  115. package/dist/receipt/signer.js.map +1 -1
  116. package/dist/receipt/types.d.ts +2 -2
  117. package/dist/receipt/types.d.ts.map +1 -1
  118. package/dist/sanitizer/output-sanitizer.d.ts +1 -1
  119. package/dist/sanitizer/output-sanitizer.d.ts.map +1 -1
  120. package/dist/sanitizer/output-sanitizer.js +8 -8
  121. package/dist/sanitizer/output-sanitizer.js.map +1 -1
  122. package/dist/security-prompt.d.ts +1 -1
  123. package/dist/security-prompt.d.ts.map +1 -1
  124. package/dist/security-prompt.js +16 -12
  125. package/dist/security-prompt.js.map +1 -1
  126. package/dist/tools/policy-check.d.ts +3 -3
  127. package/dist/tools/policy-check.d.ts.map +1 -1
  128. package/dist/tools/policy-check.js +60 -52
  129. package/dist/tools/policy-check.js.map +1 -1
  130. package/dist/translator/openclaw-translator.d.ts +1 -1
  131. package/dist/translator/openclaw-translator.d.ts.map +1 -1
  132. package/dist/translator/openclaw-translator.js +100 -80
  133. package/dist/translator/openclaw-translator.js.map +1 -1
  134. package/dist/types.d.ts +11 -13
  135. package/dist/types.d.ts.map +1 -1
  136. package/package.json +9 -4
@@ -1,63 +1,63 @@
1
- import { validatePolicy as validateCanonicalPolicy } from '@clawdstrike/policy';
2
- export const POLICY_SCHEMA_VERSION = 'clawdstrike-v1.0';
3
- const SUPPORTED_CANONICAL_VERSIONS = new Set(['1.1.0', '1.2.0']);
4
- const VALID_EGRESS_MODES = new Set(['allowlist', 'denylist', 'open', 'deny_all']);
5
- const VALID_VIOLATION_ACTIONS = new Set(['cancel', 'warn']);
6
- const UNIMPLEMENTED_VIOLATION_ACTIONS = new Set(['isolate', 'escalate']);
7
- const VALID_TIMEOUT_BEHAVIORS = new Set(['allow', 'deny', 'warn', 'defer']);
8
- const VALID_EXECUTION_MODES = new Set(['parallel', 'sequential', 'background']);
9
- const VALID_COMPUTER_USE_MODES = new Set(['observe', 'guardrail', 'fail_closed']);
1
+ import { validatePolicy as validateCanonicalPolicy } from "@clawdstrike/policy";
2
+ export const POLICY_SCHEMA_VERSION = "clawdstrike-v1.0";
3
+ const SUPPORTED_CANONICAL_VERSIONS = new Set(["1.1.0", "1.2.0"]);
4
+ const VALID_EGRESS_MODES = new Set(["allowlist", "denylist", "open", "deny_all"]);
5
+ const VALID_VIOLATION_ACTIONS = new Set(["cancel", "warn"]);
6
+ const UNIMPLEMENTED_VIOLATION_ACTIONS = new Set(["isolate", "escalate"]);
7
+ const VALID_TIMEOUT_BEHAVIORS = new Set(["allow", "deny", "warn", "defer"]);
8
+ const VALID_EXECUTION_MODES = new Set(["parallel", "sequential", "background"]);
9
+ const VALID_COMPUTER_USE_MODES = new Set(["observe", "guardrail", "fail_closed"]);
10
10
  const PLACEHOLDER_RE = /\$\{([^}]+)\}/g;
11
11
  const RESERVED_PACKAGES = new Set([
12
- 'clawdstrike-virustotal',
13
- 'clawdstrike-safe-browsing',
14
- 'clawdstrike-snyk',
12
+ "clawdstrike-virustotal",
13
+ "clawdstrike-safe-browsing",
14
+ "clawdstrike-snyk",
15
15
  ]);
16
16
  const POLICY_KEYS = new Set([
17
- 'version',
18
- 'extends',
19
- 'egress',
20
- 'filesystem',
21
- 'execution',
22
- 'tools',
23
- 'limits',
24
- 'guards',
25
- 'on_violation',
17
+ "version",
18
+ "extends",
19
+ "egress",
20
+ "filesystem",
21
+ "execution",
22
+ "tools",
23
+ "limits",
24
+ "guards",
25
+ "on_violation",
26
26
  ]);
27
- const EGRESS_KEYS = new Set(['mode', 'allowed_domains', 'allowed_cidrs', 'denied_domains']);
28
- const FILESYSTEM_KEYS = new Set(['allowed_write_roots', 'allowed_read_paths', 'forbidden_paths']);
29
- const EXECUTION_KEYS = new Set(['allowed_commands', 'denied_patterns']);
30
- const TOOLS_KEYS = new Set(['allowed', 'denied']);
31
- const LIMITS_KEYS = new Set(['max_execution_seconds', 'max_memory_mb', 'max_output_bytes']);
27
+ const EGRESS_KEYS = new Set(["mode", "allowed_domains", "allowed_cidrs", "denied_domains"]);
28
+ const FILESYSTEM_KEYS = new Set(["allowed_write_roots", "allowed_read_paths", "forbidden_paths"]);
29
+ const EXECUTION_KEYS = new Set(["allowed_commands", "denied_patterns"]);
30
+ const TOOLS_KEYS = new Set(["allowed", "denied"]);
31
+ const LIMITS_KEYS = new Set(["max_execution_seconds", "max_memory_mb", "max_output_bytes"]);
32
32
  const GUARDS_KEYS = new Set([
33
- 'forbidden_path',
34
- 'egress',
35
- 'secret_leak',
36
- 'patch_integrity',
37
- 'mcp_tool',
38
- 'custom',
39
- 'computer_use',
40
- 'remote_desktop_side_channel',
41
- 'input_injection_capability',
33
+ "forbidden_path",
34
+ "egress",
35
+ "secret_leak",
36
+ "patch_integrity",
37
+ "mcp_tool",
38
+ "custom",
39
+ "computer_use",
40
+ "remote_desktop_side_channel",
41
+ "input_injection_capability",
42
42
  ]);
43
- const COMPUTER_USE_KEYS = new Set(['enabled', 'mode', 'allowed_actions']);
43
+ const COMPUTER_USE_KEYS = new Set(["enabled", "mode", "allowed_actions"]);
44
44
  const REMOTE_DESKTOP_SIDE_CHANNEL_KEYS = new Set([
45
- 'enabled',
46
- 'clipboard_enabled',
47
- 'file_transfer_enabled',
48
- 'audio_enabled',
49
- 'drive_mapping_enabled',
50
- 'printing_enabled',
51
- 'session_share_enabled',
52
- 'max_transfer_size_bytes',
45
+ "enabled",
46
+ "clipboard_enabled",
47
+ "file_transfer_enabled",
48
+ "audio_enabled",
49
+ "drive_mapping_enabled",
50
+ "printing_enabled",
51
+ "session_share_enabled",
52
+ "max_transfer_size_bytes",
53
53
  ]);
54
54
  const INPUT_INJECTION_CAPABILITY_KEYS = new Set([
55
- 'enabled',
56
- 'allowed_input_types',
57
- 'require_postcondition_probe',
55
+ "enabled",
56
+ "allowed_input_types",
57
+ "require_postcondition_probe",
58
58
  ]);
59
59
  function isPlainObject(value) {
60
- return typeof value === 'object' && value !== null && !Array.isArray(value);
60
+ return typeof value === "object" && value !== null && !Array.isArray(value);
61
61
  }
62
62
  function ensureAllowedKeys(obj, field, allowed, errors) {
63
63
  for (const key of Object.keys(obj)) {
@@ -69,7 +69,7 @@ function ensureAllowedKeys(obj, field, allowed, errors) {
69
69
  function ensureBoolean(value, field, errors) {
70
70
  if (value === undefined)
71
71
  return;
72
- if (typeof value !== 'boolean') {
72
+ if (typeof value !== "boolean") {
73
73
  errors.push(`${field} must be a boolean`);
74
74
  }
75
75
  }
@@ -83,11 +83,11 @@ function ensureStringArray(value, field, errors, warnings) {
83
83
  const out = [];
84
84
  for (let i = 0; i < value.length; i++) {
85
85
  const item = value[i];
86
- if (typeof item !== 'string') {
86
+ if (typeof item !== "string") {
87
87
  errors.push(`${field}[${i}] must be a string`);
88
88
  continue;
89
89
  }
90
- if (item.includes('\u0000')) {
90
+ if (item.includes("\u0000")) {
91
91
  errors.push(`${field}[${i}] contains a null byte`);
92
92
  continue;
93
93
  }
@@ -101,14 +101,14 @@ function ensureStringArray(value, field, errors, warnings) {
101
101
  function ensurePositiveNumber(value, field, errors) {
102
102
  if (value === undefined)
103
103
  return;
104
- if (typeof value !== 'number' || !Number.isFinite(value) || value <= 0) {
104
+ if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) {
105
105
  errors.push(`${field} must be a positive number`);
106
106
  }
107
107
  }
108
108
  function ensureFiniteNumber(value, field, errors) {
109
109
  if (value === undefined)
110
110
  return;
111
- if (typeof value !== 'number' || !Number.isFinite(value)) {
111
+ if (typeof value !== "number" || !Number.isFinite(value)) {
112
112
  errors.push(`${field} must be a finite number`);
113
113
  }
114
114
  }
@@ -116,15 +116,15 @@ export function validatePolicy(policy) {
116
116
  const errors = [];
117
117
  const warnings = [];
118
118
  if (!isPlainObject(policy)) {
119
- return { valid: false, errors: ['Policy must be an object'], warnings: [] };
119
+ return { valid: false, errors: ["Policy must be an object"], warnings: [] };
120
120
  }
121
- ensureAllowedKeys(policy, 'policy', POLICY_KEYS, errors);
121
+ ensureAllowedKeys(policy, "policy", POLICY_KEYS, errors);
122
122
  const p = policy;
123
123
  if (p.version === undefined) {
124
124
  errors.push(`version is required (expected: ${POLICY_SCHEMA_VERSION})`);
125
125
  }
126
- else if (typeof p.version !== 'string') {
127
- errors.push('version must be a string');
126
+ else if (typeof p.version !== "string") {
127
+ errors.push("version must be a string");
128
128
  }
129
129
  else if (SUPPORTED_CANONICAL_VERSIONS.has(p.version)) {
130
130
  const canonical = validateCanonicalPolicy(policy);
@@ -137,49 +137,49 @@ export function validatePolicy(policy) {
137
137
  else if (p.version !== POLICY_SCHEMA_VERSION) {
138
138
  errors.push(`unsupported policy version: ${p.version} (supported: ${POLICY_SCHEMA_VERSION}, 1.1.0, 1.2.0)`);
139
139
  }
140
- if (p.extends !== undefined && typeof p.extends !== 'string') {
141
- errors.push('extends must be a string');
140
+ if (p.extends !== undefined && typeof p.extends !== "string") {
141
+ errors.push("extends must be a string");
142
142
  }
143
143
  // Egress validation
144
144
  if (p.egress !== undefined) {
145
145
  if (!isPlainObject(p.egress)) {
146
- errors.push('egress must be an object');
146
+ errors.push("egress must be an object");
147
147
  }
148
148
  else {
149
- ensureAllowedKeys(p.egress, 'egress', EGRESS_KEYS, errors);
149
+ ensureAllowedKeys(p.egress, "egress", EGRESS_KEYS, errors);
150
150
  const mode = p.egress.mode;
151
- if (mode !== undefined && (!VALID_EGRESS_MODES.has(mode) || typeof mode !== 'string')) {
152
- errors.push(`egress.mode must be one of: ${[...VALID_EGRESS_MODES].join(', ')}`);
151
+ if (mode !== undefined && (!VALID_EGRESS_MODES.has(mode) || typeof mode !== "string")) {
152
+ errors.push(`egress.mode must be one of: ${[...VALID_EGRESS_MODES].join(", ")}`);
153
153
  }
154
- const allowed = ensureStringArray(p.egress.allowed_domains, 'egress.allowed_domains', errors);
155
- if (mode === 'allowlist' && allowed && allowed.length === 0) {
156
- warnings.push('egress.allowlist with empty allowed_domains will deny all egress');
154
+ const allowed = ensureStringArray(p.egress.allowed_domains, "egress.allowed_domains", errors);
155
+ if (mode === "allowlist" && allowed && allowed.length === 0) {
156
+ warnings.push("egress.allowlist with empty allowed_domains will deny all egress");
157
157
  }
158
- ensureStringArray(p.egress.denied_domains, 'egress.denied_domains', errors);
159
- ensureStringArray(p.egress.allowed_cidrs, 'egress.allowed_cidrs', errors);
158
+ ensureStringArray(p.egress.denied_domains, "egress.denied_domains", errors);
159
+ ensureStringArray(p.egress.allowed_cidrs, "egress.allowed_cidrs", errors);
160
160
  }
161
161
  }
162
162
  // Filesystem validation
163
163
  if (p.filesystem !== undefined) {
164
164
  if (!isPlainObject(p.filesystem)) {
165
- errors.push('filesystem must be an object');
165
+ errors.push("filesystem must be an object");
166
166
  }
167
167
  else {
168
- ensureAllowedKeys(p.filesystem, 'filesystem', FILESYSTEM_KEYS, errors);
169
- ensureStringArray(p.filesystem.allowed_write_roots, 'filesystem.allowed_write_roots', errors);
170
- ensureStringArray(p.filesystem.allowed_read_paths, 'filesystem.allowed_read_paths', errors);
171
- ensureStringArray(p.filesystem.forbidden_paths, 'filesystem.forbidden_paths', errors, warnings);
168
+ ensureAllowedKeys(p.filesystem, "filesystem", FILESYSTEM_KEYS, errors);
169
+ ensureStringArray(p.filesystem.allowed_write_roots, "filesystem.allowed_write_roots", errors);
170
+ ensureStringArray(p.filesystem.allowed_read_paths, "filesystem.allowed_read_paths", errors);
171
+ ensureStringArray(p.filesystem.forbidden_paths, "filesystem.forbidden_paths", errors, warnings);
172
172
  }
173
173
  }
174
174
  // Execution validation
175
175
  if (p.execution !== undefined) {
176
176
  if (!isPlainObject(p.execution)) {
177
- errors.push('execution must be an object');
177
+ errors.push("execution must be an object");
178
178
  }
179
179
  else {
180
- ensureAllowedKeys(p.execution, 'execution', EXECUTION_KEYS, errors);
181
- ensureStringArray(p.execution.allowed_commands, 'execution.allowed_commands', errors);
182
- const patterns = ensureStringArray(p.execution.denied_patterns, 'execution.denied_patterns', errors);
180
+ ensureAllowedKeys(p.execution, "execution", EXECUTION_KEYS, errors);
181
+ ensureStringArray(p.execution.allowed_commands, "execution.allowed_commands", errors);
182
+ const patterns = ensureStringArray(p.execution.denied_patterns, "execution.denied_patterns", errors);
183
183
  if (patterns) {
184
184
  for (const pattern of patterns) {
185
185
  try {
@@ -196,95 +196,97 @@ export function validatePolicy(policy) {
196
196
  // Tool policy validation
197
197
  if (p.tools !== undefined) {
198
198
  if (!isPlainObject(p.tools)) {
199
- errors.push('tools must be an object');
199
+ errors.push("tools must be an object");
200
200
  }
201
201
  else {
202
- ensureAllowedKeys(p.tools, 'tools', TOOLS_KEYS, errors);
203
- ensureStringArray(p.tools.allowed, 'tools.allowed', errors);
204
- ensureStringArray(p.tools.denied, 'tools.denied', errors);
202
+ ensureAllowedKeys(p.tools, "tools", TOOLS_KEYS, errors);
203
+ ensureStringArray(p.tools.allowed, "tools.allowed", errors);
204
+ ensureStringArray(p.tools.denied, "tools.denied", errors);
205
205
  }
206
206
  }
207
207
  // Limits validation
208
208
  if (p.limits !== undefined) {
209
209
  if (!isPlainObject(p.limits)) {
210
- errors.push('limits must be an object');
210
+ errors.push("limits must be an object");
211
211
  }
212
212
  else {
213
- ensureAllowedKeys(p.limits, 'limits', LIMITS_KEYS, errors);
214
- ensurePositiveNumber(p.limits.max_execution_seconds, 'limits.max_execution_seconds', errors);
215
- ensurePositiveNumber(p.limits.max_memory_mb, 'limits.max_memory_mb', errors);
216
- ensurePositiveNumber(p.limits.max_output_bytes, 'limits.max_output_bytes', errors);
213
+ ensureAllowedKeys(p.limits, "limits", LIMITS_KEYS, errors);
214
+ ensurePositiveNumber(p.limits.max_execution_seconds, "limits.max_execution_seconds", errors);
215
+ ensurePositiveNumber(p.limits.max_memory_mb, "limits.max_memory_mb", errors);
216
+ ensurePositiveNumber(p.limits.max_output_bytes, "limits.max_output_bytes", errors);
217
217
  }
218
218
  }
219
219
  // Guard toggles validation
220
220
  if (p.guards !== undefined) {
221
221
  if (!isPlainObject(p.guards)) {
222
- errors.push('guards must be an object');
222
+ errors.push("guards must be an object");
223
223
  }
224
224
  else {
225
- ensureAllowedKeys(p.guards, 'guards', GUARDS_KEYS, errors);
226
- ensureBoolean(p.guards.forbidden_path, 'guards.forbidden_path', errors);
227
- ensureBoolean(p.guards.egress, 'guards.egress', errors);
228
- ensureBoolean(p.guards.secret_leak, 'guards.secret_leak', errors);
229
- ensureBoolean(p.guards.patch_integrity, 'guards.patch_integrity', errors);
230
- ensureBoolean(p.guards.mcp_tool, 'guards.mcp_tool', errors);
225
+ ensureAllowedKeys(p.guards, "guards", GUARDS_KEYS, errors);
226
+ ensureBoolean(p.guards.forbidden_path, "guards.forbidden_path", errors);
227
+ ensureBoolean(p.guards.egress, "guards.egress", errors);
228
+ ensureBoolean(p.guards.secret_leak, "guards.secret_leak", errors);
229
+ ensureBoolean(p.guards.patch_integrity, "guards.patch_integrity", errors);
230
+ ensureBoolean(p.guards.mcp_tool, "guards.mcp_tool", errors);
231
231
  const computerUse = p.guards.computer_use;
232
232
  if (computerUse !== undefined) {
233
233
  if (!isPlainObject(computerUse)) {
234
- errors.push('guards.computer_use must be an object');
234
+ errors.push("guards.computer_use must be an object");
235
235
  }
236
236
  else {
237
- ensureAllowedKeys(computerUse, 'guards.computer_use', COMPUTER_USE_KEYS, errors);
238
- ensureBoolean(computerUse.enabled, 'guards.computer_use.enabled', errors);
237
+ ensureAllowedKeys(computerUse, "guards.computer_use", COMPUTER_USE_KEYS, errors);
238
+ ensureBoolean(computerUse.enabled, "guards.computer_use.enabled", errors);
239
239
  const mode = computerUse.mode;
240
- if (mode !== undefined && (typeof mode !== 'string' || !VALID_COMPUTER_USE_MODES.has(mode))) {
241
- errors.push(`guards.computer_use.mode must be one of: ${[...VALID_COMPUTER_USE_MODES].join(', ')}`);
240
+ if (mode !== undefined &&
241
+ (typeof mode !== "string" || !VALID_COMPUTER_USE_MODES.has(mode))) {
242
+ errors.push(`guards.computer_use.mode must be one of: ${[...VALID_COMPUTER_USE_MODES].join(", ")}`);
242
243
  }
243
- const allowedActions = ensureStringArray(computerUse.allowed_actions, 'guards.computer_use.allowed_actions', errors);
244
+ const allowedActions = ensureStringArray(computerUse.allowed_actions, "guards.computer_use.allowed_actions", errors);
244
245
  if (allowedActions && allowedActions.length === 0) {
245
- warnings.push('guards.computer_use.allowed_actions is empty (all actions allowed)');
246
+ warnings.push("guards.computer_use.allowed_actions is empty (all actions allowed)");
246
247
  }
247
248
  }
248
249
  }
249
250
  const remoteSideChannel = p.guards.remote_desktop_side_channel;
250
251
  if (remoteSideChannel !== undefined) {
251
252
  if (!isPlainObject(remoteSideChannel)) {
252
- errors.push('guards.remote_desktop_side_channel must be an object');
253
+ errors.push("guards.remote_desktop_side_channel must be an object");
253
254
  }
254
255
  else {
255
- ensureAllowedKeys(remoteSideChannel, 'guards.remote_desktop_side_channel', REMOTE_DESKTOP_SIDE_CHANNEL_KEYS, errors);
256
- ensureBoolean(remoteSideChannel.enabled, 'guards.remote_desktop_side_channel.enabled', errors);
257
- ensureBoolean(remoteSideChannel.clipboard_enabled, 'guards.remote_desktop_side_channel.clipboard_enabled', errors);
258
- ensureBoolean(remoteSideChannel.file_transfer_enabled, 'guards.remote_desktop_side_channel.file_transfer_enabled', errors);
259
- ensureBoolean(remoteSideChannel.audio_enabled, 'guards.remote_desktop_side_channel.audio_enabled', errors);
260
- ensureBoolean(remoteSideChannel.drive_mapping_enabled, 'guards.remote_desktop_side_channel.drive_mapping_enabled', errors);
261
- ensureBoolean(remoteSideChannel.printing_enabled, 'guards.remote_desktop_side_channel.printing_enabled', errors);
262
- ensureBoolean(remoteSideChannel.session_share_enabled, 'guards.remote_desktop_side_channel.session_share_enabled', errors);
263
- ensureFiniteNumber(remoteSideChannel.max_transfer_size_bytes, 'guards.remote_desktop_side_channel.max_transfer_size_bytes', errors);
264
- if (typeof remoteSideChannel.max_transfer_size_bytes === 'number' && remoteSideChannel.max_transfer_size_bytes < 0) {
265
- errors.push('guards.remote_desktop_side_channel.max_transfer_size_bytes must be >= 0');
256
+ ensureAllowedKeys(remoteSideChannel, "guards.remote_desktop_side_channel", REMOTE_DESKTOP_SIDE_CHANNEL_KEYS, errors);
257
+ ensureBoolean(remoteSideChannel.enabled, "guards.remote_desktop_side_channel.enabled", errors);
258
+ ensureBoolean(remoteSideChannel.clipboard_enabled, "guards.remote_desktop_side_channel.clipboard_enabled", errors);
259
+ ensureBoolean(remoteSideChannel.file_transfer_enabled, "guards.remote_desktop_side_channel.file_transfer_enabled", errors);
260
+ ensureBoolean(remoteSideChannel.audio_enabled, "guards.remote_desktop_side_channel.audio_enabled", errors);
261
+ ensureBoolean(remoteSideChannel.drive_mapping_enabled, "guards.remote_desktop_side_channel.drive_mapping_enabled", errors);
262
+ ensureBoolean(remoteSideChannel.printing_enabled, "guards.remote_desktop_side_channel.printing_enabled", errors);
263
+ ensureBoolean(remoteSideChannel.session_share_enabled, "guards.remote_desktop_side_channel.session_share_enabled", errors);
264
+ ensureFiniteNumber(remoteSideChannel.max_transfer_size_bytes, "guards.remote_desktop_side_channel.max_transfer_size_bytes", errors);
265
+ if (typeof remoteSideChannel.max_transfer_size_bytes === "number" &&
266
+ remoteSideChannel.max_transfer_size_bytes < 0) {
267
+ errors.push("guards.remote_desktop_side_channel.max_transfer_size_bytes must be >= 0");
266
268
  }
267
269
  }
268
270
  }
269
271
  const inputInjection = p.guards.input_injection_capability;
270
272
  if (inputInjection !== undefined) {
271
273
  if (!isPlainObject(inputInjection)) {
272
- errors.push('guards.input_injection_capability must be an object');
274
+ errors.push("guards.input_injection_capability must be an object");
273
275
  }
274
276
  else {
275
- ensureAllowedKeys(inputInjection, 'guards.input_injection_capability', INPUT_INJECTION_CAPABILITY_KEYS, errors);
276
- ensureBoolean(inputInjection.enabled, 'guards.input_injection_capability.enabled', errors);
277
- const inputTypes = ensureStringArray(inputInjection.allowed_input_types, 'guards.input_injection_capability.allowed_input_types', errors);
277
+ ensureAllowedKeys(inputInjection, "guards.input_injection_capability", INPUT_INJECTION_CAPABILITY_KEYS, errors);
278
+ ensureBoolean(inputInjection.enabled, "guards.input_injection_capability.enabled", errors);
279
+ const inputTypes = ensureStringArray(inputInjection.allowed_input_types, "guards.input_injection_capability.allowed_input_types", errors);
278
280
  if (inputTypes && inputTypes.length === 0) {
279
- warnings.push('guards.input_injection_capability.allowed_input_types is empty (all input types allowed)');
281
+ warnings.push("guards.input_injection_capability.allowed_input_types is empty (all input types allowed)");
280
282
  }
281
- ensureBoolean(inputInjection.require_postcondition_probe, 'guards.input_injection_capability.require_postcondition_probe', errors);
283
+ ensureBoolean(inputInjection.require_postcondition_probe, "guards.input_injection_capability.require_postcondition_probe", errors);
282
284
  }
283
285
  }
284
286
  const custom = p.guards.custom;
285
287
  if (custom !== undefined) {
286
288
  if (!Array.isArray(custom)) {
287
- errors.push('guards.custom must be an array');
289
+ errors.push("guards.custom must be an array");
288
290
  }
289
291
  else {
290
292
  for (let i = 0; i < custom.length; i++) {
@@ -295,17 +297,17 @@ export function validatePolicy(policy) {
295
297
  }
296
298
  }
297
299
  // Validate placeholders across the entire policy tree (fail closed on missing env).
298
- validatePlaceholders(policy, 'policy', errors);
300
+ validatePlaceholders(policy, "policy", errors);
299
301
  // on_violation validation
300
302
  if (p.on_violation !== undefined) {
301
- if (typeof p.on_violation !== 'string') {
302
- errors.push(`on_violation must be one of: ${[...VALID_VIOLATION_ACTIONS].join(', ')}`);
303
+ if (typeof p.on_violation !== "string") {
304
+ errors.push(`on_violation must be one of: ${[...VALID_VIOLATION_ACTIONS].join(", ")}`);
303
305
  }
304
306
  else if (UNIMPLEMENTED_VIOLATION_ACTIONS.has(p.on_violation)) {
305
307
  warnings.push(`on_violation value '${p.on_violation}' is not yet implemented; use 'cancel' or 'warn'`);
306
308
  }
307
309
  else if (!VALID_VIOLATION_ACTIONS.has(p.on_violation)) {
308
- errors.push(`on_violation must be one of: ${[...VALID_VIOLATION_ACTIONS].join(', ')}`);
310
+ errors.push(`on_violation must be one of: ${[...VALID_VIOLATION_ACTIONS].join(", ")}`);
309
311
  }
310
312
  }
311
313
  return { valid: errors.length === 0, errors, warnings };
@@ -316,7 +318,7 @@ function validateCustomGuardSpec(value, base, errors) {
316
318
  return;
317
319
  }
318
320
  const pkg = value.package;
319
- if (typeof pkg !== 'string' || pkg.trim() === '') {
321
+ if (typeof pkg !== "string" || pkg.trim() === "") {
320
322
  errors.push(`${base}.package must be a non-empty string`);
321
323
  return;
322
324
  }
@@ -325,7 +327,7 @@ function validateCustomGuardSpec(value, base, errors) {
325
327
  return;
326
328
  }
327
329
  const enabled = value.enabled;
328
- if (enabled !== undefined && typeof enabled !== 'boolean') {
330
+ if (enabled !== undefined && typeof enabled !== "boolean") {
329
331
  errors.push(`${base}.enabled must be a boolean`);
330
332
  }
331
333
  const config = value.config;
@@ -334,14 +336,14 @@ function validateCustomGuardSpec(value, base, errors) {
334
336
  return;
335
337
  }
336
338
  const cfg = (isPlainObject(config) ? config : {});
337
- if (pkg === 'clawdstrike-virustotal') {
339
+ if (pkg === "clawdstrike-virustotal") {
338
340
  requireString(cfg, `${base}.config.api_key`, errors);
339
341
  }
340
- else if (pkg === 'clawdstrike-safe-browsing') {
342
+ else if (pkg === "clawdstrike-safe-browsing") {
341
343
  requireString(cfg, `${base}.config.api_key`, errors);
342
344
  requireString(cfg, `${base}.config.client_id`, errors);
343
345
  }
344
- else if (pkg === 'clawdstrike-snyk') {
346
+ else if (pkg === "clawdstrike-snyk") {
345
347
  requireString(cfg, `${base}.config.api_token`, errors);
346
348
  requireString(cfg, `${base}.config.org_id`, errors);
347
349
  }
@@ -356,16 +358,18 @@ function validateAsyncConfig(value, base, errors) {
356
358
  return;
357
359
  }
358
360
  const timeoutMs = value.timeout_ms;
359
- if (timeoutMs !== undefined && (!isFiniteNumber(timeoutMs) || timeoutMs < 100 || timeoutMs > 300_000)) {
361
+ if (timeoutMs !== undefined &&
362
+ (!isFiniteNumber(timeoutMs) || timeoutMs < 100 || timeoutMs > 300_000)) {
360
363
  errors.push(`${base}.timeout_ms must be between 100 and 300000`);
361
364
  }
362
365
  const onTimeout = value.on_timeout;
363
- if (onTimeout !== undefined && (typeof onTimeout !== 'string' || !VALID_TIMEOUT_BEHAVIORS.has(onTimeout))) {
364
- errors.push(`${base}.on_timeout must be one of: ${[...VALID_TIMEOUT_BEHAVIORS].join(', ')}`);
366
+ if (onTimeout !== undefined &&
367
+ (typeof onTimeout !== "string" || !VALID_TIMEOUT_BEHAVIORS.has(onTimeout))) {
368
+ errors.push(`${base}.on_timeout must be one of: ${[...VALID_TIMEOUT_BEHAVIORS].join(", ")}`);
365
369
  }
366
370
  const mode = value.execution_mode;
367
- if (mode !== undefined && (typeof mode !== 'string' || !VALID_EXECUTION_MODES.has(mode))) {
368
- errors.push(`${base}.execution_mode must be one of: ${[...VALID_EXECUTION_MODES].join(', ')}`);
371
+ if (mode !== undefined && (typeof mode !== "string" || !VALID_EXECUTION_MODES.has(mode))) {
372
+ errors.push(`${base}.execution_mode must be one of: ${[...VALID_EXECUTION_MODES].join(", ")}`);
369
373
  }
370
374
  if (value.rate_limit !== undefined) {
371
375
  if (!isPlainObject(value.rate_limit)) {
@@ -385,7 +389,8 @@ function validateAsyncConfig(value, base, errors) {
385
389
  errors.push(`${base}.rate_limit must specify only one of requests_per_second or requests_per_minute`);
386
390
  }
387
391
  const burst = rl.burst;
388
- if (burst !== undefined && (typeof burst !== 'number' || !Number.isInteger(burst) || burst < 1)) {
392
+ if (burst !== undefined &&
393
+ (typeof burst !== "number" || !Number.isInteger(burst) || burst < 1)) {
389
394
  errors.push(`${base}.rate_limit.burst must be >= 1`);
390
395
  }
391
396
  }
@@ -397,11 +402,11 @@ function validateAsyncConfig(value, base, errors) {
397
402
  else {
398
403
  const cache = value.cache;
399
404
  const ttl = cache.ttl_seconds;
400
- if (ttl !== undefined && (typeof ttl !== 'number' || !Number.isInteger(ttl) || ttl < 1)) {
405
+ if (ttl !== undefined && (typeof ttl !== "number" || !Number.isInteger(ttl) || ttl < 1)) {
401
406
  errors.push(`${base}.cache.ttl_seconds must be >= 1`);
402
407
  }
403
408
  const max = cache.max_size_mb;
404
- if (max !== undefined && (typeof max !== 'number' || !Number.isInteger(max) || max < 1)) {
409
+ if (max !== undefined && (typeof max !== "number" || !Number.isInteger(max) || max < 1)) {
405
410
  errors.push(`${base}.cache.max_size_mb must be >= 1`);
406
411
  }
407
412
  }
@@ -413,15 +418,16 @@ function validateAsyncConfig(value, base, errors) {
413
418
  else {
414
419
  const cb = value.circuit_breaker;
415
420
  const f = cb.failure_threshold;
416
- if (f !== undefined && (typeof f !== 'number' || !Number.isInteger(f) || f < 1)) {
421
+ if (f !== undefined && (typeof f !== "number" || !Number.isInteger(f) || f < 1)) {
417
422
  errors.push(`${base}.circuit_breaker.failure_threshold must be >= 1`);
418
423
  }
419
424
  const reset = cb.reset_timeout_ms;
420
- if (reset !== undefined && (typeof reset !== 'number' || !Number.isInteger(reset) || reset < 1000)) {
425
+ if (reset !== undefined &&
426
+ (typeof reset !== "number" || !Number.isInteger(reset) || reset < 1000)) {
421
427
  errors.push(`${base}.circuit_breaker.reset_timeout_ms must be >= 1000`);
422
428
  }
423
429
  const s = cb.success_threshold;
424
- if (s !== undefined && (typeof s !== 'number' || !Number.isInteger(s) || s < 1)) {
430
+ if (s !== undefined && (typeof s !== "number" || !Number.isInteger(s) || s < 1)) {
425
431
  errors.push(`${base}.circuit_breaker.success_threshold must be >= 1`);
426
432
  }
427
433
  }
@@ -437,30 +443,31 @@ function validateAsyncConfig(value, base, errors) {
437
443
  errors.push(`${base}.retry.multiplier must be >= 1`);
438
444
  }
439
445
  const init = retry.initial_backoff_ms;
440
- if (init !== undefined && (typeof init !== 'number' || !Number.isInteger(init) || init < 100)) {
446
+ if (init !== undefined &&
447
+ (typeof init !== "number" || !Number.isInteger(init) || init < 100)) {
441
448
  errors.push(`${base}.retry.initial_backoff_ms must be >= 100`);
442
449
  }
443
450
  const max = retry.max_backoff_ms;
444
- if (max !== undefined && (typeof max !== 'number' || !Number.isInteger(max) || max < 100)) {
451
+ if (max !== undefined && (typeof max !== "number" || !Number.isInteger(max) || max < 100)) {
445
452
  errors.push(`${base}.retry.max_backoff_ms must be >= 100`);
446
453
  }
447
- if (typeof init === 'number' && typeof max === 'number' && max < init) {
454
+ if (typeof init === "number" && typeof max === "number" && max < init) {
448
455
  errors.push(`${base}.retry.max_backoff_ms must be >= initial_backoff_ms`);
449
456
  }
450
457
  }
451
458
  }
452
459
  }
453
460
  function requireString(obj, field, errors) {
454
- const key = field.split('.').slice(-1)[0] ?? '';
461
+ const key = field.split(".").slice(-1)[0] ?? "";
455
462
  const value = obj[key];
456
- if (typeof value !== 'string' || value.trim() === '') {
463
+ if (typeof value !== "string" || value.trim() === "") {
457
464
  errors.push(`${field} missing/invalid required string`);
458
465
  }
459
466
  }
460
467
  function validatePlaceholders(value, base, errors) {
461
- if (typeof value === 'string') {
468
+ if (typeof value === "string") {
462
469
  for (const match of value.matchAll(PLACEHOLDER_RE)) {
463
- const raw = match[1] ?? '';
470
+ const raw = match[1] ?? "";
464
471
  const envName = envVarForPlaceholder(raw);
465
472
  if (!envName.ok) {
466
473
  errors.push(`${base}: ${envName.error}`);
@@ -485,19 +492,19 @@ function validatePlaceholders(value, base, errors) {
485
492
  }
486
493
  }
487
494
  function envVarForPlaceholder(raw) {
488
- if (raw.startsWith('secrets.')) {
489
- const name = raw.slice('secrets.'.length);
495
+ if (raw.startsWith("secrets.")) {
496
+ const name = raw.slice("secrets.".length);
490
497
  if (!name) {
491
- return { ok: false, error: 'placeholder ${secrets.} is invalid' };
498
+ return { ok: false, error: "placeholder ${secrets.} is invalid" };
492
499
  }
493
500
  return { ok: true, value: name };
494
501
  }
495
502
  if (!raw) {
496
- return { ok: false, error: 'placeholder ${} is invalid' };
503
+ return { ok: false, error: "placeholder ${} is invalid" };
497
504
  }
498
505
  return { ok: true, value: raw };
499
506
  }
500
507
  function isFiniteNumber(value) {
501
- return typeof value === 'number' && Number.isFinite(value);
508
+ return typeof value === "number" && Number.isFinite(value);
502
509
  }
503
510
  //# sourceMappingURL=validator.js.map