aiptx 2.0.2__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.

Potentially problematic release.


This version of aiptx might be problematic. Click here for more details.

Files changed (165) hide show
  1. aipt_v2/__init__.py +110 -0
  2. aipt_v2/__main__.py +24 -0
  3. aipt_v2/agents/AIPTxAgent/__init__.py +10 -0
  4. aipt_v2/agents/AIPTxAgent/aiptx_agent.py +211 -0
  5. aipt_v2/agents/__init__.py +24 -0
  6. aipt_v2/agents/base.py +520 -0
  7. aipt_v2/agents/ptt.py +406 -0
  8. aipt_v2/agents/state.py +168 -0
  9. aipt_v2/app.py +960 -0
  10. aipt_v2/browser/__init__.py +31 -0
  11. aipt_v2/browser/automation.py +458 -0
  12. aipt_v2/browser/crawler.py +453 -0
  13. aipt_v2/cli.py +321 -0
  14. aipt_v2/compliance/__init__.py +71 -0
  15. aipt_v2/compliance/compliance_report.py +449 -0
  16. aipt_v2/compliance/framework_mapper.py +424 -0
  17. aipt_v2/compliance/nist_mapping.py +345 -0
  18. aipt_v2/compliance/owasp_mapping.py +330 -0
  19. aipt_v2/compliance/pci_mapping.py +297 -0
  20. aipt_v2/config.py +288 -0
  21. aipt_v2/core/__init__.py +43 -0
  22. aipt_v2/core/agent.py +630 -0
  23. aipt_v2/core/llm.py +395 -0
  24. aipt_v2/core/memory.py +305 -0
  25. aipt_v2/core/ptt.py +329 -0
  26. aipt_v2/database/__init__.py +14 -0
  27. aipt_v2/database/models.py +232 -0
  28. aipt_v2/database/repository.py +384 -0
  29. aipt_v2/docker/__init__.py +23 -0
  30. aipt_v2/docker/builder.py +260 -0
  31. aipt_v2/docker/manager.py +222 -0
  32. aipt_v2/docker/sandbox.py +371 -0
  33. aipt_v2/evasion/__init__.py +58 -0
  34. aipt_v2/evasion/request_obfuscator.py +272 -0
  35. aipt_v2/evasion/tls_fingerprint.py +285 -0
  36. aipt_v2/evasion/ua_rotator.py +301 -0
  37. aipt_v2/evasion/waf_bypass.py +439 -0
  38. aipt_v2/execution/__init__.py +23 -0
  39. aipt_v2/execution/executor.py +302 -0
  40. aipt_v2/execution/parser.py +544 -0
  41. aipt_v2/execution/terminal.py +337 -0
  42. aipt_v2/health.py +437 -0
  43. aipt_v2/intelligence/__init__.py +85 -0
  44. aipt_v2/intelligence/auth.py +520 -0
  45. aipt_v2/intelligence/chaining.py +775 -0
  46. aipt_v2/intelligence/cve_aipt.py +334 -0
  47. aipt_v2/intelligence/cve_info.py +1111 -0
  48. aipt_v2/intelligence/rag.py +239 -0
  49. aipt_v2/intelligence/scope.py +442 -0
  50. aipt_v2/intelligence/searchers/__init__.py +5 -0
  51. aipt_v2/intelligence/searchers/exploitdb_searcher.py +523 -0
  52. aipt_v2/intelligence/searchers/github_searcher.py +467 -0
  53. aipt_v2/intelligence/searchers/google_searcher.py +281 -0
  54. aipt_v2/intelligence/tools.json +443 -0
  55. aipt_v2/intelligence/triage.py +670 -0
  56. aipt_v2/interface/__init__.py +5 -0
  57. aipt_v2/interface/cli.py +230 -0
  58. aipt_v2/interface/main.py +501 -0
  59. aipt_v2/interface/tui.py +1276 -0
  60. aipt_v2/interface/utils.py +583 -0
  61. aipt_v2/llm/__init__.py +39 -0
  62. aipt_v2/llm/config.py +26 -0
  63. aipt_v2/llm/llm.py +514 -0
  64. aipt_v2/llm/memory.py +214 -0
  65. aipt_v2/llm/request_queue.py +89 -0
  66. aipt_v2/llm/utils.py +89 -0
  67. aipt_v2/models/__init__.py +15 -0
  68. aipt_v2/models/findings.py +295 -0
  69. aipt_v2/models/phase_result.py +224 -0
  70. aipt_v2/models/scan_config.py +207 -0
  71. aipt_v2/monitoring/grafana/dashboards/aipt-dashboard.json +355 -0
  72. aipt_v2/monitoring/grafana/dashboards/default.yml +17 -0
  73. aipt_v2/monitoring/grafana/datasources/prometheus.yml +17 -0
  74. aipt_v2/monitoring/prometheus.yml +60 -0
  75. aipt_v2/orchestration/__init__.py +52 -0
  76. aipt_v2/orchestration/pipeline.py +398 -0
  77. aipt_v2/orchestration/progress.py +300 -0
  78. aipt_v2/orchestration/scheduler.py +296 -0
  79. aipt_v2/orchestrator.py +2284 -0
  80. aipt_v2/payloads/__init__.py +27 -0
  81. aipt_v2/payloads/cmdi.py +150 -0
  82. aipt_v2/payloads/sqli.py +263 -0
  83. aipt_v2/payloads/ssrf.py +204 -0
  84. aipt_v2/payloads/templates.py +222 -0
  85. aipt_v2/payloads/traversal.py +166 -0
  86. aipt_v2/payloads/xss.py +204 -0
  87. aipt_v2/prompts/__init__.py +60 -0
  88. aipt_v2/proxy/__init__.py +29 -0
  89. aipt_v2/proxy/history.py +352 -0
  90. aipt_v2/proxy/interceptor.py +452 -0
  91. aipt_v2/recon/__init__.py +44 -0
  92. aipt_v2/recon/dns.py +241 -0
  93. aipt_v2/recon/osint.py +367 -0
  94. aipt_v2/recon/subdomain.py +372 -0
  95. aipt_v2/recon/tech_detect.py +311 -0
  96. aipt_v2/reports/__init__.py +17 -0
  97. aipt_v2/reports/generator.py +313 -0
  98. aipt_v2/reports/html_report.py +378 -0
  99. aipt_v2/runtime/__init__.py +44 -0
  100. aipt_v2/runtime/base.py +30 -0
  101. aipt_v2/runtime/docker.py +401 -0
  102. aipt_v2/runtime/local.py +346 -0
  103. aipt_v2/runtime/tool_server.py +205 -0
  104. aipt_v2/scanners/__init__.py +28 -0
  105. aipt_v2/scanners/base.py +273 -0
  106. aipt_v2/scanners/nikto.py +244 -0
  107. aipt_v2/scanners/nmap.py +402 -0
  108. aipt_v2/scanners/nuclei.py +273 -0
  109. aipt_v2/scanners/web.py +454 -0
  110. aipt_v2/scripts/security_audit.py +366 -0
  111. aipt_v2/telemetry/__init__.py +7 -0
  112. aipt_v2/telemetry/tracer.py +347 -0
  113. aipt_v2/terminal/__init__.py +28 -0
  114. aipt_v2/terminal/executor.py +400 -0
  115. aipt_v2/terminal/sandbox.py +350 -0
  116. aipt_v2/tools/__init__.py +44 -0
  117. aipt_v2/tools/active_directory/__init__.py +78 -0
  118. aipt_v2/tools/active_directory/ad_config.py +238 -0
  119. aipt_v2/tools/active_directory/bloodhound_wrapper.py +447 -0
  120. aipt_v2/tools/active_directory/kerberos_attacks.py +430 -0
  121. aipt_v2/tools/active_directory/ldap_enum.py +533 -0
  122. aipt_v2/tools/active_directory/smb_attacks.py +505 -0
  123. aipt_v2/tools/agents_graph/__init__.py +19 -0
  124. aipt_v2/tools/agents_graph/agents_graph_actions.py +69 -0
  125. aipt_v2/tools/api_security/__init__.py +76 -0
  126. aipt_v2/tools/api_security/api_discovery.py +608 -0
  127. aipt_v2/tools/api_security/graphql_scanner.py +622 -0
  128. aipt_v2/tools/api_security/jwt_analyzer.py +577 -0
  129. aipt_v2/tools/api_security/openapi_fuzzer.py +761 -0
  130. aipt_v2/tools/browser/__init__.py +5 -0
  131. aipt_v2/tools/browser/browser_actions.py +238 -0
  132. aipt_v2/tools/browser/browser_instance.py +535 -0
  133. aipt_v2/tools/browser/tab_manager.py +344 -0
  134. aipt_v2/tools/cloud/__init__.py +70 -0
  135. aipt_v2/tools/cloud/cloud_config.py +273 -0
  136. aipt_v2/tools/cloud/cloud_scanner.py +639 -0
  137. aipt_v2/tools/cloud/prowler_tool.py +571 -0
  138. aipt_v2/tools/cloud/scoutsuite_tool.py +359 -0
  139. aipt_v2/tools/executor.py +307 -0
  140. aipt_v2/tools/parser.py +408 -0
  141. aipt_v2/tools/proxy/__init__.py +5 -0
  142. aipt_v2/tools/proxy/proxy_actions.py +103 -0
  143. aipt_v2/tools/proxy/proxy_manager.py +789 -0
  144. aipt_v2/tools/registry.py +196 -0
  145. aipt_v2/tools/scanners/__init__.py +343 -0
  146. aipt_v2/tools/scanners/acunetix_tool.py +712 -0
  147. aipt_v2/tools/scanners/burp_tool.py +631 -0
  148. aipt_v2/tools/scanners/config.py +156 -0
  149. aipt_v2/tools/scanners/nessus_tool.py +588 -0
  150. aipt_v2/tools/scanners/zap_tool.py +612 -0
  151. aipt_v2/tools/terminal/__init__.py +5 -0
  152. aipt_v2/tools/terminal/terminal_actions.py +37 -0
  153. aipt_v2/tools/terminal/terminal_manager.py +153 -0
  154. aipt_v2/tools/terminal/terminal_session.py +449 -0
  155. aipt_v2/tools/tool_processing.py +108 -0
  156. aipt_v2/utils/__init__.py +17 -0
  157. aipt_v2/utils/logging.py +201 -0
  158. aipt_v2/utils/model_manager.py +187 -0
  159. aipt_v2/utils/searchers/__init__.py +269 -0
  160. aiptx-2.0.2.dist-info/METADATA +324 -0
  161. aiptx-2.0.2.dist-info/RECORD +165 -0
  162. aiptx-2.0.2.dist-info/WHEEL +5 -0
  163. aiptx-2.0.2.dist-info/entry_points.txt +7 -0
  164. aiptx-2.0.2.dist-info/licenses/LICENSE +21 -0
  165. aiptx-2.0.2.dist-info/top_level.txt +1 -0
@@ -0,0 +1,670 @@
1
+ """
2
+ AIPT AI-Powered Triage System
3
+
4
+ Uses LLM intelligence to prioritize vulnerability findings based on:
5
+ - Real-world exploitability (not just CVSS scores)
6
+ - Business context and impact
7
+ - Attack surface exposure
8
+ - Ease of exploitation
9
+ - Potential for chaining
10
+
11
+ This helps pentesters focus on the most impactful findings first.
12
+ """
13
+ from __future__ import annotations
14
+
15
+ import asyncio
16
+ import json
17
+ import logging
18
+ import os
19
+ from dataclasses import dataclass, field
20
+ from datetime import datetime
21
+ from enum import Enum
22
+ from typing import Any
23
+
24
+ # Import VulnerabilityType from chaining module
25
+ from aipt_v2.intelligence.chaining import VulnerabilityType
26
+
27
+
28
+ logger = logging.getLogger(__name__)
29
+
30
+
31
+ class Exploitability(Enum):
32
+ """How easy is this to exploit in the real world"""
33
+ TRIVIAL = "trivial" # Script kiddie level, public exploits
34
+ EASY = "easy" # Basic skills required
35
+ MODERATE = "moderate" # Some expertise needed
36
+ DIFFICULT = "difficult" # Advanced skills, custom exploit
37
+ THEORETICAL = "theoretical" # Requires specific conditions
38
+
39
+
40
+ class BusinessCriticality(Enum):
41
+ """Business impact if exploited"""
42
+ CRITICAL = "critical" # Business-ending, massive breach
43
+ HIGH = "high" # Significant financial/reputational damage
44
+ MEDIUM = "medium" # Notable impact, recoverable
45
+ LOW = "low" # Minor impact
46
+ MINIMAL = "minimal" # Negligible business impact
47
+
48
+
49
+ @dataclass
50
+ class RiskAssessment:
51
+ """Detailed risk assessment for a finding"""
52
+ finding: Finding
53
+
54
+ # AI-assessed factors
55
+ exploitability: Exploitability
56
+ business_criticality: BusinessCriticality
57
+
58
+ # Scores (0-100)
59
+ exploitability_score: int
60
+ impact_score: int
61
+ priority_score: int # Combined score for ranking
62
+
63
+ # AI reasoning
64
+ exploitability_reasoning: str
65
+ impact_reasoning: str
66
+ attack_scenario: str
67
+
68
+ # Recommendations
69
+ remediation_priority: int # 1-5, 1 being highest
70
+ quick_win: bool # Can be fixed quickly?
71
+ requires_immediate_action: bool
72
+
73
+ # Metadata
74
+ assessed_at: datetime = field(default_factory=datetime.utcnow)
75
+ confidence: float = 0.8
76
+
77
+ def to_dict(self) -> dict[str, Any]:
78
+ return {
79
+ "finding_title": self.finding.title,
80
+ "finding_url": self.finding.url,
81
+ "original_severity": self.finding.severity.value,
82
+ "exploitability": self.exploitability.value,
83
+ "business_criticality": self.business_criticality.value,
84
+ "exploitability_score": self.exploitability_score,
85
+ "impact_score": self.impact_score,
86
+ "priority_score": self.priority_score,
87
+ "exploitability_reasoning": self.exploitability_reasoning,
88
+ "impact_reasoning": self.impact_reasoning,
89
+ "attack_scenario": self.attack_scenario,
90
+ "remediation_priority": self.remediation_priority,
91
+ "quick_win": self.quick_win,
92
+ "requires_immediate_action": self.requires_immediate_action,
93
+ "confidence": self.confidence,
94
+ }
95
+
96
+
97
+ @dataclass
98
+ class TriageResult:
99
+ """Complete triage result for all findings"""
100
+ assessments: list[RiskAssessment]
101
+ prioritized_findings: list[Finding]
102
+
103
+ # Summary statistics
104
+ critical_count: int
105
+ immediate_action_count: int
106
+ quick_wins: list[Finding]
107
+
108
+ # AI summary
109
+ executive_summary: str
110
+ top_recommendations: list[str]
111
+
112
+ # Metadata
113
+ total_findings: int
114
+ triaged_at: datetime = field(default_factory=datetime.utcnow)
115
+
116
+ def get_top_priority(self, n: int = 10) -> list[RiskAssessment]:
117
+ """Get top N priority findings"""
118
+ sorted_assessments = sorted(
119
+ self.assessments,
120
+ key=lambda a: a.priority_score,
121
+ reverse=True
122
+ )
123
+ return sorted_assessments[:n]
124
+
125
+ def to_dict(self) -> dict[str, Any]:
126
+ return {
127
+ "total_findings": self.total_findings,
128
+ "critical_count": self.critical_count,
129
+ "immediate_action_count": self.immediate_action_count,
130
+ "quick_wins_count": len(self.quick_wins),
131
+ "executive_summary": self.executive_summary,
132
+ "top_recommendations": self.top_recommendations,
133
+ "assessments": [a.to_dict() for a in self.assessments],
134
+ }
135
+
136
+
137
+ # ============================================================================
138
+ # Exploitability Rules (heuristic-based, can be enhanced with LLM)
139
+ # ============================================================================
140
+
141
+ EXPLOITABILITY_RULES = {
142
+ # Trivial - public exploits widely available
143
+ VulnerabilityType.SQL_INJECTION: {
144
+ "base": Exploitability.EASY,
145
+ "score": 85,
146
+ "tools": ["sqlmap", "manual"],
147
+ },
148
+ VulnerabilityType.XSS_REFLECTED: {
149
+ "base": Exploitability.TRIVIAL,
150
+ "score": 90,
151
+ "tools": ["browser", "burp"],
152
+ },
153
+ VulnerabilityType.XSS_STORED: {
154
+ "base": Exploitability.TRIVIAL,
155
+ "score": 95,
156
+ "tools": ["browser"],
157
+ },
158
+ VulnerabilityType.COMMAND_INJECTION: {
159
+ "base": Exploitability.EASY,
160
+ "score": 90,
161
+ "tools": ["curl", "manual"],
162
+ },
163
+ VulnerabilityType.FILE_INCLUSION: {
164
+ "base": Exploitability.EASY,
165
+ "score": 80,
166
+ "tools": ["curl", "burp"],
167
+ },
168
+ VulnerabilityType.IDOR: {
169
+ "base": Exploitability.TRIVIAL,
170
+ "score": 95,
171
+ "tools": ["browser", "burp"],
172
+ },
173
+ VulnerabilityType.OPEN_REDIRECT: {
174
+ "base": Exploitability.TRIVIAL,
175
+ "score": 90,
176
+ "tools": ["browser"],
177
+ },
178
+ VulnerabilityType.DEFAULT_CREDENTIALS: {
179
+ "base": Exploitability.TRIVIAL,
180
+ "score": 100,
181
+ "tools": ["browser"],
182
+ },
183
+ VulnerabilityType.SSRF: {
184
+ "base": Exploitability.MODERATE,
185
+ "score": 70,
186
+ "tools": ["burp", "custom"],
187
+ },
188
+ VulnerabilityType.XXE: {
189
+ "base": Exploitability.MODERATE,
190
+ "score": 65,
191
+ "tools": ["burp", "custom"],
192
+ },
193
+ VulnerabilityType.INSECURE_DESERIALIZATION: {
194
+ "base": Exploitability.DIFFICULT,
195
+ "score": 50,
196
+ "tools": ["ysoserial", "custom"],
197
+ },
198
+ VulnerabilityType.RCE: {
199
+ "base": Exploitability.EASY, # If found, usually exploitable
200
+ "score": 85,
201
+ "tools": ["various"],
202
+ },
203
+ }
204
+
205
+ # Impact multipliers based on vulnerability type
206
+ IMPACT_MULTIPLIERS = {
207
+ VulnerabilityType.RCE: 1.0,
208
+ VulnerabilityType.SQL_INJECTION: 0.95,
209
+ VulnerabilityType.COMMAND_INJECTION: 0.95,
210
+ VulnerabilityType.AUTH_BYPASS: 0.9,
211
+ VulnerabilityType.PRIVILEGE_ESCALATION: 0.9,
212
+ VulnerabilityType.INSECURE_DESERIALIZATION: 0.85,
213
+ VulnerabilityType.XXE: 0.8,
214
+ VulnerabilityType.SSRF: 0.8,
215
+ VulnerabilityType.FILE_INCLUSION: 0.75,
216
+ VulnerabilityType.XSS_STORED: 0.7,
217
+ VulnerabilityType.IDOR: 0.7,
218
+ VulnerabilityType.XSS_REFLECTED: 0.5,
219
+ VulnerabilityType.OPEN_REDIRECT: 0.3,
220
+ VulnerabilityType.INFORMATION_DISCLOSURE: 0.4,
221
+ }
222
+
223
+
224
+ class AITriage:
225
+ """
226
+ AI-Powered Vulnerability Triage System
227
+
228
+ Analyzes findings using a combination of:
229
+ 1. Rule-based heuristics (fast, deterministic)
230
+ 2. LLM analysis (deep, contextual) - when available
231
+ 3. Business context awareness
232
+
233
+ Example:
234
+ triage = AITriage()
235
+ result = await triage.analyze(findings)
236
+ for assessment in result.get_top_priority(5):
237
+ print(f"Priority {assessment.remediation_priority}: {assessment.finding.title}")
238
+ """
239
+
240
+ def __init__(
241
+ self,
242
+ use_llm: bool = True,
243
+ llm_provider: str = "anthropic",
244
+ llm_model: str = "claude-3-haiku-20240307",
245
+ ):
246
+ self.use_llm = use_llm
247
+ self.llm_provider = llm_provider
248
+ self.llm_model = llm_model
249
+ self._llm_client = None
250
+
251
+ async def analyze(
252
+ self,
253
+ findings: list[Finding],
254
+ business_context: str = "",
255
+ target_type: str = "web_application",
256
+ ) -> TriageResult:
257
+ """
258
+ Analyze and prioritize all findings.
259
+
260
+ Args:
261
+ findings: List of vulnerability findings
262
+ business_context: Optional context about the target business
263
+ target_type: Type of target (web_application, api, mobile, etc.)
264
+
265
+ Returns:
266
+ TriageResult with prioritized findings
267
+ """
268
+ if not findings:
269
+ return TriageResult(
270
+ assessments=[],
271
+ prioritized_findings=[],
272
+ critical_count=0,
273
+ immediate_action_count=0,
274
+ quick_wins=[],
275
+ executive_summary="No findings to analyze.",
276
+ top_recommendations=[],
277
+ total_findings=0,
278
+ )
279
+
280
+ logger.info(f"Starting AI triage of {len(findings)} findings")
281
+
282
+ # Assess each finding
283
+ assessments = []
284
+ for finding in findings:
285
+ assessment = await self._assess_finding(
286
+ finding, business_context, target_type
287
+ )
288
+ assessments.append(assessment)
289
+
290
+ # Sort by priority score
291
+ assessments.sort(key=lambda a: a.priority_score, reverse=True)
292
+ prioritized = [a.finding for a in assessments]
293
+
294
+ # Identify critical and immediate action items
295
+ critical = [a for a in assessments if a.business_criticality == BusinessCriticality.CRITICAL]
296
+ immediate = [a for a in assessments if a.requires_immediate_action]
297
+ quick_wins = [a.finding for a in assessments if a.quick_win]
298
+
299
+ # Generate executive summary
300
+ summary = self._generate_executive_summary(assessments, business_context)
301
+ recommendations = self._generate_recommendations(assessments)
302
+
303
+ return TriageResult(
304
+ assessments=assessments,
305
+ prioritized_findings=prioritized,
306
+ critical_count=len(critical),
307
+ immediate_action_count=len(immediate),
308
+ quick_wins=quick_wins[:10], # Top 10 quick wins
309
+ executive_summary=summary,
310
+ top_recommendations=recommendations,
311
+ total_findings=len(findings),
312
+ )
313
+
314
+ async def _assess_finding(
315
+ self,
316
+ finding: Finding,
317
+ business_context: str,
318
+ target_type: str,
319
+ ) -> RiskAssessment:
320
+ """Assess a single finding"""
321
+ # Get base exploitability from rules
322
+ exploitability, exploitability_score = self._assess_exploitability(finding)
323
+
324
+ # Assess business impact
325
+ business_criticality, impact_score = self._assess_business_impact(
326
+ finding, business_context, target_type
327
+ )
328
+
329
+ # Calculate priority score (weighted combination)
330
+ priority_score = int(
331
+ (exploitability_score * 0.4) +
332
+ (impact_score * 0.4) +
333
+ (self._severity_to_score(finding.severity) * 0.2)
334
+ )
335
+
336
+ # Generate reasoning (use LLM if available, otherwise heuristic)
337
+ if self.use_llm and self._can_use_llm():
338
+ reasoning = await self._llm_assess(finding, business_context)
339
+ exploitability_reasoning = reasoning.get("exploitability", "")
340
+ impact_reasoning = reasoning.get("impact", "")
341
+ attack_scenario = reasoning.get("scenario", "")
342
+ else:
343
+ exploitability_reasoning = self._heuristic_exploitability_reason(finding)
344
+ impact_reasoning = self._heuristic_impact_reason(finding, business_context)
345
+ attack_scenario = self._generate_attack_scenario(finding)
346
+
347
+ # Determine remediation priority (1-5)
348
+ remediation_priority = self._calculate_remediation_priority(
349
+ priority_score, exploitability, business_criticality
350
+ )
351
+
352
+ # Check if quick win
353
+ quick_win = self._is_quick_win(finding)
354
+
355
+ # Check if requires immediate action
356
+ immediate = (
357
+ business_criticality == BusinessCriticality.CRITICAL or
358
+ (exploitability in [Exploitability.TRIVIAL, Exploitability.EASY] and
359
+ finding.severity in [Severity.CRITICAL, Severity.HIGH])
360
+ )
361
+
362
+ return RiskAssessment(
363
+ finding=finding,
364
+ exploitability=exploitability,
365
+ business_criticality=business_criticality,
366
+ exploitability_score=exploitability_score,
367
+ impact_score=impact_score,
368
+ priority_score=priority_score,
369
+ exploitability_reasoning=exploitability_reasoning,
370
+ impact_reasoning=impact_reasoning,
371
+ attack_scenario=attack_scenario,
372
+ remediation_priority=remediation_priority,
373
+ quick_win=quick_win,
374
+ requires_immediate_action=immediate,
375
+ )
376
+
377
+ def _assess_exploitability(
378
+ self,
379
+ finding: Finding,
380
+ ) -> tuple[Exploitability, int]:
381
+ """Assess how exploitable a finding is"""
382
+ rules = EXPLOITABILITY_RULES.get(finding.vuln_type)
383
+
384
+ if rules:
385
+ base = rules["base"]
386
+ score = rules["score"]
387
+ else:
388
+ # Default based on severity
389
+ severity_map = {
390
+ Severity.CRITICAL: (Exploitability.EASY, 80),
391
+ Severity.HIGH: (Exploitability.MODERATE, 60),
392
+ Severity.MEDIUM: (Exploitability.MODERATE, 50),
393
+ Severity.LOW: (Exploitability.DIFFICULT, 30),
394
+ Severity.INFO: (Exploitability.THEORETICAL, 10),
395
+ }
396
+ base, score = severity_map.get(
397
+ finding.severity,
398
+ (Exploitability.MODERATE, 50)
399
+ )
400
+
401
+ # Adjust score based on additional factors
402
+ if finding.confirmed:
403
+ score = min(100, score + 10)
404
+ if finding.exploited:
405
+ score = min(100, score + 15)
406
+ if finding.poc_command:
407
+ score = min(100, score + 10)
408
+
409
+ return base, score
410
+
411
+ def _assess_business_impact(
412
+ self,
413
+ finding: Finding,
414
+ business_context: str,
415
+ target_type: str,
416
+ ) -> tuple[BusinessCriticality, int]:
417
+ """Assess business impact of a finding"""
418
+ # Base impact from vulnerability type
419
+ multiplier = IMPACT_MULTIPLIERS.get(finding.vuln_type, 0.5)
420
+
421
+ # Base score from severity
422
+ base_score = self._severity_to_score(finding.severity)
423
+ impact_score = int(base_score * multiplier)
424
+
425
+ # Adjust for business context keywords
426
+ high_value_keywords = [
427
+ "payment", "financial", "pii", "healthcare", "hipaa",
428
+ "pci", "credentials", "admin", "authentication", "api",
429
+ ]
430
+
431
+ context_lower = (business_context + finding.url + finding.description).lower()
432
+ for keyword in high_value_keywords:
433
+ if keyword in context_lower:
434
+ impact_score = min(100, impact_score + 5)
435
+
436
+ # Determine criticality
437
+ if impact_score >= 85:
438
+ criticality = BusinessCriticality.CRITICAL
439
+ elif impact_score >= 70:
440
+ criticality = BusinessCriticality.HIGH
441
+ elif impact_score >= 50:
442
+ criticality = BusinessCriticality.MEDIUM
443
+ elif impact_score >= 30:
444
+ criticality = BusinessCriticality.LOW
445
+ else:
446
+ criticality = BusinessCriticality.MINIMAL
447
+
448
+ return criticality, impact_score
449
+
450
+ def _severity_to_score(self, severity: Severity) -> int:
451
+ """Convert severity to numeric score"""
452
+ scores = {
453
+ Severity.CRITICAL: 100,
454
+ Severity.HIGH: 80,
455
+ Severity.MEDIUM: 50,
456
+ Severity.LOW: 25,
457
+ Severity.INFO: 10,
458
+ }
459
+ return scores.get(severity, 50)
460
+
461
+ def _calculate_remediation_priority(
462
+ self,
463
+ priority_score: int,
464
+ exploitability: Exploitability,
465
+ criticality: BusinessCriticality,
466
+ ) -> int:
467
+ """Calculate remediation priority (1-5, 1 highest)"""
468
+ if priority_score >= 85 or criticality == BusinessCriticality.CRITICAL:
469
+ return 1
470
+ if priority_score >= 70 or criticality == BusinessCriticality.HIGH:
471
+ return 2
472
+ if priority_score >= 50:
473
+ return 3
474
+ if priority_score >= 30:
475
+ return 4
476
+ return 5
477
+
478
+ def _is_quick_win(self, finding: Finding) -> bool:
479
+ """Determine if a finding is a quick win to fix"""
480
+ quick_win_types = [
481
+ VulnerabilityType.DEFAULT_CREDENTIALS,
482
+ VulnerabilityType.MISCONFIGURATION,
483
+ VulnerabilityType.DIRECTORY_LISTING,
484
+ VulnerabilityType.INFORMATION_DISCLOSURE,
485
+ VulnerabilityType.OPEN_REDIRECT,
486
+ VulnerabilityType.CORS_MISCONFIGURATION,
487
+ ]
488
+ return finding.vuln_type in quick_win_types
489
+
490
+ def _heuristic_exploitability_reason(self, finding: Finding) -> str:
491
+ """Generate exploitability reasoning without LLM"""
492
+ rules = EXPLOITABILITY_RULES.get(finding.vuln_type)
493
+
494
+ if rules:
495
+ tools = ", ".join(rules.get("tools", ["manual"]))
496
+ return (
497
+ f"This {finding.vuln_type.value} vulnerability is considered "
498
+ f"{rules['base'].value} to exploit. Common tools include: {tools}. "
499
+ f"{'Confirmed and exploited in testing.' if finding.exploited else ''}"
500
+ )
501
+
502
+ return f"Exploitability assessment based on {finding.severity.value} severity."
503
+
504
+ def _heuristic_impact_reason(
505
+ self,
506
+ finding: Finding,
507
+ business_context: str,
508
+ ) -> str:
509
+ """Generate impact reasoning without LLM"""
510
+ impacts = {
511
+ VulnerabilityType.RCE: "allows complete server compromise and data access",
512
+ VulnerabilityType.SQL_INJECTION: "could lead to full database compromise",
513
+ VulnerabilityType.AUTH_BYPASS: "enables unauthorized access to protected resources",
514
+ VulnerabilityType.IDOR: "allows access to other users' data",
515
+ VulnerabilityType.XSS_STORED: "can compromise any user who views affected pages",
516
+ VulnerabilityType.SSRF: "may expose internal network and services",
517
+ }
518
+
519
+ impact = impacts.get(
520
+ finding.vuln_type,
521
+ f"could have {finding.severity.value} impact on the application"
522
+ )
523
+
524
+ return f"This vulnerability {impact}."
525
+
526
+ def _generate_attack_scenario(self, finding: Finding) -> str:
527
+ """Generate a realistic attack scenario"""
528
+ scenarios = {
529
+ VulnerabilityType.SQL_INJECTION: (
530
+ "1. Attacker identifies SQL injection point\n"
531
+ "2. Uses sqlmap or manual techniques to extract data\n"
532
+ "3. Dumps user credentials, PII, or business data\n"
533
+ "4. May escalate to OS command execution via xp_cmdshell"
534
+ ),
535
+ VulnerabilityType.XSS_STORED: (
536
+ "1. Attacker injects malicious JavaScript\n"
537
+ "2. Script executes when other users view the page\n"
538
+ "3. Steals session cookies or credentials\n"
539
+ "4. Performs actions as the victim user"
540
+ ),
541
+ VulnerabilityType.SSRF: (
542
+ "1. Attacker crafts request to internal resources\n"
543
+ "2. Accesses internal admin panels or databases\n"
544
+ "3. Reads cloud metadata (AWS keys, etc.)\n"
545
+ "4. Pivots to attack internal network"
546
+ ),
547
+ VulnerabilityType.RCE: (
548
+ "1. Attacker achieves code execution\n"
549
+ "2. Establishes reverse shell or backdoor\n"
550
+ "3. Dumps credentials and sensitive data\n"
551
+ "4. Moves laterally through network"
552
+ ),
553
+ VulnerabilityType.IDOR: (
554
+ "1. Attacker manipulates object references\n"
555
+ "2. Accesses other users' records\n"
556
+ "3. Extracts or modifies sensitive data\n"
557
+ "4. May enumerate all records in system"
558
+ ),
559
+ }
560
+
561
+ return scenarios.get(
562
+ finding.vuln_type,
563
+ f"Attacker exploits {finding.vuln_type.value} at {finding.url}"
564
+ )
565
+
566
+ def _can_use_llm(self) -> bool:
567
+ """Check if LLM is available"""
568
+ # Check for API key
569
+ if self.llm_provider == "anthropic":
570
+ return bool(os.getenv("ANTHROPIC_API_KEY"))
571
+ if self.llm_provider == "openai":
572
+ return bool(os.getenv("OPENAI_API_KEY"))
573
+ return False
574
+
575
+ async def _llm_assess(
576
+ self,
577
+ finding: Finding,
578
+ business_context: str,
579
+ ) -> dict[str, str]:
580
+ """Use LLM to assess finding (when available)"""
581
+ # This would integrate with litellm or direct API calls
582
+ # For now, return empty to fall back to heuristics
583
+ return {}
584
+
585
+ def _generate_executive_summary(
586
+ self,
587
+ assessments: list[RiskAssessment],
588
+ business_context: str,
589
+ ) -> str:
590
+ """Generate executive summary of findings"""
591
+ if not assessments:
592
+ return "No vulnerabilities were identified during this assessment."
593
+
594
+ critical = sum(1 for a in assessments if a.business_criticality == BusinessCriticality.CRITICAL)
595
+ high = sum(1 for a in assessments if a.business_criticality == BusinessCriticality.HIGH)
596
+ immediate = sum(1 for a in assessments if a.requires_immediate_action)
597
+
598
+ lines = [
599
+ f"## Executive Summary\n",
600
+ f"This assessment identified **{len(assessments)} vulnerabilities** requiring attention.\n",
601
+ ]
602
+
603
+ if critical > 0 or immediate > 0:
604
+ lines.append(
605
+ f"**URGENT:** {critical} critical and {immediate} immediate-action items "
606
+ f"require priority remediation.\n"
607
+ )
608
+
609
+ lines.append(f"\n### Risk Breakdown\n")
610
+ lines.append(f"- **Critical Impact:** {critical}")
611
+ lines.append(f"- **High Impact:** {high}")
612
+ lines.append(f"- **Requires Immediate Action:** {immediate}")
613
+
614
+ # Top risk
615
+ if assessments:
616
+ top = assessments[0]
617
+ lines.append(
618
+ f"\n### Highest Priority Finding\n"
619
+ f"**{top.finding.title}** at `{top.finding.url}`\n"
620
+ f"- Exploitability: {top.exploitability.value}\n"
621
+ f"- Business Impact: {top.business_criticality.value}\n"
622
+ )
623
+
624
+ return "\n".join(lines)
625
+
626
+ def _generate_recommendations(
627
+ self,
628
+ assessments: list[RiskAssessment],
629
+ ) -> list[str]:
630
+ """Generate top remediation recommendations"""
631
+ recommendations = []
632
+
633
+ # Group by priority
634
+ priority_1 = [a for a in assessments if a.remediation_priority == 1]
635
+ quick_wins = [a for a in assessments if a.quick_win]
636
+
637
+ if priority_1:
638
+ recommendations.append(
639
+ f"Address {len(priority_1)} critical-priority items immediately"
640
+ )
641
+
642
+ if quick_wins:
643
+ recommendations.append(
644
+ f"Resolve {len(quick_wins)} quick-win items to reduce attack surface"
645
+ )
646
+
647
+ # Add specific recommendations based on finding types
648
+ vuln_types = {a.finding.vuln_type for a in assessments}
649
+
650
+ if VulnerabilityType.SQL_INJECTION in vuln_types:
651
+ recommendations.append(
652
+ "Implement parameterized queries to eliminate SQL injection"
653
+ )
654
+
655
+ if VulnerabilityType.XSS_STORED in vuln_types or VulnerabilityType.XSS_REFLECTED in vuln_types:
656
+ recommendations.append(
657
+ "Deploy Content Security Policy and output encoding"
658
+ )
659
+
660
+ if VulnerabilityType.IDOR in vuln_types:
661
+ recommendations.append(
662
+ "Implement proper authorization checks on all object access"
663
+ )
664
+
665
+ if VulnerabilityType.DEFAULT_CREDENTIALS in vuln_types:
666
+ recommendations.append(
667
+ "Change all default credentials immediately"
668
+ )
669
+
670
+ return recommendations[:10] # Top 10
@@ -0,0 +1,5 @@
1
+ """
2
+ AIPT Interface Module - TUI and CLI interfaces
3
+ """
4
+
5
+ __all__ = []