@denial-web/clawguard 0.1.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 (83) hide show
  1. package/.clawguard.example.json +16 -0
  2. package/LICENSE +21 -0
  3. package/README.md +241 -0
  4. package/SECURITY.md +33 -0
  5. package/action.yml +72 -0
  6. package/docs/ARCHITECTURE.md +312 -0
  7. package/docs/ARCHITECTURE_ROADMAP.md +267 -0
  8. package/docs/CLAWHUB_METADATA.md +57 -0
  9. package/docs/DEMO_CAPTURE.md +25 -0
  10. package/docs/DEMO_SCRIPT.md +87 -0
  11. package/docs/DEPENDENCY_SCANNING.md +61 -0
  12. package/docs/GITHUB_ACTION.md +56 -0
  13. package/docs/GITHUB_REPO_SETUP.md +76 -0
  14. package/docs/HTML_REPORTS.md +27 -0
  15. package/docs/INTEGRATION_SPEC.md +253 -0
  16. package/docs/LAUNCH_CHECKLIST.md +64 -0
  17. package/docs/LAUNCH_PLAN.md +40 -0
  18. package/docs/LOCAL_PROJECT_ASSETS.md +250 -0
  19. package/docs/MCP_PLUGIN_SCANNING.md +53 -0
  20. package/docs/NEXT_SESSION.md +110 -0
  21. package/docs/NPM_PUBLISHING.md +66 -0
  22. package/docs/OPENCLAW_CLAWHUB_RESEARCH.md +128 -0
  23. package/docs/POLICY_MODEL.md +198 -0
  24. package/docs/PROJECT_REVIEW.md +108 -0
  25. package/docs/REAL_WORLD_VALIDATION.md +57 -0
  26. package/docs/RELEASE_NOTES_v0.1.0.md +52 -0
  27. package/docs/REPORT_SCHEMA.md +81 -0
  28. package/docs/RULES.md +92 -0
  29. package/docs/THREAT_MODEL.md +50 -0
  30. package/docs/WEB_DEMO.md +39 -0
  31. package/docs/WORKSPACE_SCANNING.md +41 -0
  32. package/examples/clawhub-origin-without-lock/skills/orphan-helper/.clawhub/origin.json +6 -0
  33. package/examples/clawhub-origin-without-lock/skills/orphan-helper/SKILL.md +11 -0
  34. package/examples/clawhub-workspace/.clawhub/lock.json +22 -0
  35. package/examples/clawhub-workspace/skills/drift-helper/.clawhub/origin.json +6 -0
  36. package/examples/clawhub-workspace/skills/drift-helper/SKILL.md +11 -0
  37. package/examples/clawhub-workspace/skills/missing-origin/SKILL.md +11 -0
  38. package/examples/clawhub-workspace/skills/weather-helper/.clawhub/origin.json +6 -0
  39. package/examples/clawhub-workspace/skills/weather-helper/SKILL.md +15 -0
  40. package/examples/declared-api-skill/SKILL.md +27 -0
  41. package/examples/dependency-python-skill/SKILL.md +16 -0
  42. package/examples/dependency-python-skill/pyproject.toml +5 -0
  43. package/examples/dependency-python-skill/requirements.txt +3 -0
  44. package/examples/dependency-risky-skill/SKILL.md +16 -0
  45. package/examples/dependency-risky-skill/package.json +12 -0
  46. package/examples/dependency-safe-skill/SKILL.md +16 -0
  47. package/examples/dependency-safe-skill/package-lock.json +19 -0
  48. package/examples/dependency-safe-skill/package.json +7 -0
  49. package/examples/metadata-mismatch-skill/SKILL.md +22 -0
  50. package/examples/openclaw-plugin-config/.openclaw/plugins.json +18 -0
  51. package/examples/openclaw-workspace/.agents/skills/research-helper/SKILL.md +11 -0
  52. package/examples/openclaw-workspace/skills/notes/SKILL.md +3 -0
  53. package/examples/openclaw-workspace/skills/research-helper/SKILL.md +17 -0
  54. package/examples/risky-mcp-config/.cursor/mcp.json +29 -0
  55. package/examples/risky-openclaw-plugin/openclaw.plugin.json +6 -0
  56. package/examples/risky-openclaw-plugin/package.json +7 -0
  57. package/examples/risky-openclaw-plugin/src/index.ts +1 -0
  58. package/examples/risky-skill/SKILL.md +17 -0
  59. package/examples/safe-mcp-config/.cursor/mcp.json +15 -0
  60. package/examples/safe-openclaw-plugin/dist/index.js +1 -0
  61. package/examples/safe-openclaw-plugin/openclaw.plugin.json +5 -0
  62. package/examples/safe-openclaw-plugin/package.json +14 -0
  63. package/examples/safe-skill/SKILL.md +12 -0
  64. package/package.json +49 -0
  65. package/schemas/clawguard-report.schema.json +266 -0
  66. package/scripts/capture-demo.js +206 -0
  67. package/src/clawhub.js +383 -0
  68. package/src/cli.js +296 -0
  69. package/src/config.js +205 -0
  70. package/src/dependencies.js +417 -0
  71. package/src/mcp-config.js +592 -0
  72. package/src/policy.js +165 -0
  73. package/src/reporters/html.js +482 -0
  74. package/src/reporters/sarif.js +121 -0
  75. package/src/rule-catalog.js +400 -0
  76. package/src/rules.js +121 -0
  77. package/src/scanner.js +387 -0
  78. package/src/skill-metadata.js +516 -0
  79. package/src/web-server.js +395 -0
  80. package/src/workspace.js +233 -0
  81. package/web/app.js +374 -0
  82. package/web/index.html +119 -0
  83. package/web/styles.css +453 -0
package/web/styles.css ADDED
@@ -0,0 +1,453 @@
1
+ :root {
2
+ color-scheme: light;
3
+ --bg: #f6f3ec;
4
+ --ink: #20242a;
5
+ --muted: #69717a;
6
+ --panel: #ffffff;
7
+ --line: #d9ddd4;
8
+ --field: #fbfaf7;
9
+ --green: #28724f;
10
+ --amber: #946300;
11
+ --orange: #b94f1d;
12
+ --red: #9f2424;
13
+ --blue: #315f88;
14
+ --shadow: 0 22px 70px rgba(32, 36, 42, 0.12);
15
+ }
16
+
17
+ * {
18
+ box-sizing: border-box;
19
+ }
20
+
21
+ body {
22
+ margin: 0;
23
+ min-height: 100vh;
24
+ background:
25
+ linear-gradient(135deg, rgba(40, 114, 79, 0.08), transparent 34%),
26
+ linear-gradient(315deg, rgba(185, 79, 29, 0.08), transparent 32%),
27
+ var(--bg);
28
+ color: var(--ink);
29
+ font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
30
+ }
31
+
32
+ button, select, textarea {
33
+ font: inherit;
34
+ }
35
+
36
+ button, select {
37
+ min-height: 40px;
38
+ }
39
+
40
+ button {
41
+ border: 0;
42
+ border-radius: 8px;
43
+ background: var(--ink);
44
+ color: #fff;
45
+ padding: 0 14px;
46
+ font-weight: 700;
47
+ cursor: pointer;
48
+ }
49
+
50
+ button:hover {
51
+ filter: brightness(1.08);
52
+ }
53
+
54
+ button:disabled {
55
+ cursor: not-allowed;
56
+ opacity: 0.5;
57
+ }
58
+
59
+ button.ghost {
60
+ background: transparent;
61
+ border: 1px solid var(--line);
62
+ color: var(--ink);
63
+ }
64
+
65
+ .shell {
66
+ width: min(1380px, calc(100vw - 28px));
67
+ margin: 0 auto;
68
+ padding: 20px 0;
69
+ }
70
+
71
+ .workbench {
72
+ min-height: calc(100vh - 40px);
73
+ display: grid;
74
+ grid-template-columns: minmax(320px, 430px) minmax(0, 1fr);
75
+ border: 1px solid var(--line);
76
+ background: rgba(255, 255, 255, 0.74);
77
+ box-shadow: var(--shadow);
78
+ }
79
+
80
+ .input-pane, .result-pane {
81
+ padding: 22px;
82
+ }
83
+
84
+ .input-pane {
85
+ border-right: 1px solid var(--line);
86
+ background: rgba(255, 255, 255, 0.66);
87
+ display: flex;
88
+ flex-direction: column;
89
+ gap: 18px;
90
+ }
91
+
92
+ .brand-row {
93
+ display: flex;
94
+ gap: 12px;
95
+ align-items: center;
96
+ }
97
+
98
+ .mark {
99
+ width: 48px;
100
+ height: 48px;
101
+ display: grid;
102
+ place-items: center;
103
+ border-radius: 8px;
104
+ background: var(--ink);
105
+ color: #fff;
106
+ font-weight: 900;
107
+ letter-spacing: 0;
108
+ }
109
+
110
+ h1, h2, h3, p {
111
+ margin: 0;
112
+ }
113
+
114
+ h1 {
115
+ font-size: 25px;
116
+ line-height: 1;
117
+ }
118
+
119
+ h2 {
120
+ font-size: 16px;
121
+ }
122
+
123
+ .brand-row p, .eyebrow, label, .example-card p, #reason {
124
+ color: var(--muted);
125
+ }
126
+
127
+ .eyebrow, label {
128
+ font-size: 12px;
129
+ font-weight: 800;
130
+ text-transform: uppercase;
131
+ }
132
+
133
+ .control-row {
134
+ display: grid;
135
+ gap: 7px;
136
+ }
137
+
138
+ select, textarea {
139
+ width: 100%;
140
+ border: 1px solid var(--line);
141
+ border-radius: 8px;
142
+ background: var(--field);
143
+ color: var(--ink);
144
+ }
145
+
146
+ select {
147
+ padding: 0 10px;
148
+ }
149
+
150
+ .editor-head, .actions, .section-head, .status-strip, .report-actions {
151
+ display: flex;
152
+ align-items: center;
153
+ justify-content: space-between;
154
+ gap: 12px;
155
+ }
156
+
157
+ textarea {
158
+ min-height: 280px;
159
+ resize: vertical;
160
+ padding: 14px;
161
+ font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
162
+ font-size: 13px;
163
+ line-height: 1.5;
164
+ }
165
+
166
+ .actions {
167
+ justify-content: flex-start;
168
+ }
169
+
170
+ .report-actions {
171
+ justify-content: flex-end;
172
+ flex-wrap: wrap;
173
+ }
174
+
175
+ .folder-box {
176
+ display: grid;
177
+ gap: 10px;
178
+ border: 1px solid var(--line);
179
+ border-radius: 8px;
180
+ background: var(--panel);
181
+ padding: 12px;
182
+ }
183
+
184
+ .folder-box p {
185
+ margin-top: 4px;
186
+ color: var(--muted);
187
+ font-size: 13px;
188
+ }
189
+
190
+ input[type="file"] {
191
+ width: 100%;
192
+ min-height: 40px;
193
+ border: 1px dashed var(--line);
194
+ border-radius: 8px;
195
+ background: var(--field);
196
+ padding: 9px;
197
+ color: var(--muted);
198
+ }
199
+
200
+ .examples {
201
+ display: grid;
202
+ gap: 8px;
203
+ margin-top: 10px;
204
+ }
205
+
206
+ .example-card {
207
+ width: 100%;
208
+ min-height: auto;
209
+ text-align: left;
210
+ display: block;
211
+ border: 1px solid var(--line);
212
+ border-radius: 8px;
213
+ background: var(--panel);
214
+ color: var(--ink);
215
+ padding: 11px;
216
+ }
217
+
218
+ .example-card strong {
219
+ display: block;
220
+ font-size: 14px;
221
+ }
222
+
223
+ .example-card p {
224
+ margin-top: 3px;
225
+ font-size: 12px;
226
+ line-height: 1.35;
227
+ }
228
+
229
+ .result-pane {
230
+ display: grid;
231
+ align-content: start;
232
+ gap: 16px;
233
+ }
234
+
235
+ .status-strip {
236
+ min-height: 58px;
237
+ }
238
+
239
+ #target-name {
240
+ margin-top: 4px;
241
+ overflow-wrap: anywhere;
242
+ }
243
+
244
+ .pill, .tag, .severity {
245
+ display: inline-flex;
246
+ align-items: center;
247
+ min-height: 26px;
248
+ border-radius: 8px;
249
+ padding: 4px 8px;
250
+ font-size: 12px;
251
+ font-weight: 800;
252
+ text-transform: uppercase;
253
+ }
254
+
255
+ .pill {
256
+ background: #e9eee8;
257
+ color: var(--blue);
258
+ }
259
+
260
+ .score-panel {
261
+ display: grid;
262
+ grid-template-columns: 170px minmax(0, 1fr);
263
+ gap: 16px;
264
+ align-items: stretch;
265
+ }
266
+
267
+ .score-ring, .decision, .metrics div, .metadata-grid div, .finding-card, .empty-state {
268
+ border: 1px solid var(--line);
269
+ border-radius: 8px;
270
+ background: var(--panel);
271
+ }
272
+
273
+ .score-ring {
274
+ min-height: 170px;
275
+ display: grid;
276
+ place-items: center;
277
+ align-content: center;
278
+ border-width: 8px;
279
+ border-color: var(--blue);
280
+ }
281
+
282
+ .score-ring strong {
283
+ display: block;
284
+ font-size: 54px;
285
+ line-height: 1;
286
+ }
287
+
288
+ .score-ring span {
289
+ margin-top: 6px;
290
+ font-size: 13px;
291
+ font-weight: 900;
292
+ text-transform: uppercase;
293
+ }
294
+
295
+ .decision {
296
+ padding: 18px;
297
+ }
298
+
299
+ .decision h3 {
300
+ margin: 6px 0 8px;
301
+ font-size: 30px;
302
+ text-transform: uppercase;
303
+ }
304
+
305
+ .action-tags {
306
+ display: flex;
307
+ flex-wrap: wrap;
308
+ gap: 6px;
309
+ margin-top: 12px;
310
+ }
311
+
312
+ .tag {
313
+ background: #edf1ea;
314
+ color: var(--ink);
315
+ }
316
+
317
+ .metrics, .metadata-grid {
318
+ display: grid;
319
+ gap: 10px;
320
+ }
321
+
322
+ .metrics {
323
+ grid-template-columns: repeat(4, minmax(0, 1fr));
324
+ }
325
+
326
+ .metadata-grid {
327
+ grid-template-columns: repeat(4, minmax(0, 1fr));
328
+ }
329
+
330
+ .metrics div, .metadata-grid div {
331
+ padding: 13px;
332
+ }
333
+
334
+ .metrics span, .metadata-grid span {
335
+ display: block;
336
+ color: var(--muted);
337
+ font-size: 12px;
338
+ font-weight: 800;
339
+ text-transform: uppercase;
340
+ }
341
+
342
+ .metrics strong, .metadata-grid strong {
343
+ display: block;
344
+ margin-top: 4px;
345
+ font-size: 25px;
346
+ }
347
+
348
+ .findings {
349
+ display: grid;
350
+ gap: 10px;
351
+ margin-top: 10px;
352
+ }
353
+
354
+ .empty-state {
355
+ padding: 18px;
356
+ color: var(--muted);
357
+ }
358
+
359
+ .finding-card {
360
+ padding: 14px;
361
+ }
362
+
363
+ .finding-top {
364
+ display: flex;
365
+ justify-content: space-between;
366
+ align-items: flex-start;
367
+ gap: 12px;
368
+ }
369
+
370
+ .finding-card h3 {
371
+ font-size: 15px;
372
+ }
373
+
374
+ .location, .evidence, .recommendation {
375
+ margin-top: 8px;
376
+ font-size: 13px;
377
+ }
378
+
379
+ .location {
380
+ color: var(--muted);
381
+ font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
382
+ overflow-wrap: anywhere;
383
+ }
384
+
385
+ .evidence {
386
+ padding: 10px;
387
+ border: 1px solid var(--line);
388
+ border-radius: 8px;
389
+ background: var(--field);
390
+ font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
391
+ overflow-wrap: anywhere;
392
+ white-space: pre-wrap;
393
+ }
394
+
395
+ .recommendation {
396
+ color: var(--muted);
397
+ }
398
+
399
+ .severity.critical, .level-critical .score-ring {
400
+ border-color: var(--red);
401
+ color: var(--red);
402
+ }
403
+
404
+ .severity.high, .level-high .score-ring {
405
+ border-color: var(--orange);
406
+ color: var(--orange);
407
+ }
408
+
409
+ .severity.medium, .level-medium .score-ring {
410
+ border-color: var(--amber);
411
+ color: var(--amber);
412
+ }
413
+
414
+ .severity.low, .level-low .score-ring {
415
+ border-color: var(--green);
416
+ color: var(--green);
417
+ }
418
+
419
+ .severity.info, .level-info .score-ring {
420
+ border-color: var(--blue);
421
+ color: var(--blue);
422
+ }
423
+
424
+ @media (max-width: 900px) {
425
+ .workbench, .score-panel {
426
+ grid-template-columns: 1fr;
427
+ }
428
+
429
+ .input-pane {
430
+ border-right: 0;
431
+ border-bottom: 1px solid var(--line);
432
+ }
433
+
434
+ .metrics, .metadata-grid {
435
+ grid-template-columns: repeat(2, minmax(0, 1fr));
436
+ }
437
+ }
438
+
439
+ @media (max-width: 560px) {
440
+ .shell {
441
+ width: min(100vw - 16px, 1380px);
442
+ padding: 8px 0;
443
+ }
444
+
445
+ .input-pane, .result-pane {
446
+ padding: 14px;
447
+ }
448
+
449
+ .editor-head, .actions, .section-head, .status-strip {
450
+ align-items: stretch;
451
+ flex-direction: column;
452
+ }
453
+ }