securityclaw 0.0.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 (62) hide show
  1. package/CHANGELOG.md +49 -0
  2. package/LICENSE +21 -0
  3. package/README.md +135 -0
  4. package/README.zh-CN.md +135 -0
  5. package/admin/public/app.js +148 -0
  6. package/admin/public/favicon.svg +21 -0
  7. package/admin/public/index.html +31 -0
  8. package/admin/public/styles.css +2715 -0
  9. package/admin/server.ts +1053 -0
  10. package/bin/install-lib.mjs +88 -0
  11. package/bin/securityclaw.mjs +66 -0
  12. package/config/policy.default.yaml +520 -0
  13. package/index.ts +2662 -0
  14. package/install.sh +22 -0
  15. package/openclaw.plugin.json +60 -0
  16. package/package.json +69 -0
  17. package/src/admin/build.ts +113 -0
  18. package/src/admin/console_notice.ts +195 -0
  19. package/src/admin/dashboard_url_state.ts +80 -0
  20. package/src/admin/openclaw_session_catalog.ts +137 -0
  21. package/src/admin/runtime_guard.ts +51 -0
  22. package/src/admin/skill_interception_store.ts +1606 -0
  23. package/src/application/commands/approval_commands.ts +189 -0
  24. package/src/approvals/chat_approval_store.ts +433 -0
  25. package/src/config/live_config.ts +144 -0
  26. package/src/config/loader.ts +168 -0
  27. package/src/config/runtime_override.ts +66 -0
  28. package/src/config/strategy_store.ts +121 -0
  29. package/src/config/validator.ts +222 -0
  30. package/src/domain/models/resource_context.ts +31 -0
  31. package/src/domain/ports/approval_repository.ts +40 -0
  32. package/src/domain/ports/notification_port.ts +29 -0
  33. package/src/domain/ports/openclaw_adapter.ts +22 -0
  34. package/src/domain/services/account_policy_engine.ts +163 -0
  35. package/src/domain/services/approval_service.ts +336 -0
  36. package/src/domain/services/approval_subject_resolver.ts +37 -0
  37. package/src/domain/services/context_inference_service.ts +502 -0
  38. package/src/domain/services/file_rule_registry.ts +171 -0
  39. package/src/domain/services/formatting_service.ts +101 -0
  40. package/src/domain/services/path_candidate_inference.ts +111 -0
  41. package/src/domain/services/sensitive_path_registry.ts +288 -0
  42. package/src/domain/services/sensitivity_label_inference.ts +161 -0
  43. package/src/domain/services/shell_filesystem_inference.ts +360 -0
  44. package/src/engine/approval_fsm.ts +104 -0
  45. package/src/engine/decision_engine.ts +39 -0
  46. package/src/engine/dlp_engine.ts +91 -0
  47. package/src/engine/rule_engine.ts +208 -0
  48. package/src/events/emitter.ts +86 -0
  49. package/src/events/schema.ts +27 -0
  50. package/src/hooks/context_guard.ts +36 -0
  51. package/src/hooks/output_guard.ts +66 -0
  52. package/src/hooks/persist_guard.ts +69 -0
  53. package/src/hooks/policy_guard.ts +222 -0
  54. package/src/hooks/result_guard.ts +88 -0
  55. package/src/i18n/locale.ts +36 -0
  56. package/src/index.ts +255 -0
  57. package/src/infrastructure/adapters/notification_adapter.ts +173 -0
  58. package/src/infrastructure/adapters/openclaw_adapter_impl.ts +59 -0
  59. package/src/infrastructure/config/plugin_config_parser.ts +105 -0
  60. package/src/monitoring/status_store.ts +612 -0
  61. package/src/types.ts +409 -0
  62. package/src/utils.ts +97 -0
@@ -0,0 +1,88 @@
1
+ export function resolveInstallTarget(options = {}) {
2
+ const archivePath = typeof options.archivePath === "string" ? options.archivePath.trim() : "";
3
+ if (archivePath) {
4
+ return archivePath;
5
+ }
6
+
7
+ const npmSpec = typeof options.npmSpec === "string" ? options.npmSpec.trim() : "";
8
+ if (npmSpec) {
9
+ return npmSpec;
10
+ }
11
+
12
+ const packageName = typeof options.packageName === "string" ? options.packageName.trim() : "";
13
+ if (!packageName) {
14
+ throw new Error("SecurityClaw installer requires a package name or archive path.");
15
+ }
16
+
17
+ const packageVersion = typeof options.packageVersion === "string" ? options.packageVersion.trim() : "";
18
+ return packageVersion ? `${packageName}@${packageVersion}` : packageName;
19
+ }
20
+
21
+ export function buildInstallPlan(options = {}) {
22
+ const openclawBin = typeof options.openclawBin === "string" && options.openclawBin.trim()
23
+ ? options.openclawBin.trim()
24
+ : "openclaw";
25
+ const installTarget = resolveInstallTarget(options);
26
+ const restart = options.restart !== false;
27
+ const verify = options.verify !== false;
28
+
29
+ return [
30
+ [openclawBin, "plugins", "install", installTarget],
31
+ ...(restart ? [[openclawBin, "gateway", "restart"]] : []),
32
+ ...(verify ? [[openclawBin, "gateway", "status"]] : []),
33
+ ];
34
+ }
35
+
36
+ export function parseInstallArgs(argv = []) {
37
+ const options = {
38
+ restart: true,
39
+ verify: true,
40
+ dryRun: false,
41
+ };
42
+
43
+ for (let index = 0; index < argv.length; index += 1) {
44
+ const token = argv[index];
45
+ if (token === "--dry-run") {
46
+ options.dryRun = true;
47
+ continue;
48
+ }
49
+ if (token === "--no-restart") {
50
+ options.restart = false;
51
+ continue;
52
+ }
53
+ if (token === "--no-status") {
54
+ options.verify = false;
55
+ continue;
56
+ }
57
+ if (token === "--archive") {
58
+ const value = argv[index + 1];
59
+ if (!value) {
60
+ throw new Error("Missing value for --archive");
61
+ }
62
+ options.archivePath = value;
63
+ index += 1;
64
+ continue;
65
+ }
66
+ if (token === "--npm-spec") {
67
+ const value = argv[index + 1];
68
+ if (!value) {
69
+ throw new Error("Missing value for --npm-spec");
70
+ }
71
+ options.npmSpec = value;
72
+ index += 1;
73
+ continue;
74
+ }
75
+ if (token === "--openclaw-bin") {
76
+ const value = argv[index + 1];
77
+ if (!value) {
78
+ throw new Error("Missing value for --openclaw-bin");
79
+ }
80
+ options.openclawBin = value;
81
+ index += 1;
82
+ continue;
83
+ }
84
+ throw new Error(`Unknown install option: ${token}`);
85
+ }
86
+
87
+ return options;
88
+ }
@@ -0,0 +1,66 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { readFileSync } from "node:fs";
4
+ import { spawnSync } from "node:child_process";
5
+ import path from "node:path";
6
+ import { fileURLToPath } from "node:url";
7
+
8
+ import { buildInstallPlan, parseInstallArgs } from "./install-lib.mjs";
9
+
10
+ const ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
11
+ const pkg = JSON.parse(readFileSync(path.join(ROOT, "package.json"), "utf8"));
12
+
13
+ function printUsage() {
14
+ console.log(`SecurityClaw installer
15
+
16
+ Usage:
17
+ securityclaw install [--dry-run] [--no-restart] [--no-status]
18
+ securityclaw install --archive <path-to-tgz>
19
+ securityclaw install --npm-spec <package@version>
20
+
21
+ Examples:
22
+ npx securityclaw install
23
+ npx securityclaw install --dry-run
24
+ `);
25
+ }
26
+
27
+ function runCommand(command, args, dryRun) {
28
+ const display = [command, ...args].map((part) => JSON.stringify(part)).join(" ");
29
+ console.log(display);
30
+ if (dryRun) {
31
+ return;
32
+ }
33
+
34
+ const result = spawnSync(command, args, {
35
+ cwd: ROOT,
36
+ stdio: "inherit",
37
+ });
38
+ if (result.status !== 0) {
39
+ process.exit(result.status ?? 1);
40
+ }
41
+ }
42
+
43
+ function main() {
44
+ const [command, ...rest] = process.argv.slice(2);
45
+ if (!command || command === "help" || command === "--help" || command === "-h") {
46
+ printUsage();
47
+ return;
48
+ }
49
+
50
+ if (command !== "install") {
51
+ console.error(`Unknown command: ${command}`);
52
+ printUsage();
53
+ process.exit(1);
54
+ }
55
+
56
+ const parsed = parseInstallArgs(rest);
57
+ const plan = buildInstallPlan({
58
+ packageName: pkg.name,
59
+ packageVersion: pkg.version,
60
+ ...parsed,
61
+ });
62
+
63
+ plan.forEach(([binary, ...args]) => runCommand(binary, args, parsed.dryRun));
64
+ }
65
+
66
+ main();
@@ -0,0 +1,520 @@
1
+ version: "1.0"
2
+ policy_version: "2026-03-17"
3
+ environment: "default"
4
+ defaults:
5
+ approval_ttl_seconds: 900
6
+ persist_mode: "compat"
7
+ hooks:
8
+ before_prompt_build:
9
+ enabled: true
10
+ timeout_ms: 40
11
+ fail_mode: "open"
12
+ before_tool_call:
13
+ enabled: true
14
+ timeout_ms: 50
15
+ fail_mode: "close"
16
+ after_tool_call:
17
+ enabled: true
18
+ timeout_ms: 50
19
+ fail_mode: "open"
20
+ tool_result_persist:
21
+ enabled: true
22
+ timeout_ms: 50
23
+ fail_mode: "close"
24
+ message_sending:
25
+ enabled: true
26
+ timeout_ms: 40
27
+ fail_mode: "open"
28
+ policies:
29
+ - rule_id: "high-risk-command-block"
30
+ group: "execution_control"
31
+ control_domain: "execution_control"
32
+ title: "高危命令模式默认拦截"
33
+ description: "阻断删除、权限递归修改、下载后执行、提权和停用系统审计等高危命令模式。"
34
+ severity: "critical"
35
+ owner: "security"
36
+ playbook_url: "https://docs.securityclaw.local/playbooks/high-risk-command"
37
+ enabled: true
38
+ priority: 320
39
+ decision: "block"
40
+ reason_codes:
41
+ - "HIGH_RISK_COMMAND_BLOCK"
42
+ match:
43
+ tool:
44
+ - "shell.exec"
45
+ tool_args_regex:
46
+ - '(^|\W)rm\s+-rf(\W|$)'
47
+ - '(^|\W)chmod\s+-R(\W|$)'
48
+ - '(curl|wget)\s+\S+\s*(\||&&)\s*(sh|bash)'
49
+ - '(^|\W)(sudo|doas|pkexec)\b'
50
+ - '(launchctl\s+unload|systemctl\s+(stop|disable))'
51
+
52
+ - rule_id: "untrusted-execution-challenge"
53
+ group: "execution_control"
54
+ control_domain: "execution_control"
55
+ title: "未受信输入驱动执行需审批"
56
+ description: "当未受信内容直接驱动执行类操作时,要求一次性、绑定 trace 的审批。"
57
+ severity: "high"
58
+ owner: "security"
59
+ playbook_url: "https://docs.securityclaw.local/playbooks/untrusted-execution"
60
+ enabled: true
61
+ priority: 300
62
+ decision: "challenge"
63
+ reason_codes:
64
+ - "UNTRUSTED_EXECUTION_REQUIRES_APPROVAL"
65
+ approval_requirements:
66
+ ticket_required: true
67
+ approver_roles:
68
+ - "secops"
69
+ - "security-lead"
70
+ single_use: true
71
+ trace_binding: "trace"
72
+ ttl_seconds: 600
73
+ match:
74
+ trust_level:
75
+ - "untrusted"
76
+ tool_group:
77
+ - "execution"
78
+
79
+ - rule_id: "workspace-outside-write-block"
80
+ group: "data_access"
81
+ control_domain: "data_access"
82
+ title: "工作区外或系统目录写入删除默认拦截"
83
+ description: "阻断对工作区外和系统目录的写入、删除或覆盖类操作。"
84
+ severity: "critical"
85
+ owner: "platform-security"
86
+ playbook_url: "https://docs.securityclaw.local/playbooks/outside-write"
87
+ enabled: true
88
+ priority: 280
89
+ decision: "block"
90
+ reason_codes:
91
+ - "OUTSIDE_WRITE_BLOCK"
92
+ match:
93
+ tool_group:
94
+ - "filesystem"
95
+ operation:
96
+ - "write"
97
+ - "delete"
98
+ resource_scope:
99
+ - "workspace_outside"
100
+ - "system"
101
+
102
+ - rule_id: "sensitive-directory-enumeration-challenge"
103
+ group: "data_access"
104
+ control_domain: "data_access"
105
+ title: "枚举敏感目录需审批"
106
+ description: "对凭据目录、个人内容目录、下载暂存区、浏览器资料目录和通信存储等高风险目录的枚举与搜索默认进入审批。"
107
+ severity: "high"
108
+ owner: "security"
109
+ playbook_url: "https://docs.securityclaw.local/playbooks/sensitive-enumeration"
110
+ enabled: true
111
+ priority: 250
112
+ decision: "challenge"
113
+ reason_codes:
114
+ - "SENSITIVE_DIRECTORY_ENUMERATION_REQUIRES_APPROVAL"
115
+ approval_requirements:
116
+ approver_roles:
117
+ - "secops"
118
+ ttl_seconds: 600
119
+ match:
120
+ tool_group:
121
+ - "filesystem"
122
+ operation:
123
+ - "list"
124
+ - "search"
125
+ asset_labels:
126
+ - "credential"
127
+ - "personal_content"
128
+ - "download_staging"
129
+ - "browser_profile"
130
+ - "browser_secret_store"
131
+ - "communication_store"
132
+
133
+ - rule_id: "credential-path-access-challenge"
134
+ group: "credential_protection"
135
+ control_domain: "credential_protection"
136
+ title: "敏感凭据路径访问需审批"
137
+ description: "读取凭据目录、环境变量文件、密钥材料和云访问凭据时默认要求审批。"
138
+ severity: "critical"
139
+ owner: "security"
140
+ playbook_url: "https://docs.securityclaw.local/playbooks/credential-path"
141
+ enabled: true
142
+ priority: 260
143
+ decision: "challenge"
144
+ reason_codes:
145
+ - "CREDENTIAL_PATH_ACCESS_REQUIRES_APPROVAL"
146
+ approval_requirements:
147
+ ticket_required: true
148
+ approver_roles:
149
+ - "secops"
150
+ ttl_seconds: 600
151
+ match:
152
+ tool_group:
153
+ - "filesystem"
154
+ operation:
155
+ - "read"
156
+ - "search"
157
+ - "list"
158
+ asset_labels:
159
+ - "credential"
160
+
161
+ - rule_id: "communication-store-access-challenge"
162
+ group: "data_access"
163
+ control_domain: "data_access"
164
+ title: "读取本地通信存储需审批"
165
+ description: "直接访问本地消息数据库、邮件存储和聊天历史目录时默认进入审批。"
166
+ severity: "high"
167
+ owner: "security"
168
+ playbook_url: "https://docs.securityclaw.local/playbooks/communication-store"
169
+ enabled: true
170
+ priority: 255
171
+ decision: "challenge"
172
+ reason_codes:
173
+ - "COMMUNICATION_STORE_ACCESS_REQUIRES_APPROVAL"
174
+ approval_requirements:
175
+ approver_roles:
176
+ - "secops"
177
+ ttl_seconds: 600
178
+ match:
179
+ tool_group:
180
+ - "filesystem"
181
+ operation:
182
+ - "read"
183
+ - "search"
184
+ - "list"
185
+ asset_labels:
186
+ - "communication_store"
187
+
188
+ - rule_id: "public-network-egress-challenge"
189
+ group: "data_egress"
190
+ control_domain: "data_egress"
191
+ title: "访问公网接口需审批"
192
+ description: "访问公网、未知域、个人网盘或 paste 类站点时,至少要求显式审批。"
193
+ severity: "high"
194
+ owner: "security"
195
+ playbook_url: "https://docs.securityclaw.local/playbooks/public-egress"
196
+ enabled: true
197
+ priority: 220
198
+ decision: "challenge"
199
+ reason_codes:
200
+ - "PUBLIC_EGRESS_REQUIRES_APPROVAL"
201
+ approval_requirements:
202
+ approver_roles:
203
+ - "secops"
204
+ ttl_seconds: 600
205
+ match:
206
+ tool_group:
207
+ - "network"
208
+ destination_type:
209
+ - "public"
210
+ - "personal_storage"
211
+ - "paste_service"
212
+
213
+ - rule_id: "sensitive-public-egress-block"
214
+ group: "data_egress"
215
+ control_domain: "data_egress"
216
+ title: "敏感数据向公网外发默认拦截"
217
+ description: "当请求命中客户、财务、PII、通信或密钥类数据标签时,禁止直接向公网外发。"
218
+ severity: "critical"
219
+ owner: "security"
220
+ playbook_url: "https://docs.securityclaw.local/playbooks/sensitive-egress"
221
+ enabled: true
222
+ priority: 310
223
+ decision: "block"
224
+ reason_codes:
225
+ - "SENSITIVE_PUBLIC_EGRESS_BLOCK"
226
+ match:
227
+ tool_group:
228
+ - "network"
229
+ destination_type:
230
+ - "public"
231
+ - "personal_storage"
232
+ - "paste_service"
233
+ data_labels:
234
+ - "secret"
235
+ - "pii"
236
+ - "customer_data"
237
+ - "financial"
238
+ - "communications"
239
+
240
+ - rule_id: "sensitive-archive-challenge"
241
+ group: "data_egress"
242
+ control_domain: "data_egress"
243
+ title: "敏感内容归档导出需审批"
244
+ description: "对客户数据、财务资料、密钥或媒体资料进行归档、压缩或导出时要求审批。"
245
+ severity: "high"
246
+ owner: "security"
247
+ playbook_url: "https://docs.securityclaw.local/playbooks/archive-export"
248
+ enabled: true
249
+ priority: 210
250
+ decision: "challenge"
251
+ reason_codes:
252
+ - "SENSITIVE_ARCHIVE_REQUIRES_APPROVAL"
253
+ approval_requirements:
254
+ approver_roles:
255
+ - "secops"
256
+ ttl_seconds: 600
257
+ match:
258
+ tool_group:
259
+ - "archive"
260
+ data_labels:
261
+ - "secret"
262
+ - "customer_data"
263
+ - "financial"
264
+ - "media"
265
+
266
+ - rule_id: "critical-control-plane-change-challenge"
267
+ group: "change_control"
268
+ control_domain: "change_control"
269
+ title: "关键控制面文件变更需审批"
270
+ description: "修改 CI/CD、部署、容器、Terraform、Kubernetes 或 IAM 相关文件时默认进入审批。"
271
+ severity: "critical"
272
+ owner: "platform-security"
273
+ playbook_url: "https://docs.securityclaw.local/playbooks/control-plane-change"
274
+ enabled: true
275
+ priority: 240
276
+ decision: "challenge"
277
+ reason_codes:
278
+ - "CONTROL_PLANE_CHANGE_REQUIRES_APPROVAL"
279
+ approval_requirements:
280
+ ticket_required: true
281
+ approver_roles:
282
+ - "platform-security"
283
+ ttl_seconds: 900
284
+ match:
285
+ operation:
286
+ - "write"
287
+ - "delete"
288
+ - "modify"
289
+ path_glob:
290
+ - "**/.github/workflows/**"
291
+ - "**/Dockerfile"
292
+ - "**/*.tf"
293
+ - "**/k8s/**"
294
+ - "**/manifests/**"
295
+ - "**/deploy/**"
296
+ - "**/*secret*.yaml"
297
+ - "**/*iam*"
298
+
299
+ - rule_id: "email-content-access-challenge"
300
+ group: "data_access"
301
+ control_domain: "data_access"
302
+ title: "读取邮箱正文或附件需审批"
303
+ description: "邮箱正文、附件、搜索结果和批量导出默认纳入审批流。"
304
+ severity: "high"
305
+ owner: "security"
306
+ playbook_url: "https://docs.securityclaw.local/playbooks/email-access"
307
+ enabled: true
308
+ priority: 180
309
+ decision: "challenge"
310
+ reason_codes:
311
+ - "EMAIL_CONTENT_ACCESS_REQUIRES_APPROVAL"
312
+ approval_requirements:
313
+ approver_roles:
314
+ - "secops"
315
+ ttl_seconds: 600
316
+ match:
317
+ tool_group:
318
+ - "email"
319
+ operation:
320
+ - "read"
321
+ - "search"
322
+ - "export"
323
+
324
+ - rule_id: "sms-content-access-challenge"
325
+ group: "data_access"
326
+ control_domain: "data_access"
327
+ title: "读取短信内容需审批"
328
+ description: "短信正文、会话历史、搜索结果和导出默认纳入审批流。"
329
+ severity: "high"
330
+ owner: "security"
331
+ playbook_url: "https://docs.securityclaw.local/playbooks/sms-access"
332
+ enabled: true
333
+ priority: 185
334
+ decision: "challenge"
335
+ reason_codes:
336
+ - "SMS_CONTENT_ACCESS_REQUIRES_APPROVAL"
337
+ approval_requirements:
338
+ approver_roles:
339
+ - "secops"
340
+ ttl_seconds: 600
341
+ match:
342
+ tool_group:
343
+ - "sms"
344
+ operation:
345
+ - "read"
346
+ - "search"
347
+ - "export"
348
+ - "list"
349
+
350
+ - rule_id: "sms-otp-block"
351
+ group: "credential_protection"
352
+ control_domain: "credential_protection"
353
+ title: "读取短信验证码或登录通知默认拦截"
354
+ description: "命中 OTP、验证码或登录提醒等短信内容时直接拦截。"
355
+ severity: "critical"
356
+ owner: "security"
357
+ playbook_url: "https://docs.securityclaw.local/playbooks/sms-otp"
358
+ enabled: true
359
+ priority: 305
360
+ decision: "block"
361
+ reason_codes:
362
+ - "SMS_OTP_ACCESS_BLOCK"
363
+ match:
364
+ tool_group:
365
+ - "sms"
366
+ data_labels:
367
+ - "otp"
368
+
369
+ - rule_id: "album-sensitive-read-challenge"
370
+ group: "data_access"
371
+ control_domain: "data_access"
372
+ title: "读取截图、扫描件或证件照片需审批"
373
+ description: "相册中的截图、录屏、扫描件、证件和 OCR 文本读取默认进入审批。"
374
+ severity: "high"
375
+ owner: "security"
376
+ playbook_url: "https://docs.securityclaw.local/playbooks/album-sensitive-read"
377
+ enabled: true
378
+ priority: 175
379
+ decision: "challenge"
380
+ reason_codes:
381
+ - "ALBUM_SENSITIVE_READ_REQUIRES_APPROVAL"
382
+ approval_requirements:
383
+ approver_roles:
384
+ - "secops"
385
+ ttl_seconds: 600
386
+ match:
387
+ tool_group:
388
+ - "album"
389
+ tool_args_summary:
390
+ - "screenshot"
391
+ - "screen recording"
392
+ - "scan"
393
+ - "ocr"
394
+ - "id card"
395
+ - "passport"
396
+ - "截图"
397
+ - "录屏"
398
+ - "扫描"
399
+ - "证件"
400
+ - "发票"
401
+ - "合同"
402
+
403
+ - rule_id: "browser-credential-block"
404
+ group: "credential_protection"
405
+ control_domain: "credential_protection"
406
+ title: "读取浏览器 Cookie、密码库或历史数据库默认拦截"
407
+ description: "浏览器凭据、Cookie、自动填充、历史与下载数据库等高敏内容读取默认阻断。"
408
+ severity: "critical"
409
+ owner: "security"
410
+ playbook_url: "https://docs.securityclaw.local/playbooks/browser-secret"
411
+ enabled: true
412
+ priority: 315
413
+ decision: "block"
414
+ reason_codes:
415
+ - "BROWSER_SECRET_ACCESS_BLOCK"
416
+ match:
417
+ tool_group:
418
+ - "browser"
419
+ - "filesystem"
420
+ operation:
421
+ - "read"
422
+ - "search"
423
+ - "list"
424
+ data_labels:
425
+ - "browser_secret"
426
+
427
+ - rule_id: "business-system-bulk-read-block"
428
+ group: "data_access"
429
+ control_domain: "data_access"
430
+ title: "业务系统批量读取默认拦截"
431
+ description: "CRM、ERP、HR、财务、工单与客服系统的批量读取或导出默认拦截。"
432
+ severity: "critical"
433
+ owner: "security"
434
+ playbook_url: "https://docs.securityclaw.local/playbooks/business-bulk-read"
435
+ enabled: true
436
+ priority: 290
437
+ decision: "block"
438
+ reason_codes:
439
+ - "BUSINESS_SYSTEM_BULK_READ_BLOCK"
440
+ match:
441
+ tool_group:
442
+ - "business"
443
+ operation:
444
+ - "read"
445
+ - "search"
446
+ - "export"
447
+ min_record_count: 50
448
+
449
+ - rule_id: "break-glass-exception-challenge"
450
+ group: "approval_exception"
451
+ control_domain: "approval_exception"
452
+ title: "Break-glass 例外放行需单次审批"
453
+ description: "显式请求 break-glass 或策略例外时,要求工单、审批人角色和单次 trace 绑定。"
454
+ severity: "critical"
455
+ owner: "security"
456
+ playbook_url: "https://docs.securityclaw.local/playbooks/break-glass"
457
+ enabled: true
458
+ priority: 330
459
+ decision: "challenge"
460
+ reason_codes:
461
+ - "BREAK_GLASS_REQUIRES_APPROVAL"
462
+ approval_requirements:
463
+ ticket_required: true
464
+ approver_roles:
465
+ - "secops"
466
+ - "security-lead"
467
+ single_use: true
468
+ trace_binding: "trace"
469
+ ttl_seconds: 300
470
+ match:
471
+ tags:
472
+ - "break_glass"
473
+ dlp:
474
+ on_dlp_hit: "sanitize"
475
+ patterns:
476
+ - name: "email"
477
+ type: "pii"
478
+ action: "mask"
479
+ regex: "[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,}"
480
+ flags: "ig"
481
+ - name: "api-key"
482
+ type: "secret"
483
+ action: "mask"
484
+ regex: "sk-[A-Za-z0-9]{10,}"
485
+ - name: "access-key"
486
+ type: "credential"
487
+ action: "mask"
488
+ regex: "AKIA[0-9A-Z]{16}"
489
+ - name: "bearer-token"
490
+ type: "token"
491
+ action: "remove"
492
+ regex: "Bearer\\s+[A-Za-z0-9._-]{12,}"
493
+ - name: "jwt"
494
+ type: "token"
495
+ action: "remove"
496
+ regex: "eyJ[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+"
497
+ - name: "private-key"
498
+ type: "credential"
499
+ action: "remove"
500
+ regex: "-----BEGIN(?: RSA| EC| OPENSSH| DSA)? PRIVATE KEY-----"
501
+ - name: "cookie-session"
502
+ type: "credential"
503
+ action: "mask"
504
+ regex: "(session(id)?|cookie)=[A-Za-z0-9._%+-]{12,}"
505
+ flags: "ig"
506
+ - name: "connection-string"
507
+ type: "credential"
508
+ action: "remove"
509
+ regex: "(postgres(ql)?|mysql|mongodb|redis|amqp):\\/\\/[^\\s\"']+"
510
+ flags: "ig"
511
+ - name: "internal-url"
512
+ type: "credential"
513
+ action: "mask"
514
+ regex: "https?:\\/\\/[A-Za-z0-9.-]+\\.(internal|corp|local)(:[0-9]+)?[^\\s\"']*"
515
+ flags: "ig"
516
+ event_sink:
517
+ webhook_url: ""
518
+ timeout_ms: 3000
519
+ max_buffer: 100
520
+ retry_limit: 3