zen-ai-pentest 2.0.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.
- agents/__init__.py +28 -0
- agents/agent_base.py +239 -0
- agents/agent_orchestrator.py +346 -0
- agents/analysis_agent.py +225 -0
- agents/cli.py +258 -0
- agents/exploit_agent.py +224 -0
- agents/integration.py +211 -0
- agents/post_scan_agent.py +937 -0
- agents/react_agent.py +384 -0
- agents/react_agent_enhanced.py +616 -0
- agents/react_agent_vm.py +298 -0
- agents/research_agent.py +176 -0
- api/__init__.py +11 -0
- api/auth.py +123 -0
- api/main.py +1027 -0
- api/schemas.py +357 -0
- api/websocket.py +97 -0
- autonomous/__init__.py +122 -0
- autonomous/agent.py +253 -0
- autonomous/agent_loop.py +1370 -0
- autonomous/exploit_validator.py +1537 -0
- autonomous/memory.py +448 -0
- autonomous/react.py +339 -0
- autonomous/tool_executor.py +488 -0
- backends/__init__.py +16 -0
- backends/chatgpt_direct.py +133 -0
- backends/claude_direct.py +130 -0
- backends/duckduckgo.py +138 -0
- backends/openrouter.py +120 -0
- benchmarks/__init__.py +149 -0
- benchmarks/benchmark_engine.py +904 -0
- benchmarks/ci_benchmark.py +785 -0
- benchmarks/comparison.py +729 -0
- benchmarks/metrics.py +553 -0
- benchmarks/run_benchmarks.py +809 -0
- ci_cd/__init__.py +2 -0
- core/__init__.py +17 -0
- core/async_pool.py +282 -0
- core/asyncio_fix.py +222 -0
- core/cache.py +472 -0
- core/container.py +277 -0
- core/database.py +114 -0
- core/input_validator.py +353 -0
- core/models.py +288 -0
- core/orchestrator.py +611 -0
- core/plugin_manager.py +571 -0
- core/rate_limiter.py +405 -0
- core/secure_config.py +328 -0
- core/shield_integration.py +296 -0
- modules/__init__.py +46 -0
- modules/cve_database.py +362 -0
- modules/exploit_assist.py +330 -0
- modules/nuclei_integration.py +480 -0
- modules/osint.py +604 -0
- modules/protonvpn.py +554 -0
- modules/recon.py +165 -0
- modules/sql_injection_db.py +826 -0
- modules/tool_orchestrator.py +498 -0
- modules/vuln_scanner.py +292 -0
- modules/wordlist_generator.py +566 -0
- risk_engine/__init__.py +99 -0
- risk_engine/business_impact.py +267 -0
- risk_engine/business_impact_calculator.py +563 -0
- risk_engine/cvss.py +156 -0
- risk_engine/epss.py +190 -0
- risk_engine/example_usage.py +294 -0
- risk_engine/false_positive_engine.py +1073 -0
- risk_engine/scorer.py +304 -0
- web_ui/backend/main.py +471 -0
- zen_ai_pentest-2.0.0.dist-info/METADATA +795 -0
- zen_ai_pentest-2.0.0.dist-info/RECORD +75 -0
- zen_ai_pentest-2.0.0.dist-info/WHEEL +5 -0
- zen_ai_pentest-2.0.0.dist-info/entry_points.txt +2 -0
- zen_ai_pentest-2.0.0.dist-info/licenses/LICENSE +21 -0
- zen_ai_pentest-2.0.0.dist-info/top_level.txt +10 -0
risk_engine/scorer.py
ADDED
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Main Risk Scoring Implementation
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import asyncio
|
|
6
|
+
from dataclasses import dataclass, field
|
|
7
|
+
from datetime import datetime
|
|
8
|
+
from enum import Enum
|
|
9
|
+
from typing import Any, Dict, List, Optional
|
|
10
|
+
|
|
11
|
+
from .cvss import CVSSCalculator
|
|
12
|
+
from .epss import EPSSClient
|
|
13
|
+
from .business_impact import BusinessImpactCalculator
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class SeverityLevel(Enum):
|
|
17
|
+
"""Risk severity levels with SLA requirements."""
|
|
18
|
+
CRITICAL = (9.0, 10.0, "24h")
|
|
19
|
+
HIGH = (7.0, 8.9, "72h")
|
|
20
|
+
MEDIUM = (4.0, 6.9, "14d")
|
|
21
|
+
LOW = (1.0, 3.9, "30d")
|
|
22
|
+
INFO = (0.0, 0.9, "Best effort")
|
|
23
|
+
|
|
24
|
+
def __init__(self, min_score: float, max_score: float, sla: str):
|
|
25
|
+
self.min_score = min_score
|
|
26
|
+
self.max_score = max_score
|
|
27
|
+
self.sla = sla
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
@dataclass
|
|
31
|
+
class RiskScore:
|
|
32
|
+
"""Complete risk score with all components."""
|
|
33
|
+
value: float # 0-10
|
|
34
|
+
severity: SeverityLevel
|
|
35
|
+
|
|
36
|
+
# Component scores (0-1 each)
|
|
37
|
+
cvss_score: float
|
|
38
|
+
epss_score: float
|
|
39
|
+
business_impact_score: float
|
|
40
|
+
exploit_validation_score: float
|
|
41
|
+
|
|
42
|
+
# Detailed breakdown
|
|
43
|
+
components: Dict[str, Any] = field(default_factory=dict)
|
|
44
|
+
|
|
45
|
+
# Context
|
|
46
|
+
target_context: Dict[str, Any] = field(default_factory=dict)
|
|
47
|
+
|
|
48
|
+
# Recommendations
|
|
49
|
+
prioritized_actions: List[str] = field(default_factory=list)
|
|
50
|
+
|
|
51
|
+
timestamp: datetime = field(default_factory=datetime.now)
|
|
52
|
+
|
|
53
|
+
def to_dict(self) -> Dict:
|
|
54
|
+
return {
|
|
55
|
+
'risk_score': round(self.value, 2),
|
|
56
|
+
'severity': self.severity.name,
|
|
57
|
+
'severity_range': f"{self.severity.min_score}-{self.severity.max_score}",
|
|
58
|
+
'sla': self.severity.sla,
|
|
59
|
+
'components': {
|
|
60
|
+
'cvss': round(self.cvss_score, 3),
|
|
61
|
+
'epss': round(self.epss_score, 3),
|
|
62
|
+
'business_impact': round(self.business_impact_score, 3),
|
|
63
|
+
'exploit_validation': round(self.exploit_validation_score, 3)
|
|
64
|
+
},
|
|
65
|
+
'detailed_breakdown': self.components,
|
|
66
|
+
'target_context': self.target_context,
|
|
67
|
+
'prioritized_actions': self.prioritized_actions,
|
|
68
|
+
'timestamp': self.timestamp.isoformat()
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
class RiskScorer:
|
|
73
|
+
"""
|
|
74
|
+
Multi-factor risk scoring engine.
|
|
75
|
+
|
|
76
|
+
Combines:
|
|
77
|
+
- CVSS (25%): Base vulnerability severity
|
|
78
|
+
- EPSS (25%): Exploit probability
|
|
79
|
+
- Business Impact (35%): Contextual risk
|
|
80
|
+
- Exploit Validation (15%): Confirmed exploitation
|
|
81
|
+
"""
|
|
82
|
+
|
|
83
|
+
WEIGHTS = {
|
|
84
|
+
'cvss': 0.25,
|
|
85
|
+
'epss': 0.25,
|
|
86
|
+
'business': 0.35,
|
|
87
|
+
'validation': 0.15
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
def __init__(
|
|
91
|
+
self,
|
|
92
|
+
enable_epss: bool = True,
|
|
93
|
+
enable_business_context: bool = True
|
|
94
|
+
):
|
|
95
|
+
self.cvss_calc = CVSSCalculator()
|
|
96
|
+
self.epss_client = EPSSClient() if enable_epss else None
|
|
97
|
+
self.business_calc = BusinessImpactCalculator() if enable_business_context else None
|
|
98
|
+
|
|
99
|
+
def calculate(
|
|
100
|
+
self,
|
|
101
|
+
finding: Dict[str, Any],
|
|
102
|
+
target_context: Optional[Dict] = None
|
|
103
|
+
) -> RiskScore:
|
|
104
|
+
"""
|
|
105
|
+
Calculate comprehensive risk score for a finding.
|
|
106
|
+
|
|
107
|
+
Args:
|
|
108
|
+
finding: Vulnerability finding with CVE, severity, etc.
|
|
109
|
+
target_context: Target information (internet-facing, data sensitivity, etc.)
|
|
110
|
+
|
|
111
|
+
Returns:
|
|
112
|
+
RiskScore with all components and recommendations
|
|
113
|
+
"""
|
|
114
|
+
target_context = target_context or {}
|
|
115
|
+
|
|
116
|
+
# 1. CVSS Score (normalize to 0-1)
|
|
117
|
+
cvss_score = self._calculate_cvss(finding) / 10.0
|
|
118
|
+
|
|
119
|
+
# 2. EPSS Score (0-1 probability)
|
|
120
|
+
epss_score = self._get_epss(finding)
|
|
121
|
+
|
|
122
|
+
# 3. Business Impact (0-1)
|
|
123
|
+
business_score = self._calculate_business_impact(finding, target_context)
|
|
124
|
+
|
|
125
|
+
# 4. Exploit Validation (0 or 1)
|
|
126
|
+
validation_score = self._validate_exploit(finding)
|
|
127
|
+
|
|
128
|
+
# Calculate weighted risk score (0-10)
|
|
129
|
+
risk_value = (
|
|
130
|
+
cvss_score * self.WEIGHTS['cvss'] +
|
|
131
|
+
epss_score * self.WEIGHTS['epss'] +
|
|
132
|
+
business_score * self.WEIGHTS['business'] +
|
|
133
|
+
validation_score * self.WEIGHTS['validation']
|
|
134
|
+
) * 10
|
|
135
|
+
|
|
136
|
+
# Determine severity level
|
|
137
|
+
severity = self._get_severity(risk_value)
|
|
138
|
+
|
|
139
|
+
# Generate recommendations
|
|
140
|
+
recommendations = self._generate_recommendations(
|
|
141
|
+
finding, severity, cvss_score, epss_score
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
return RiskScore(
|
|
145
|
+
value=risk_value,
|
|
146
|
+
severity=severity,
|
|
147
|
+
cvss_score=cvss_score,
|
|
148
|
+
epss_score=epss_score,
|
|
149
|
+
business_impact_score=business_score,
|
|
150
|
+
exploit_validation_score=validation_score,
|
|
151
|
+
components={
|
|
152
|
+
'cvss_details': self.cvss_calc.get_details(finding),
|
|
153
|
+
'epss_details': {'cve_id': finding.get('cve_id'), 'score': epss_score},
|
|
154
|
+
'business_factors': self._get_business_factors(target_context),
|
|
155
|
+
'validation_status': self._get_validation_status(finding)
|
|
156
|
+
},
|
|
157
|
+
target_context=target_context,
|
|
158
|
+
prioritized_actions=recommendations
|
|
159
|
+
)
|
|
160
|
+
|
|
161
|
+
def _calculate_cvss(self, finding: Dict) -> float:
|
|
162
|
+
"""Calculate CVSS base score."""
|
|
163
|
+
# Use provided CVSS or calculate from details
|
|
164
|
+
if 'cvss_score' in finding:
|
|
165
|
+
return finding['cvss_score']
|
|
166
|
+
|
|
167
|
+
# Calculate from CVE ID
|
|
168
|
+
if 'cve_id' in finding:
|
|
169
|
+
return self.cvss_calc.from_cve(finding['cve_id'])
|
|
170
|
+
|
|
171
|
+
# Estimate from description
|
|
172
|
+
return self.cvss_calc.estimate(finding.get('description', ''))
|
|
173
|
+
|
|
174
|
+
def _get_epss(self, finding: Dict) -> float:
|
|
175
|
+
"""Get EPSS probability score."""
|
|
176
|
+
if not self.epss_client:
|
|
177
|
+
return 0.5 # Default if EPSS disabled
|
|
178
|
+
|
|
179
|
+
cve_id = finding.get('cve_id')
|
|
180
|
+
if not cve_id:
|
|
181
|
+
return 0.0
|
|
182
|
+
|
|
183
|
+
try:
|
|
184
|
+
return self.epss_client.get_score(cve_id)
|
|
185
|
+
except Exception:
|
|
186
|
+
return 0.0
|
|
187
|
+
|
|
188
|
+
def _calculate_business_impact(
|
|
189
|
+
self,
|
|
190
|
+
finding: Dict,
|
|
191
|
+
context: Dict
|
|
192
|
+
) -> float:
|
|
193
|
+
"""Calculate business impact score."""
|
|
194
|
+
if not self.business_calc:
|
|
195
|
+
return 0.5 # Default
|
|
196
|
+
|
|
197
|
+
return self.business_calc.calculate(finding, context)
|
|
198
|
+
|
|
199
|
+
def _validate_exploit(self, finding: Dict) -> float:
|
|
200
|
+
"""
|
|
201
|
+
Validate if exploit is confirmed.
|
|
202
|
+
Returns: 1.0 = confirmed, 0.5 = code available, 0.2 = theoretical, 0.0 = none
|
|
203
|
+
"""
|
|
204
|
+
# Check if we have proof of exploitation
|
|
205
|
+
if finding.get('exploit_validated', False):
|
|
206
|
+
return 1.0
|
|
207
|
+
|
|
208
|
+
# Check if exploit code is available
|
|
209
|
+
if finding.get('exploit_available', False):
|
|
210
|
+
return 0.5
|
|
211
|
+
|
|
212
|
+
# Check if it's theoretically exploitable
|
|
213
|
+
if finding.get('theoretically_exploitable', False):
|
|
214
|
+
return 0.2
|
|
215
|
+
|
|
216
|
+
return 0.0
|
|
217
|
+
|
|
218
|
+
def _get_severity(self, risk_value: float) -> SeverityLevel:
|
|
219
|
+
"""Determine severity level from risk score."""
|
|
220
|
+
for level in SeverityLevel:
|
|
221
|
+
if level.min_score <= risk_value <= level.max_score:
|
|
222
|
+
return level
|
|
223
|
+
return SeverityLevel.INFO
|
|
224
|
+
|
|
225
|
+
def _generate_recommendations(
|
|
226
|
+
self,
|
|
227
|
+
finding: Dict,
|
|
228
|
+
severity: SeverityLevel,
|
|
229
|
+
cvss: float,
|
|
230
|
+
epss: float
|
|
231
|
+
) -> List[str]:
|
|
232
|
+
"""Generate prioritized remediation actions."""
|
|
233
|
+
recommendations = []
|
|
234
|
+
|
|
235
|
+
if severity == SeverityLevel.CRITICAL:
|
|
236
|
+
recommendations.append("IMMEDIATE: Isolate affected system")
|
|
237
|
+
recommendations.append("Deploy emergency patch within 24h")
|
|
238
|
+
recommendations.append("Activate incident response team")
|
|
239
|
+
|
|
240
|
+
elif severity == SeverityLevel.HIGH:
|
|
241
|
+
recommendations.append("Schedule patch deployment within 72h")
|
|
242
|
+
recommendations.append("Implement temporary workaround/WAF rule")
|
|
243
|
+
recommendations.append("Increase monitoring on affected assets")
|
|
244
|
+
|
|
245
|
+
elif severity == SeverityLevel.MEDIUM:
|
|
246
|
+
recommendations.append("Include in next maintenance window")
|
|
247
|
+
recommendations.append("Review and update security policies")
|
|
248
|
+
|
|
249
|
+
# EPSS-specific recommendations
|
|
250
|
+
if epss > 0.5:
|
|
251
|
+
recommendations.append(f"HIGH EXPLOIT PROBABILITY ({epss:.1%}) - Prioritize patching")
|
|
252
|
+
|
|
253
|
+
# CVSS-specific
|
|
254
|
+
if cvss > 0.8:
|
|
255
|
+
recommendations.append("Critical technical severity - Network segmentation recommended")
|
|
256
|
+
|
|
257
|
+
return recommendations
|
|
258
|
+
|
|
259
|
+
def _get_business_factors(self, context: Dict) -> Dict:
|
|
260
|
+
"""Extract business impact factors."""
|
|
261
|
+
return {
|
|
262
|
+
'internet_facing': context.get('internet_facing', False),
|
|
263
|
+
'data_sensitivity': context.get('data_sensitivity', 'unknown'),
|
|
264
|
+
'compliance_scope': context.get('compliance', []),
|
|
265
|
+
'asset_criticality': context.get('asset_criticality', 'medium')
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
def _get_validation_status(self, finding: Dict) -> str:
|
|
269
|
+
"""Get human-readable validation status."""
|
|
270
|
+
if finding.get('exploit_validated', False):
|
|
271
|
+
return "Confirmed Exploitable"
|
|
272
|
+
elif finding.get('exploit_available', False):
|
|
273
|
+
return "Exploit Code Available"
|
|
274
|
+
elif finding.get('theoretically_exploitable', False):
|
|
275
|
+
return "Theoretically Exploitable"
|
|
276
|
+
return "No Known Exploit"
|
|
277
|
+
|
|
278
|
+
def prioritize_findings(
|
|
279
|
+
self,
|
|
280
|
+
findings: List[Dict],
|
|
281
|
+
target_context: Optional[Dict] = None
|
|
282
|
+
) -> List[Dict]:
|
|
283
|
+
"""
|
|
284
|
+
Prioritize multiple findings by risk score.
|
|
285
|
+
|
|
286
|
+
Returns:
|
|
287
|
+
Findings sorted by risk (highest first) with risk scores attached
|
|
288
|
+
"""
|
|
289
|
+
scored_findings = []
|
|
290
|
+
|
|
291
|
+
for finding in findings:
|
|
292
|
+
risk = self.calculate(finding, target_context)
|
|
293
|
+
scored_findings.append({
|
|
294
|
+
**finding,
|
|
295
|
+
'risk_score': risk.to_dict()
|
|
296
|
+
})
|
|
297
|
+
|
|
298
|
+
# Sort by risk score descending
|
|
299
|
+
scored_findings.sort(
|
|
300
|
+
key=lambda x: x['risk_score']['risk_score'],
|
|
301
|
+
reverse=True
|
|
302
|
+
)
|
|
303
|
+
|
|
304
|
+
return scored_findings
|