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.
- kekkai/cli.py +789 -19
- kekkai/compliance/__init__.py +68 -0
- kekkai/compliance/hipaa.py +235 -0
- kekkai/compliance/mappings.py +136 -0
- kekkai/compliance/owasp.py +517 -0
- kekkai/compliance/owasp_agentic.py +267 -0
- kekkai/compliance/pci_dss.py +205 -0
- kekkai/compliance/soc2.py +209 -0
- kekkai/dojo.py +91 -14
- kekkai/dojo_import.py +9 -1
- kekkai/fix/__init__.py +47 -0
- kekkai/fix/audit.py +278 -0
- kekkai/fix/differ.py +427 -0
- kekkai/fix/engine.py +500 -0
- kekkai/fix/prompts.py +251 -0
- kekkai/output.py +10 -12
- kekkai/report/__init__.py +41 -0
- kekkai/report/compliance_matrix.py +98 -0
- kekkai/report/generator.py +365 -0
- kekkai/report/html.py +69 -0
- kekkai/report/pdf.py +63 -0
- kekkai/report/unified.py +226 -0
- kekkai/scanners/container.py +33 -3
- kekkai/scanners/gitleaks.py +3 -1
- kekkai/scanners/semgrep.py +1 -1
- kekkai/scanners/trivy.py +1 -1
- kekkai/threatflow/model_adapter.py +143 -1
- kekkai/triage/__init__.py +54 -1
- kekkai/triage/loader.py +196 -0
- kekkai_cli-1.1.1.dist-info/METADATA +379 -0
- {kekkai_cli-1.0.5.dist-info → kekkai_cli-1.1.1.dist-info}/RECORD +34 -33
- {kekkai_cli-1.0.5.dist-info → kekkai_cli-1.1.1.dist-info}/entry_points.txt +0 -1
- {kekkai_cli-1.0.5.dist-info → kekkai_cli-1.1.1.dist-info}/top_level.txt +0 -1
- kekkai_cli-1.0.5.dist-info/METADATA +0 -135
- portal/__init__.py +0 -19
- portal/api.py +0 -155
- portal/auth.py +0 -103
- portal/enterprise/__init__.py +0 -32
- portal/enterprise/audit.py +0 -435
- portal/enterprise/licensing.py +0 -342
- portal/enterprise/rbac.py +0 -276
- portal/enterprise/saml.py +0 -595
- portal/ops/__init__.py +0 -53
- portal/ops/backup.py +0 -553
- portal/ops/log_shipper.py +0 -469
- portal/ops/monitoring.py +0 -517
- portal/ops/restore.py +0 -469
- portal/ops/secrets.py +0 -408
- portal/ops/upgrade.py +0 -591
- portal/tenants.py +0 -340
- portal/uploads.py +0 -259
- portal/web.py +0 -384
- {kekkai_cli-1.0.5.dist-info → kekkai_cli-1.1.1.dist-info}/WHEEL +0 -0
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"""Compliance framework mapping for security findings.
|
|
2
|
+
|
|
3
|
+
Maps security findings to compliance framework controls for audit reporting.
|
|
4
|
+
|
|
5
|
+
Supported frameworks:
|
|
6
|
+
- PCI-DSS v4.0 (Payment Card Industry)
|
|
7
|
+
- SOC 2 Type II (Service Organization Controls)
|
|
8
|
+
- OWASP Top 10 2025 (Web Application Security)
|
|
9
|
+
- OWASP Agentic AI Top 10 (Autonomous AI Agent Security)
|
|
10
|
+
- HIPAA (Health Insurance Portability and Accountability)
|
|
11
|
+
|
|
12
|
+
Security considerations:
|
|
13
|
+
- Mappings are advisory, not compliance certifications
|
|
14
|
+
- Always include disclaimer in generated reports
|
|
15
|
+
- Raw finding data shown, no compliance assessments
|
|
16
|
+
|
|
17
|
+
ASVS Requirements:
|
|
18
|
+
- V5.3.1: Output encoding for reports
|
|
19
|
+
- V8.1.1: Reports stored in user-specified paths only
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
from __future__ import annotations
|
|
23
|
+
|
|
24
|
+
from .hipaa import HIPAA_SAFEGUARDS, HIPAASafeguard, map_to_hipaa
|
|
25
|
+
from .mappings import (
|
|
26
|
+
ComplianceMapping,
|
|
27
|
+
ComplianceMappingResult,
|
|
28
|
+
FrameworkControl,
|
|
29
|
+
map_finding_to_frameworks,
|
|
30
|
+
map_findings_to_all_frameworks,
|
|
31
|
+
)
|
|
32
|
+
from .owasp import OWASP_TOP_10, OWASPCategory, map_to_owasp
|
|
33
|
+
from .owasp_agentic import (
|
|
34
|
+
OWASP_AGENTIC_TOP_10,
|
|
35
|
+
OWASPAgenticCategory,
|
|
36
|
+
map_to_owasp_agentic,
|
|
37
|
+
)
|
|
38
|
+
from .pci_dss import PCI_DSS_CONTROLS, PCIDSSControl, map_to_pci_dss
|
|
39
|
+
from .soc2 import SOC2_CRITERIA, SOC2Criterion, map_to_soc2
|
|
40
|
+
|
|
41
|
+
__all__ = [
|
|
42
|
+
# Core mapping
|
|
43
|
+
"ComplianceMapping",
|
|
44
|
+
"ComplianceMappingResult",
|
|
45
|
+
"FrameworkControl",
|
|
46
|
+
"map_finding_to_frameworks",
|
|
47
|
+
"map_findings_to_all_frameworks",
|
|
48
|
+
# PCI-DSS
|
|
49
|
+
"PCIDSSControl",
|
|
50
|
+
"PCI_DSS_CONTROLS",
|
|
51
|
+
"map_to_pci_dss",
|
|
52
|
+
# SOC 2
|
|
53
|
+
"SOC2Criterion",
|
|
54
|
+
"SOC2_CRITERIA",
|
|
55
|
+
"map_to_soc2",
|
|
56
|
+
# OWASP Top 10 2025
|
|
57
|
+
"OWASPCategory",
|
|
58
|
+
"OWASP_TOP_10",
|
|
59
|
+
"map_to_owasp",
|
|
60
|
+
# OWASP Agentic AI Top 10
|
|
61
|
+
"OWASPAgenticCategory",
|
|
62
|
+
"OWASP_AGENTIC_TOP_10",
|
|
63
|
+
"map_to_owasp_agentic",
|
|
64
|
+
# HIPAA
|
|
65
|
+
"HIPAASafeguard",
|
|
66
|
+
"HIPAA_SAFEGUARDS",
|
|
67
|
+
"map_to_hipaa",
|
|
68
|
+
]
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
"""HIPAA Security Rule safeguard mapping for security findings.
|
|
2
|
+
|
|
3
|
+
Maps findings to HIPAA Security Rule safeguards based on CWE IDs and rule patterns.
|
|
4
|
+
Reference: https://www.hhs.gov/hipaa/for-professionals/security/index.html
|
|
5
|
+
|
|
6
|
+
Note: HIPAA mappings are advisory and apply primarily to healthcare-related
|
|
7
|
+
applications handling Protected Health Information (PHI).
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
from dataclasses import dataclass
|
|
13
|
+
from typing import TYPE_CHECKING
|
|
14
|
+
|
|
15
|
+
from .mappings import FrameworkControl
|
|
16
|
+
|
|
17
|
+
if TYPE_CHECKING:
|
|
18
|
+
from kekkai.scanners.base import Finding
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
@dataclass(frozen=True)
|
|
22
|
+
class HIPAASafeguard:
|
|
23
|
+
"""HIPAA Security Rule safeguard definition."""
|
|
24
|
+
|
|
25
|
+
id: str
|
|
26
|
+
title: str
|
|
27
|
+
description: str
|
|
28
|
+
category: str # Administrative, Physical, Technical
|
|
29
|
+
implementation: str # Required, Addressable
|
|
30
|
+
cwes: frozenset[int]
|
|
31
|
+
rule_patterns: tuple[str, ...]
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
# HIPAA Security Rule safeguards relevant to application security
|
|
35
|
+
HIPAA_SAFEGUARDS: dict[str, HIPAASafeguard] = {
|
|
36
|
+
# Technical Safeguards
|
|
37
|
+
"164.312(a)(1)": HIPAASafeguard(
|
|
38
|
+
id="164.312(a)(1)",
|
|
39
|
+
title="Access Control",
|
|
40
|
+
description=(
|
|
41
|
+
"Implement technical policies and procedures for electronic "
|
|
42
|
+
"information systems that maintain ePHI"
|
|
43
|
+
),
|
|
44
|
+
category="Technical",
|
|
45
|
+
implementation="Required",
|
|
46
|
+
cwes=frozenset({264, 284, 285, 287, 306, 639, 862, 863}),
|
|
47
|
+
rule_patterns=("access-control", "authorization", "authentication"),
|
|
48
|
+
),
|
|
49
|
+
"164.312(a)(2)(i)": HIPAASafeguard(
|
|
50
|
+
id="164.312(a)(2)(i)",
|
|
51
|
+
title="Unique User Identification",
|
|
52
|
+
description="Assign a unique name and/or number for identifying and tracking user identity",
|
|
53
|
+
category="Technical",
|
|
54
|
+
implementation="Required",
|
|
55
|
+
cwes=frozenset({287, 288, 521}),
|
|
56
|
+
rule_patterns=("user-identification", "identity", "authentication"),
|
|
57
|
+
),
|
|
58
|
+
"164.312(a)(2)(ii)": HIPAASafeguard(
|
|
59
|
+
id="164.312(a)(2)(ii)",
|
|
60
|
+
title="Emergency Access Procedure",
|
|
61
|
+
description="Establish procedures for obtaining necessary ePHI during an emergency",
|
|
62
|
+
category="Technical",
|
|
63
|
+
implementation="Required",
|
|
64
|
+
cwes=frozenset({269}),
|
|
65
|
+
rule_patterns=("emergency-access", "break-glass"),
|
|
66
|
+
),
|
|
67
|
+
"164.312(a)(2)(iii)": HIPAASafeguard(
|
|
68
|
+
id="164.312(a)(2)(iii)",
|
|
69
|
+
title="Automatic Logoff",
|
|
70
|
+
description=(
|
|
71
|
+
"Implement electronic procedures that terminate an electronic session after inactivity"
|
|
72
|
+
),
|
|
73
|
+
category="Technical",
|
|
74
|
+
implementation="Addressable",
|
|
75
|
+
cwes=frozenset({613}),
|
|
76
|
+
rule_patterns=("session", "timeout", "logoff", "idle"),
|
|
77
|
+
),
|
|
78
|
+
"164.312(a)(2)(iv)": HIPAASafeguard(
|
|
79
|
+
id="164.312(a)(2)(iv)",
|
|
80
|
+
title="Encryption and Decryption",
|
|
81
|
+
description="Implement a mechanism to encrypt and decrypt ePHI",
|
|
82
|
+
category="Technical",
|
|
83
|
+
implementation="Addressable",
|
|
84
|
+
cwes=frozenset({311, 312, 319, 326, 327, 328}),
|
|
85
|
+
rule_patterns=("encryption", "crypto", "decrypt"),
|
|
86
|
+
),
|
|
87
|
+
"164.312(b)": HIPAASafeguard(
|
|
88
|
+
id="164.312(b)",
|
|
89
|
+
title="Audit Controls",
|
|
90
|
+
description=(
|
|
91
|
+
"Implement hardware, software, and/or procedures to record and examine activity"
|
|
92
|
+
),
|
|
93
|
+
category="Technical",
|
|
94
|
+
implementation="Required",
|
|
95
|
+
cwes=frozenset({117, 223, 532, 778}),
|
|
96
|
+
rule_patterns=("audit", "logging", "monitoring", "log-injection"),
|
|
97
|
+
),
|
|
98
|
+
"164.312(c)(1)": HIPAASafeguard(
|
|
99
|
+
id="164.312(c)(1)",
|
|
100
|
+
title="Integrity",
|
|
101
|
+
description=(
|
|
102
|
+
"Implement policies and procedures to protect ePHI from "
|
|
103
|
+
"improper alteration or destruction"
|
|
104
|
+
),
|
|
105
|
+
category="Technical",
|
|
106
|
+
implementation="Required",
|
|
107
|
+
cwes=frozenset({345, 353, 494, 502}),
|
|
108
|
+
rule_patterns=("integrity", "tampering", "modification"),
|
|
109
|
+
),
|
|
110
|
+
"164.312(c)(2)": HIPAASafeguard(
|
|
111
|
+
id="164.312(c)(2)",
|
|
112
|
+
title="Mechanism to Authenticate ePHI",
|
|
113
|
+
description="Implement electronic mechanisms to corroborate that ePHI has not been altered",
|
|
114
|
+
category="Technical",
|
|
115
|
+
implementation="Addressable",
|
|
116
|
+
cwes=frozenset({345, 347, 354}),
|
|
117
|
+
rule_patterns=("authentication", "signature", "hash", "checksum"),
|
|
118
|
+
),
|
|
119
|
+
"164.312(d)": HIPAASafeguard(
|
|
120
|
+
id="164.312(d)",
|
|
121
|
+
title="Person or Entity Authentication",
|
|
122
|
+
description=(
|
|
123
|
+
"Implement procedures to verify that a person or entity seeking "
|
|
124
|
+
"access is the one claimed"
|
|
125
|
+
),
|
|
126
|
+
category="Technical",
|
|
127
|
+
implementation="Required",
|
|
128
|
+
cwes=frozenset({287, 290, 294, 295, 302, 306, 307}),
|
|
129
|
+
rule_patterns=("authentication", "verify", "identity", "credential"),
|
|
130
|
+
),
|
|
131
|
+
"164.312(e)(1)": HIPAASafeguard(
|
|
132
|
+
id="164.312(e)(1)",
|
|
133
|
+
title="Transmission Security",
|
|
134
|
+
description=(
|
|
135
|
+
"Implement technical security measures to guard against unauthorized access to ePHI"
|
|
136
|
+
),
|
|
137
|
+
category="Technical",
|
|
138
|
+
implementation="Required",
|
|
139
|
+
cwes=frozenset({319, 523, 757}),
|
|
140
|
+
rule_patterns=("transmission", "tls", "ssl", "transport"),
|
|
141
|
+
),
|
|
142
|
+
"164.312(e)(2)(i)": HIPAASafeguard(
|
|
143
|
+
id="164.312(e)(2)(i)",
|
|
144
|
+
title="Integrity Controls",
|
|
145
|
+
description=(
|
|
146
|
+
"Implement security measures to ensure electronically transmitted "
|
|
147
|
+
"ePHI is not improperly modified"
|
|
148
|
+
),
|
|
149
|
+
category="Technical",
|
|
150
|
+
implementation="Addressable",
|
|
151
|
+
cwes=frozenset({319, 345}),
|
|
152
|
+
rule_patterns=("integrity", "transmission", "modification"),
|
|
153
|
+
),
|
|
154
|
+
"164.312(e)(2)(ii)": HIPAASafeguard(
|
|
155
|
+
id="164.312(e)(2)(ii)",
|
|
156
|
+
title="Encryption",
|
|
157
|
+
description="Implement mechanism to encrypt ePHI whenever deemed appropriate",
|
|
158
|
+
category="Technical",
|
|
159
|
+
implementation="Addressable",
|
|
160
|
+
cwes=frozenset({311, 319, 326, 327}),
|
|
161
|
+
rule_patterns=("encryption", "tls", "ssl"),
|
|
162
|
+
),
|
|
163
|
+
# Administrative Safeguards (security-relevant)
|
|
164
|
+
"164.308(a)(1)(ii)(A)": HIPAASafeguard(
|
|
165
|
+
id="164.308(a)(1)(ii)(A)",
|
|
166
|
+
title="Risk Analysis",
|
|
167
|
+
description=(
|
|
168
|
+
"Conduct an accurate and thorough assessment of potential risks and vulnerabilities"
|
|
169
|
+
),
|
|
170
|
+
category="Administrative",
|
|
171
|
+
implementation="Required",
|
|
172
|
+
cwes=frozenset({937, 1035, 1104}),
|
|
173
|
+
rule_patterns=("vulnerability", "risk", "cve-", "scan"),
|
|
174
|
+
),
|
|
175
|
+
"164.308(a)(5)(ii)(B)": HIPAASafeguard(
|
|
176
|
+
id="164.308(a)(5)(ii)(B)",
|
|
177
|
+
title="Protection from Malicious Software",
|
|
178
|
+
description="Procedures for guarding against, detecting, and reporting malicious software",
|
|
179
|
+
category="Administrative",
|
|
180
|
+
implementation="Addressable",
|
|
181
|
+
cwes=frozenset({94, 502, 829}),
|
|
182
|
+
rule_patterns=("malware", "malicious", "injection"),
|
|
183
|
+
),
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
def _extract_cwe_id(cwe_str: str | None) -> int | None:
|
|
188
|
+
"""Extract numeric CWE ID from string."""
|
|
189
|
+
if not cwe_str:
|
|
190
|
+
return None
|
|
191
|
+
cwe_str = cwe_str.upper().replace("CWE-", "").replace("CWE", "")
|
|
192
|
+
try:
|
|
193
|
+
return int(cwe_str.strip())
|
|
194
|
+
except ValueError:
|
|
195
|
+
return None
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
def map_to_hipaa(finding: Finding) -> list[FrameworkControl]:
|
|
199
|
+
"""Map a finding to HIPAA Security Rule safeguards."""
|
|
200
|
+
controls: list[FrameworkControl] = []
|
|
201
|
+
|
|
202
|
+
cwe_id = _extract_cwe_id(finding.cwe)
|
|
203
|
+
rule_id_lower = (finding.rule_id or "").lower()
|
|
204
|
+
title_lower = finding.title.lower()
|
|
205
|
+
|
|
206
|
+
for safeguard in HIPAA_SAFEGUARDS.values():
|
|
207
|
+
matched = False
|
|
208
|
+
|
|
209
|
+
# Match by CWE
|
|
210
|
+
if cwe_id and cwe_id in safeguard.cwes:
|
|
211
|
+
matched = True
|
|
212
|
+
|
|
213
|
+
# Match by rule pattern
|
|
214
|
+
if not matched:
|
|
215
|
+
for pattern in safeguard.rule_patterns:
|
|
216
|
+
if pattern in rule_id_lower or pattern in title_lower:
|
|
217
|
+
matched = True
|
|
218
|
+
break
|
|
219
|
+
|
|
220
|
+
# CVEs map to 164.308(a)(1)(ii)(A) (risk analysis)
|
|
221
|
+
if not matched and safeguard.id == "164.308(a)(1)(ii)(A)" and finding.cve:
|
|
222
|
+
matched = True
|
|
223
|
+
|
|
224
|
+
if matched:
|
|
225
|
+
controls.append(
|
|
226
|
+
FrameworkControl(
|
|
227
|
+
framework="HIPAA",
|
|
228
|
+
control_id=safeguard.id,
|
|
229
|
+
title=safeguard.title,
|
|
230
|
+
description=safeguard.description,
|
|
231
|
+
requirement_level=safeguard.implementation.lower(),
|
|
232
|
+
)
|
|
233
|
+
)
|
|
234
|
+
|
|
235
|
+
return controls
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
"""Core compliance mapping engine.
|
|
2
|
+
|
|
3
|
+
Maps security findings to compliance framework controls using CWE IDs,
|
|
4
|
+
rule patterns, and severity levels.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
from dataclasses import dataclass, field
|
|
10
|
+
from typing import TYPE_CHECKING
|
|
11
|
+
|
|
12
|
+
if TYPE_CHECKING:
|
|
13
|
+
from collections.abc import Sequence
|
|
14
|
+
|
|
15
|
+
from kekkai.scanners.base import Finding
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@dataclass(frozen=True)
|
|
19
|
+
class FrameworkControl:
|
|
20
|
+
"""A single compliance framework control."""
|
|
21
|
+
|
|
22
|
+
framework: str
|
|
23
|
+
control_id: str
|
|
24
|
+
title: str
|
|
25
|
+
description: str
|
|
26
|
+
requirement_level: str = "required" # required, recommended, optional
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
@dataclass
|
|
30
|
+
class ComplianceMapping:
|
|
31
|
+
"""Mapping of a finding to compliance controls."""
|
|
32
|
+
|
|
33
|
+
finding_hash: str
|
|
34
|
+
finding_title: str
|
|
35
|
+
finding_severity: str
|
|
36
|
+
controls: list[FrameworkControl] = field(default_factory=list)
|
|
37
|
+
|
|
38
|
+
def add_control(self, control: FrameworkControl) -> None:
|
|
39
|
+
"""Add a control to this mapping."""
|
|
40
|
+
self.controls.append(control)
|
|
41
|
+
|
|
42
|
+
def has_framework(self, framework: str) -> bool:
|
|
43
|
+
"""Check if any control from a framework is mapped."""
|
|
44
|
+
return any(c.framework == framework for c in self.controls)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
@dataclass
|
|
48
|
+
class ComplianceMappingResult:
|
|
49
|
+
"""Result of mapping findings to all frameworks."""
|
|
50
|
+
|
|
51
|
+
mappings: list[ComplianceMapping] = field(default_factory=list)
|
|
52
|
+
framework_summary: dict[str, int] = field(default_factory=dict)
|
|
53
|
+
unmapped_count: int = 0
|
|
54
|
+
total_findings: int = 0
|
|
55
|
+
|
|
56
|
+
def get_controls_by_framework(self, framework: str) -> list[FrameworkControl]:
|
|
57
|
+
"""Get all unique controls for a framework."""
|
|
58
|
+
seen: set[str] = set()
|
|
59
|
+
result: list[FrameworkControl] = []
|
|
60
|
+
for mapping in self.mappings:
|
|
61
|
+
for control in mapping.controls:
|
|
62
|
+
if control.framework == framework and control.control_id not in seen:
|
|
63
|
+
seen.add(control.control_id)
|
|
64
|
+
result.append(control)
|
|
65
|
+
return sorted(result, key=lambda c: c.control_id)
|
|
66
|
+
|
|
67
|
+
def get_findings_for_control(self, framework: str, control_id: str) -> list[ComplianceMapping]:
|
|
68
|
+
"""Get all findings mapped to a specific control."""
|
|
69
|
+
return [
|
|
70
|
+
m
|
|
71
|
+
for m in self.mappings
|
|
72
|
+
if any(c.framework == framework and c.control_id == control_id for c in m.controls)
|
|
73
|
+
]
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def map_finding_to_frameworks(finding: Finding) -> ComplianceMapping:
|
|
77
|
+
"""Map a single finding to all applicable compliance frameworks."""
|
|
78
|
+
from .hipaa import map_to_hipaa
|
|
79
|
+
from .owasp import map_to_owasp
|
|
80
|
+
from .owasp_agentic import map_to_owasp_agentic
|
|
81
|
+
from .pci_dss import map_to_pci_dss
|
|
82
|
+
from .soc2 import map_to_soc2
|
|
83
|
+
|
|
84
|
+
mapping = ComplianceMapping(
|
|
85
|
+
finding_hash=finding.dedupe_hash(),
|
|
86
|
+
finding_title=finding.title,
|
|
87
|
+
finding_severity=finding.severity.value,
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
# Map to each framework
|
|
91
|
+
for control in map_to_pci_dss(finding):
|
|
92
|
+
mapping.add_control(control)
|
|
93
|
+
|
|
94
|
+
for control in map_to_soc2(finding):
|
|
95
|
+
mapping.add_control(control)
|
|
96
|
+
|
|
97
|
+
for control in map_to_owasp(finding):
|
|
98
|
+
mapping.add_control(control)
|
|
99
|
+
|
|
100
|
+
for control in map_to_owasp_agentic(finding):
|
|
101
|
+
mapping.add_control(control)
|
|
102
|
+
|
|
103
|
+
for control in map_to_hipaa(finding):
|
|
104
|
+
mapping.add_control(control)
|
|
105
|
+
|
|
106
|
+
return mapping
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def map_findings_to_all_frameworks(
|
|
110
|
+
findings: Sequence[Finding],
|
|
111
|
+
) -> ComplianceMappingResult:
|
|
112
|
+
"""Map all findings to compliance frameworks."""
|
|
113
|
+
result = ComplianceMappingResult(total_findings=len(findings))
|
|
114
|
+
|
|
115
|
+
framework_counts: dict[str, set[str]] = {
|
|
116
|
+
"PCI-DSS": set(),
|
|
117
|
+
"SOC2": set(),
|
|
118
|
+
"OWASP": set(),
|
|
119
|
+
"OWASP-Agentic": set(),
|
|
120
|
+
"HIPAA": set(),
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
for finding in findings:
|
|
124
|
+
mapping = map_finding_to_frameworks(finding)
|
|
125
|
+
result.mappings.append(mapping)
|
|
126
|
+
|
|
127
|
+
if not mapping.controls:
|
|
128
|
+
result.unmapped_count += 1
|
|
129
|
+
else:
|
|
130
|
+
for control in mapping.controls:
|
|
131
|
+
if control.framework in framework_counts:
|
|
132
|
+
framework_counts[control.framework].add(control.control_id)
|
|
133
|
+
|
|
134
|
+
result.framework_summary = {k: len(v) for k, v in framework_counts.items()}
|
|
135
|
+
|
|
136
|
+
return result
|