kekkai-cli 1.0.5__py3-none-any.whl → 1.1.1__py3-none-any.whl

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 (53) hide show
  1. kekkai/cli.py +789 -19
  2. kekkai/compliance/__init__.py +68 -0
  3. kekkai/compliance/hipaa.py +235 -0
  4. kekkai/compliance/mappings.py +136 -0
  5. kekkai/compliance/owasp.py +517 -0
  6. kekkai/compliance/owasp_agentic.py +267 -0
  7. kekkai/compliance/pci_dss.py +205 -0
  8. kekkai/compliance/soc2.py +209 -0
  9. kekkai/dojo.py +91 -14
  10. kekkai/dojo_import.py +9 -1
  11. kekkai/fix/__init__.py +47 -0
  12. kekkai/fix/audit.py +278 -0
  13. kekkai/fix/differ.py +427 -0
  14. kekkai/fix/engine.py +500 -0
  15. kekkai/fix/prompts.py +251 -0
  16. kekkai/output.py +10 -12
  17. kekkai/report/__init__.py +41 -0
  18. kekkai/report/compliance_matrix.py +98 -0
  19. kekkai/report/generator.py +365 -0
  20. kekkai/report/html.py +69 -0
  21. kekkai/report/pdf.py +63 -0
  22. kekkai/report/unified.py +226 -0
  23. kekkai/scanners/container.py +33 -3
  24. kekkai/scanners/gitleaks.py +3 -1
  25. kekkai/scanners/semgrep.py +1 -1
  26. kekkai/scanners/trivy.py +1 -1
  27. kekkai/threatflow/model_adapter.py +143 -1
  28. kekkai/triage/__init__.py +54 -1
  29. kekkai/triage/loader.py +196 -0
  30. kekkai_cli-1.1.1.dist-info/METADATA +379 -0
  31. {kekkai_cli-1.0.5.dist-info → kekkai_cli-1.1.1.dist-info}/RECORD +34 -33
  32. {kekkai_cli-1.0.5.dist-info → kekkai_cli-1.1.1.dist-info}/entry_points.txt +0 -1
  33. {kekkai_cli-1.0.5.dist-info → kekkai_cli-1.1.1.dist-info}/top_level.txt +0 -1
  34. kekkai_cli-1.0.5.dist-info/METADATA +0 -135
  35. portal/__init__.py +0 -19
  36. portal/api.py +0 -155
  37. portal/auth.py +0 -103
  38. portal/enterprise/__init__.py +0 -32
  39. portal/enterprise/audit.py +0 -435
  40. portal/enterprise/licensing.py +0 -342
  41. portal/enterprise/rbac.py +0 -276
  42. portal/enterprise/saml.py +0 -595
  43. portal/ops/__init__.py +0 -53
  44. portal/ops/backup.py +0 -553
  45. portal/ops/log_shipper.py +0 -469
  46. portal/ops/monitoring.py +0 -517
  47. portal/ops/restore.py +0 -469
  48. portal/ops/secrets.py +0 -408
  49. portal/ops/upgrade.py +0 -591
  50. portal/tenants.py +0 -340
  51. portal/uploads.py +0 -259
  52. portal/web.py +0 -384
  53. {kekkai_cli-1.0.5.dist-info → kekkai_cli-1.1.1.dist-info}/WHEEL +0 -0
@@ -0,0 +1,517 @@
1
+ """OWASP Top 10 2025 mapping for security findings.
2
+
3
+ Maps findings to OWASP Top 10 2025 categories based on CWE IDs and rule patterns.
4
+ Reference: https://owasp.org/Top10/2025/
5
+
6
+ Changes from 2021:
7
+ - A01:2025 Broken Access Control (now includes SSRF)
8
+ - A02:2025 Security Misconfiguration (moved up from #5)
9
+ - A03:2025 Software Supply Chain Failures (NEW - replaces Vulnerable Components)
10
+ - A04:2025 Cryptographic Failures (moved down from #2)
11
+ - A05:2025 Injection (moved down from #3)
12
+ - A06:2025 Insecure Design (moved down from #4)
13
+ - A07:2025 Authentication Failures (renamed)
14
+ - A08:2025 Software or Data Integrity Failures (stable)
15
+ - A09:2025 Security Logging and Alerting Failures (minor rename)
16
+ - A10:2025 Mishandling of Exceptional Conditions (NEW)
17
+ """
18
+
19
+ from __future__ import annotations
20
+
21
+ from dataclasses import dataclass
22
+ from typing import TYPE_CHECKING
23
+
24
+ from .mappings import FrameworkControl
25
+
26
+ if TYPE_CHECKING:
27
+ from kekkai.scanners.base import Finding
28
+
29
+
30
+ @dataclass(frozen=True)
31
+ class OWASPCategory:
32
+ """OWASP Top 10 category definition."""
33
+
34
+ id: str
35
+ name: str
36
+ description: str
37
+ cwes: frozenset[int]
38
+ rule_patterns: tuple[str, ...]
39
+
40
+
41
+ # OWASP Top 10 2025 Categories with CWE mappings
42
+ OWASP_TOP_10: dict[str, OWASPCategory] = {
43
+ "A01": OWASPCategory(
44
+ id="A01:2025",
45
+ name="Broken Access Control",
46
+ description=(
47
+ "Restrictions on authenticated users are not properly enforced. "
48
+ "Now includes SSRF vulnerabilities."
49
+ ),
50
+ cwes=frozenset(
51
+ {
52
+ 22,
53
+ 23,
54
+ 35,
55
+ 59, # Path traversal
56
+ 200,
57
+ 201,
58
+ 219, # Information exposure
59
+ 264,
60
+ 275,
61
+ 276,
62
+ 284,
63
+ 285, # Permissions
64
+ 352, # CSRF
65
+ 359,
66
+ 377,
67
+ 402,
68
+ 425,
69
+ 441,
70
+ 497,
71
+ 538,
72
+ 540,
73
+ 548,
74
+ 552,
75
+ 566,
76
+ 601, # Open redirect
77
+ 639,
78
+ 651,
79
+ 668,
80
+ 706,
81
+ 862,
82
+ 863, # Missing authorization
83
+ 913,
84
+ 918, # SSRF (moved from A10:2021)
85
+ 922,
86
+ 1275,
87
+ }
88
+ ),
89
+ rule_patterns=(
90
+ "access-control",
91
+ "authorization",
92
+ "idor",
93
+ "path-traversal",
94
+ "directory-traversal",
95
+ "ssrf",
96
+ "server-side-request",
97
+ "open-redirect",
98
+ ),
99
+ ),
100
+ "A02": OWASPCategory(
101
+ id="A02:2025",
102
+ name="Security Misconfiguration",
103
+ description=(
104
+ "Missing security hardening or improperly configured permissions. "
105
+ "Moved up from #5 in 2021."
106
+ ),
107
+ cwes=frozenset(
108
+ {
109
+ 2,
110
+ 11,
111
+ 13,
112
+ 15,
113
+ 16,
114
+ 260,
115
+ 315,
116
+ 520,
117
+ 526,
118
+ 537,
119
+ 541,
120
+ 547,
121
+ 611, # XXE
122
+ 614,
123
+ 756,
124
+ 776,
125
+ 942,
126
+ 1004,
127
+ 1032,
128
+ 1174,
129
+ }
130
+ ),
131
+ rule_patterns=(
132
+ "misconfiguration",
133
+ "config",
134
+ "default",
135
+ "debug",
136
+ "verbose",
137
+ "hardcoded",
138
+ "xxe",
139
+ ),
140
+ ),
141
+ "A03": OWASPCategory(
142
+ id="A03:2025",
143
+ name="Software Supply Chain Failures",
144
+ description=(
145
+ "Vulnerabilities in software dependencies, build systems, and "
146
+ "distribution infrastructure. Replaces Vulnerable Components from 2021."
147
+ ),
148
+ cwes=frozenset(
149
+ {
150
+ 426, # Untrusted search path
151
+ 494, # Download without integrity check
152
+ 506, # Embedded malicious code
153
+ 829, # Inclusion of untrusted functionality
154
+ 937, # Using components with known vulnerabilities
155
+ 1035, # Reliance on reverse DNS
156
+ 1104, # Use of unmaintained third-party components
157
+ }
158
+ ),
159
+ rule_patterns=(
160
+ "supply-chain",
161
+ "dependency",
162
+ "component",
163
+ "outdated",
164
+ "cve-",
165
+ "vulnerability",
166
+ "sbom",
167
+ "third-party",
168
+ ),
169
+ ),
170
+ "A04": OWASPCategory(
171
+ id="A04:2025",
172
+ name="Cryptographic Failures",
173
+ description=(
174
+ "Failures related to cryptography leading to sensitive data exposure. "
175
+ "Moved down from #2 in 2021."
176
+ ),
177
+ cwes=frozenset(
178
+ {
179
+ 261,
180
+ 296,
181
+ 310,
182
+ 319, # Cleartext transmission
183
+ 320,
184
+ 321,
185
+ 322,
186
+ 323,
187
+ 324,
188
+ 325,
189
+ 326,
190
+ 327,
191
+ 328,
192
+ 329, # Weak crypto
193
+ 330,
194
+ 331,
195
+ 335,
196
+ 336,
197
+ 337,
198
+ 338,
199
+ 339,
200
+ 340,
201
+ 347,
202
+ 523,
203
+ 720,
204
+ 757,
205
+ 759,
206
+ 760,
207
+ 780,
208
+ 818,
209
+ 916,
210
+ }
211
+ ),
212
+ rule_patterns=(
213
+ "crypto",
214
+ "encryption",
215
+ "hash",
216
+ "ssl",
217
+ "tls",
218
+ "certificate",
219
+ "weak-crypto",
220
+ "cleartext",
221
+ ),
222
+ ),
223
+ "A05": OWASPCategory(
224
+ id="A05:2025",
225
+ name="Injection",
226
+ description=(
227
+ "User-supplied data is not validated, filtered, or sanitized. "
228
+ "Moved down from #3 in 2021."
229
+ ),
230
+ cwes=frozenset(
231
+ {
232
+ 20, # Improper input validation
233
+ 74,
234
+ 75,
235
+ 77,
236
+ 78,
237
+ 79,
238
+ 80,
239
+ 83,
240
+ 87,
241
+ 88,
242
+ 89, # SQL injection
243
+ 90,
244
+ 91,
245
+ 93,
246
+ 94,
247
+ 95,
248
+ 96,
249
+ 97,
250
+ 98,
251
+ 99,
252
+ 100,
253
+ 113,
254
+ 116,
255
+ 138,
256
+ 184,
257
+ 470,
258
+ 471,
259
+ 564,
260
+ 610,
261
+ 643,
262
+ 644,
263
+ 652,
264
+ 917,
265
+ }
266
+ ),
267
+ rule_patterns=(
268
+ "injection",
269
+ "sqli",
270
+ "xss",
271
+ "command-injection",
272
+ "os-command",
273
+ "ldap",
274
+ "xpath",
275
+ "nosql",
276
+ "template-injection",
277
+ ),
278
+ ),
279
+ "A06": OWASPCategory(
280
+ id="A06:2025",
281
+ name="Insecure Design",
282
+ description=("Missing or ineffective control design. Moved down from #4 in 2021."),
283
+ cwes=frozenset(
284
+ {
285
+ 73,
286
+ 183,
287
+ 209,
288
+ 213,
289
+ 235,
290
+ 256,
291
+ 257,
292
+ 266,
293
+ 269,
294
+ 280,
295
+ 311,
296
+ 312,
297
+ 313,
298
+ 316,
299
+ 419,
300
+ 430,
301
+ 434,
302
+ 444,
303
+ 451,
304
+ 472,
305
+ 501,
306
+ 522,
307
+ 525,
308
+ 539,
309
+ 579,
310
+ 598,
311
+ 602,
312
+ 642,
313
+ 646,
314
+ 650,
315
+ 653,
316
+ 656,
317
+ 657,
318
+ 799,
319
+ 807,
320
+ 840,
321
+ 841,
322
+ 927,
323
+ 1021,
324
+ 1173,
325
+ }
326
+ ),
327
+ rule_patterns=(
328
+ "insecure-design",
329
+ "business-logic",
330
+ "threat-model",
331
+ "race-condition",
332
+ ),
333
+ ),
334
+ "A07": OWASPCategory(
335
+ id="A07:2025",
336
+ name="Authentication Failures",
337
+ description=(
338
+ "Functions related to authentication and session management "
339
+ "are incorrectly implemented. Renamed from 'Identification and "
340
+ "Authentication Failures'."
341
+ ),
342
+ cwes=frozenset(
343
+ {
344
+ 255,
345
+ 259,
346
+ 287,
347
+ 288,
348
+ 290,
349
+ 294,
350
+ 295,
351
+ 297,
352
+ 300,
353
+ 302,
354
+ 304,
355
+ 306,
356
+ 307,
357
+ 346,
358
+ 384,
359
+ 521, # Weak password
360
+ 613, # Session expiration
361
+ 620,
362
+ 640,
363
+ 798, # Hardcoded credentials
364
+ 940,
365
+ 1216,
366
+ }
367
+ ),
368
+ rule_patterns=(
369
+ "authentication",
370
+ "auth",
371
+ "session",
372
+ "password",
373
+ "credential",
374
+ "login",
375
+ "jwt",
376
+ "mfa",
377
+ "2fa",
378
+ ),
379
+ ),
380
+ "A08": OWASPCategory(
381
+ id="A08:2025",
382
+ name="Software or Data Integrity Failures",
383
+ description=("Code and infrastructure that does not protect against integrity violations."),
384
+ cwes=frozenset(
385
+ {
386
+ 345, # Insufficient verification
387
+ 353,
388
+ 426,
389
+ 494,
390
+ 502, # Deserialization
391
+ 565,
392
+ 784,
393
+ 829,
394
+ 830,
395
+ 913,
396
+ 915,
397
+ }
398
+ ),
399
+ rule_patterns=(
400
+ "deserialization",
401
+ "integrity",
402
+ "signature",
403
+ "ci-cd",
404
+ "update",
405
+ "tampering",
406
+ ),
407
+ ),
408
+ "A09": OWASPCategory(
409
+ id="A09:2025",
410
+ name="Security Logging and Alerting Failures",
411
+ description=(
412
+ "Insufficient logging, detection, monitoring, and active response. "
413
+ "Minor rename to include 'Alerting'."
414
+ ),
415
+ cwes=frozenset(
416
+ {
417
+ 117, # Log injection
418
+ 223, # Omission of security info
419
+ 532, # Info exposure through logs
420
+ 778,
421
+ 779, # Insufficient logging
422
+ }
423
+ ),
424
+ rule_patterns=(
425
+ "logging",
426
+ "monitoring",
427
+ "audit",
428
+ "log-injection",
429
+ "alerting",
430
+ ),
431
+ ),
432
+ "A10": OWASPCategory(
433
+ id="A10:2025",
434
+ name="Mishandling of Exceptional Conditions",
435
+ description=(
436
+ "Improper handling of errors, exceptions, and unexpected inputs. NEW category in 2025."
437
+ ),
438
+ cwes=frozenset(
439
+ {
440
+ 248, # Uncaught exception
441
+ 252,
442
+ 253, # Unchecked return value
443
+ 390,
444
+ 391, # Detection of error condition
445
+ 392, # Missing report of error
446
+ 397, # Throwing generic exception
447
+ 754, # Improper check for unusual conditions
448
+ 755, # Improper handling of exceptional conditions
449
+ 756, # Missing custom error page
450
+ 757, # Selection of insecure algorithm during negotiation
451
+ }
452
+ ),
453
+ rule_patterns=(
454
+ "exception",
455
+ "error-handling",
456
+ "uncaught",
457
+ "unhandled",
458
+ "edge-case",
459
+ "boundary",
460
+ "overflow",
461
+ ),
462
+ ),
463
+ }
464
+
465
+
466
+ def _extract_cwe_id(cwe_str: str | None) -> int | None:
467
+ """Extract numeric CWE ID from string like 'CWE-79'."""
468
+ if not cwe_str:
469
+ return None
470
+ cwe_str = cwe_str.upper().replace("CWE-", "").replace("CWE", "")
471
+ try:
472
+ return int(cwe_str.strip())
473
+ except ValueError:
474
+ return None
475
+
476
+
477
+ def map_to_owasp(finding: Finding) -> list[FrameworkControl]:
478
+ """Map a finding to OWASP Top 10 2025 categories."""
479
+ controls: list[FrameworkControl] = []
480
+
481
+ # Extract CWE ID
482
+ cwe_id = _extract_cwe_id(finding.cwe)
483
+
484
+ # Check rule_id patterns
485
+ rule_id_lower = (finding.rule_id or "").lower()
486
+ title_lower = finding.title.lower()
487
+
488
+ for category in OWASP_TOP_10.values():
489
+ matched = False
490
+
491
+ # Match by CWE
492
+ if cwe_id and cwe_id in category.cwes:
493
+ matched = True
494
+
495
+ # Match by rule pattern
496
+ if not matched:
497
+ for pattern in category.rule_patterns:
498
+ if pattern in rule_id_lower or pattern in title_lower:
499
+ matched = True
500
+ break
501
+
502
+ # Match CVEs to A03 (Software Supply Chain Failures)
503
+ if not matched and category.id == "A03:2025" and finding.cve:
504
+ matched = True
505
+
506
+ if matched:
507
+ controls.append(
508
+ FrameworkControl(
509
+ framework="OWASP",
510
+ control_id=category.id,
511
+ title=category.name,
512
+ description=category.description,
513
+ requirement_level="required",
514
+ )
515
+ )
516
+
517
+ return controls