zen-ai-pentest 2.2.0__py3-none-any.whl → 2.3.0__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.
@@ -0,0 +1,206 @@
1
+ """Risk Scoring Module: CVSS + EPSS + Business Impact
2
+
3
+ Combines multiple risk factors for comprehensive scoring:
4
+ - CVSS (Common Vulnerability Scoring System)
5
+ - EPSS (Exploit Prediction Scoring System)
6
+ - Business Impact (Criticality of affected asset)
7
+ """
8
+ from typing import Dict, List, Optional, Tuple
9
+ from dataclasses import dataclass
10
+ from enum import Enum
11
+ import math
12
+
13
+
14
+ class SeverityLevel(Enum):
15
+ CRITICAL = "critical"
16
+ HIGH = "high"
17
+ MEDIUM = "medium"
18
+ LOW = "low"
19
+ INFO = "info"
20
+
21
+
22
+ @dataclass
23
+ class RiskFactors:
24
+ """Risk factors for scoring"""
25
+ cvss_score: float = 0.0 # 0.0 - 10.0
26
+ epss_score: float = 0.0 # 0.0 - 1.0 (probability)
27
+ business_impact: int = 1 # 1 - 5 (asset criticality)
28
+ exposure: int = 1 # 1 - 5 (network exposure)
29
+ data_sensitivity: int = 1 # 1 - 5 (data classification)
30
+
31
+
32
+ class RiskScoringModule:
33
+ """Advanced risk scoring with CVSS + EPSS + Business Impact"""
34
+
35
+ name = "risk_scoring"
36
+ version = "1.0.0"
37
+ enabled = True
38
+
39
+ # Weight factors (must sum to 1.0)
40
+ WEIGHTS = {
41
+ 'cvss': 0.35,
42
+ 'epss': 0.25,
43
+ 'business': 0.25,
44
+ 'exposure': 0.10,
45
+ 'data': 0.05
46
+ }
47
+
48
+ def __init__(self):
49
+ self.name = "risk_scoring"
50
+ self.enabled = True
51
+
52
+ def calculate_cvss_score(self, cve_id: str) -> float:
53
+ """Fetch CVSS score from CVE database"""
54
+ # In production, this would query NVD API
55
+ # For demo, return mock scores based on CVE ID
56
+ cvss_map = {
57
+ 'CVE-2021-44228': 10.0, # Log4j
58
+ 'CVE-2024-1234': 9.8,
59
+ 'CVE-2024-5678': 7.5,
60
+ 'CVE-2024-9999': 5.3,
61
+ }
62
+ return cvss_map.get(cve_id, 7.0)
63
+
64
+ def calculate_epss_score(self, cve_id: str) -> float:
65
+ """Fetch EPSS score (exploit probability)"""
66
+ # EPSS = probability of exploitation in wild
67
+ # In production: query EPSS API
68
+ epss_map = {
69
+ 'CVE-2021-44228': 0.97, # Log4j - very likely exploited
70
+ 'CVE-2024-1234': 0.75,
71
+ 'CVE-2024-5678': 0.35,
72
+ 'CVE-2024-9999': 0.10,
73
+ }
74
+ return epss_map.get(cve_id, 0.30)
75
+
76
+ def calculate_business_impact(self, asset_type: str) -> int:
77
+ """Calculate business impact score (1-5)"""
78
+ impact_map = {
79
+ 'production': 5,
80
+ 'database': 5,
81
+ 'domain_controller': 5,
82
+ 'api_gateway': 4,
83
+ 'web_server': 3,
84
+ 'workstation': 2,
85
+ 'test': 1,
86
+ }
87
+ return impact_map.get(asset_type.lower(), 3)
88
+
89
+ def calculate_composite_score(self, factors: RiskFactors) -> float:
90
+ """Calculate composite risk score (0-100)"""
91
+ # Normalize all factors to 0-100 scale
92
+ cvss_normalized = factors.cvss_score * 10 # 0-10 -> 0-100
93
+ epss_normalized = factors.epss_score * 100 # 0-1 -> 0-100
94
+ business_normalized = factors.business_impact * 20 # 1-5 -> 20-100
95
+ exposure_normalized = factors.exposure * 20 # 1-5 -> 20-100
96
+ data_normalized = factors.data_sensitivity * 20 # 1-5 -> 20-100
97
+
98
+ # Weighted sum
99
+ score = (
100
+ cvss_normalized * self.WEIGHTS['cvss'] +
101
+ epss_normalized * self.WEIGHTS['epss'] +
102
+ business_normalized * self.WEIGHTS['business'] +
103
+ exposure_normalized * self.WEIGHTS['exposure'] +
104
+ data_normalized * self.WEIGHTS['data']
105
+ )
106
+
107
+ return round(score, 2)
108
+
109
+ def score_to_severity(self, score: float) -> SeverityLevel:
110
+ """Convert numeric score to severity level"""
111
+ if score >= 80:
112
+ return SeverityLevel.CRITICAL
113
+ elif score >= 60:
114
+ return SeverityLevel.HIGH
115
+ elif score >= 40:
116
+ return SeverityLevel.MEDIUM
117
+ elif score >= 20:
118
+ return SeverityLevel.LOW
119
+ else:
120
+ return SeverityLevel.INFO
121
+
122
+ def score_vulnerability(
123
+ self,
124
+ cve_id: str,
125
+ asset_type: str = "web_server",
126
+ exposure: int = 3,
127
+ data_sensitivity: int = 3
128
+ ) -> Dict:
129
+ """Score a single vulnerability"""
130
+ factors = RiskFactors(
131
+ cvss_score=self.calculate_cvss_score(cve_id),
132
+ epss_score=self.calculate_epss_score(cve_id),
133
+ business_impact=self.calculate_business_impact(asset_type),
134
+ exposure=exposure,
135
+ data_sensitivity=data_sensitivity
136
+ )
137
+
138
+ composite_score = self.calculate_composite_score(factors)
139
+ severity = self.score_to_severity(composite_score)
140
+
141
+ return {
142
+ 'cve_id': cve_id,
143
+ 'asset_type': asset_type,
144
+ 'cvss_score': factors.cvss_score,
145
+ 'epss_score': factors.epss_score,
146
+ 'business_impact': factors.business_impact,
147
+ 'composite_score': composite_score,
148
+ 'severity': severity.value,
149
+ 'priority': self._calculate_priority(composite_score, factors.epss_score),
150
+ 'remediation_timeline': self._get_remediation_timeline(severity)
151
+ }
152
+
153
+ def _calculate_priority(self, score: float, epss: float) -> str:
154
+ """Calculate remediation priority"""
155
+ if score >= 80 and epss > 0.5:
156
+ return "P1 - Immediate (24h)"
157
+ elif score >= 60 or (score >= 40 and epss > 0.5):
158
+ return "P2 - High (72h)"
159
+ elif score >= 40:
160
+ return "P3 - Medium (7 days)"
161
+ elif score >= 20:
162
+ return "P4 - Low (30 days)"
163
+ else:
164
+ return "P5 - Info (next cycle)"
165
+
166
+ def _get_remediation_timeline(self, severity: SeverityLevel) -> str:
167
+ """Get recommended remediation timeline"""
168
+ timelines = {
169
+ SeverityLevel.CRITICAL: "Immediate - 24 hours",
170
+ SeverityLevel.HIGH: "Urgent - 72 hours",
171
+ SeverityLevel.MEDIUM: "Standard - 7 days",
172
+ SeverityLevel.LOW: "Planned - 30 days",
173
+ SeverityLevel.INFO: "Track - Next cycle"
174
+ }
175
+ return timelines[severity]
176
+
177
+ def score_findings(
178
+ self,
179
+ findings: List[Dict],
180
+ asset_inventory: Optional[Dict] = None
181
+ ) -> List[Dict]:
182
+ """Score multiple findings"""
183
+ scored_findings = []
184
+ for finding in findings:
185
+ cve = finding.get('cve_id', 'CVE-2024-0000')
186
+ asset = finding.get('asset_type', 'web_server')
187
+ exposure = finding.get('exposure', 3)
188
+ data_sens = finding.get('data_sensitivity', 3)
189
+
190
+ scored = self.score_vulnerability(cve, asset, exposure, data_sens)
191
+ scored['original_finding'] = finding
192
+ scored_findings.append(scored)
193
+
194
+ # Sort by composite score (highest first)
195
+ scored_findings.sort(key=lambda x: x['composite_score'], reverse=True)
196
+ return scored_findings
197
+
198
+ def get_info(self) -> Dict:
199
+ """Get module info"""
200
+ return {
201
+ 'name': self.name,
202
+ 'version': self.version,
203
+ 'description': 'Advanced risk scoring: CVSS + EPSS + Business Impact',
204
+ 'factors': list(self.WEIGHTS.keys()),
205
+ 'scoring_range': '0-100'
206
+ }