souleyez 2.43.28__py3-none-any.whl → 2.43.32__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 (356) hide show
  1. souleyez/__init__.py +1 -2
  2. souleyez/ai/__init__.py +21 -15
  3. souleyez/ai/action_mapper.py +249 -150
  4. souleyez/ai/chain_advisor.py +116 -100
  5. souleyez/ai/claude_provider.py +29 -28
  6. souleyez/ai/context_builder.py +80 -62
  7. souleyez/ai/executor.py +158 -117
  8. souleyez/ai/feedback_handler.py +136 -121
  9. souleyez/ai/llm_factory.py +27 -20
  10. souleyez/ai/llm_provider.py +4 -2
  11. souleyez/ai/ollama_provider.py +6 -9
  12. souleyez/ai/ollama_service.py +44 -37
  13. souleyez/ai/path_scorer.py +91 -76
  14. souleyez/ai/recommender.py +176 -144
  15. souleyez/ai/report_context.py +74 -73
  16. souleyez/ai/report_service.py +84 -66
  17. souleyez/ai/result_parser.py +222 -229
  18. souleyez/ai/safety.py +67 -44
  19. souleyez/auth/__init__.py +23 -22
  20. souleyez/auth/audit.py +36 -26
  21. souleyez/auth/engagement_access.py +65 -48
  22. souleyez/auth/permissions.py +14 -3
  23. souleyez/auth/session_manager.py +54 -37
  24. souleyez/auth/user_manager.py +109 -64
  25. souleyez/commands/audit.py +40 -43
  26. souleyez/commands/auth.py +35 -15
  27. souleyez/commands/deliverables.py +55 -50
  28. souleyez/commands/engagement.py +47 -28
  29. souleyez/commands/license.py +32 -23
  30. souleyez/commands/screenshots.py +36 -32
  31. souleyez/commands/user.py +82 -36
  32. souleyez/config.py +52 -44
  33. souleyez/core/credential_tester.py +87 -81
  34. souleyez/core/cve_mappings.py +179 -192
  35. souleyez/core/cve_matcher.py +162 -148
  36. souleyez/core/msf_auto_mapper.py +100 -83
  37. souleyez/core/msf_chain_engine.py +294 -256
  38. souleyez/core/msf_database.py +153 -70
  39. souleyez/core/msf_integration.py +679 -673
  40. souleyez/core/msf_rpc_client.py +40 -42
  41. souleyez/core/msf_rpc_manager.py +77 -79
  42. souleyez/core/msf_sync_manager.py +241 -181
  43. souleyez/core/network_utils.py +22 -15
  44. souleyez/core/parser_handler.py +34 -25
  45. souleyez/core/pending_chains.py +114 -63
  46. souleyez/core/templates.py +158 -107
  47. souleyez/core/tool_chaining.py +9592 -2879
  48. souleyez/core/version_utils.py +79 -94
  49. souleyez/core/vuln_correlation.py +136 -89
  50. souleyez/core/web_utils.py +33 -32
  51. souleyez/data/wordlists/ad_users.txt +378 -0
  52. souleyez/data/wordlists/api_endpoints_large.txt +769 -0
  53. souleyez/data/wordlists/home_dir_sensitive.txt +39 -0
  54. souleyez/data/wordlists/lfi_payloads.txt +82 -0
  55. souleyez/data/wordlists/passwords_brute.txt +1548 -0
  56. souleyez/data/wordlists/passwords_crack.txt +2479 -0
  57. souleyez/data/wordlists/passwords_spray.txt +386 -0
  58. souleyez/data/wordlists/subdomains_large.txt +5057 -0
  59. souleyez/data/wordlists/usernames_common.txt +694 -0
  60. souleyez/data/wordlists/web_dirs_large.txt +4769 -0
  61. souleyez/detection/__init__.py +1 -1
  62. souleyez/detection/attack_signatures.py +12 -17
  63. souleyez/detection/mitre_mappings.py +61 -55
  64. souleyez/detection/validator.py +97 -86
  65. souleyez/devtools.py +23 -10
  66. souleyez/docs/README.md +4 -4
  67. souleyez/docs/api-reference/cli-commands.md +2 -2
  68. souleyez/docs/developer-guide/adding-new-tools.md +562 -0
  69. souleyez/docs/user-guide/auto-chaining.md +30 -8
  70. souleyez/docs/user-guide/getting-started.md +1 -1
  71. souleyez/docs/user-guide/installation.md +26 -3
  72. souleyez/docs/user-guide/metasploit-integration.md +2 -2
  73. souleyez/docs/user-guide/rbac.md +1 -1
  74. souleyez/docs/user-guide/scope-management.md +1 -1
  75. souleyez/docs/user-guide/siem-integration.md +1 -1
  76. souleyez/docs/user-guide/tools-reference.md +1 -8
  77. souleyez/docs/user-guide/worker-management.md +1 -1
  78. souleyez/engine/background.py +1238 -535
  79. souleyez/engine/base.py +4 -1
  80. souleyez/engine/job_status.py +17 -49
  81. souleyez/engine/log_sanitizer.py +103 -77
  82. souleyez/engine/manager.py +38 -7
  83. souleyez/engine/result_handler.py +2198 -1550
  84. souleyez/engine/worker_manager.py +50 -41
  85. souleyez/export/evidence_bundle.py +72 -62
  86. souleyez/feature_flags/features.py +16 -20
  87. souleyez/feature_flags.py +5 -9
  88. souleyez/handlers/__init__.py +11 -0
  89. souleyez/handlers/base.py +188 -0
  90. souleyez/handlers/bash_handler.py +277 -0
  91. souleyez/handlers/bloodhound_handler.py +243 -0
  92. souleyez/handlers/certipy_handler.py +311 -0
  93. souleyez/handlers/crackmapexec_handler.py +486 -0
  94. souleyez/handlers/dnsrecon_handler.py +344 -0
  95. souleyez/handlers/enum4linux_handler.py +400 -0
  96. souleyez/handlers/evil_winrm_handler.py +493 -0
  97. souleyez/handlers/ffuf_handler.py +815 -0
  98. souleyez/handlers/gobuster_handler.py +1114 -0
  99. souleyez/handlers/gpp_extract_handler.py +334 -0
  100. souleyez/handlers/hashcat_handler.py +444 -0
  101. souleyez/handlers/hydra_handler.py +563 -0
  102. souleyez/handlers/impacket_getuserspns_handler.py +343 -0
  103. souleyez/handlers/impacket_psexec_handler.py +222 -0
  104. souleyez/handlers/impacket_secretsdump_handler.py +426 -0
  105. souleyez/handlers/john_handler.py +286 -0
  106. souleyez/handlers/katana_handler.py +425 -0
  107. souleyez/handlers/kerbrute_handler.py +298 -0
  108. souleyez/handlers/ldapsearch_handler.py +636 -0
  109. souleyez/handlers/lfi_extract_handler.py +464 -0
  110. souleyez/handlers/msf_auxiliary_handler.py +408 -0
  111. souleyez/handlers/msf_exploit_handler.py +380 -0
  112. souleyez/handlers/nikto_handler.py +413 -0
  113. souleyez/handlers/nmap_handler.py +821 -0
  114. souleyez/handlers/nuclei_handler.py +359 -0
  115. souleyez/handlers/nxc_handler.py +371 -0
  116. souleyez/handlers/rdp_sec_check_handler.py +353 -0
  117. souleyez/handlers/registry.py +288 -0
  118. souleyez/handlers/responder_handler.py +232 -0
  119. souleyez/handlers/service_explorer_handler.py +434 -0
  120. souleyez/handlers/smbclient_handler.py +344 -0
  121. souleyez/handlers/smbmap_handler.py +510 -0
  122. souleyez/handlers/smbpasswd_handler.py +296 -0
  123. souleyez/handlers/sqlmap_handler.py +1116 -0
  124. souleyez/handlers/theharvester_handler.py +601 -0
  125. souleyez/handlers/whois_handler.py +277 -0
  126. souleyez/handlers/wpscan_handler.py +554 -0
  127. souleyez/history.py +32 -16
  128. souleyez/importers/msf_importer.py +106 -75
  129. souleyez/importers/smart_importer.py +208 -147
  130. souleyez/integrations/siem/__init__.py +10 -10
  131. souleyez/integrations/siem/base.py +17 -18
  132. souleyez/integrations/siem/elastic.py +108 -122
  133. souleyez/integrations/siem/factory.py +207 -80
  134. souleyez/integrations/siem/googlesecops.py +146 -154
  135. souleyez/integrations/siem/rule_mappings/__init__.py +1 -1
  136. souleyez/integrations/siem/rule_mappings/wazuh_rules.py +8 -5
  137. souleyez/integrations/siem/sentinel.py +107 -109
  138. souleyez/integrations/siem/splunk.py +246 -212
  139. souleyez/integrations/siem/wazuh.py +65 -71
  140. souleyez/integrations/wazuh/__init__.py +5 -5
  141. souleyez/integrations/wazuh/client.py +70 -93
  142. souleyez/integrations/wazuh/config.py +85 -57
  143. souleyez/integrations/wazuh/host_mapper.py +28 -36
  144. souleyez/integrations/wazuh/sync.py +78 -68
  145. souleyez/intelligence/__init__.py +4 -5
  146. souleyez/intelligence/correlation_analyzer.py +309 -295
  147. souleyez/intelligence/exploit_knowledge.py +661 -623
  148. souleyez/intelligence/exploit_suggestions.py +159 -139
  149. souleyez/intelligence/gap_analyzer.py +132 -97
  150. souleyez/intelligence/gap_detector.py +251 -214
  151. souleyez/intelligence/sensitive_tables.py +266 -129
  152. souleyez/intelligence/service_parser.py +137 -123
  153. souleyez/intelligence/surface_analyzer.py +407 -268
  154. souleyez/intelligence/target_parser.py +159 -162
  155. souleyez/licensing/__init__.py +6 -6
  156. souleyez/licensing/validator.py +17 -19
  157. souleyez/log_config.py +79 -54
  158. souleyez/main.py +1505 -687
  159. souleyez/migrations/fix_job_counter.py +16 -14
  160. souleyez/parsers/bloodhound_parser.py +41 -39
  161. souleyez/parsers/crackmapexec_parser.py +178 -111
  162. souleyez/parsers/dalfox_parser.py +72 -77
  163. souleyez/parsers/dnsrecon_parser.py +103 -91
  164. souleyez/parsers/enum4linux_parser.py +183 -153
  165. souleyez/parsers/ffuf_parser.py +29 -25
  166. souleyez/parsers/gobuster_parser.py +301 -41
  167. souleyez/parsers/hashcat_parser.py +324 -79
  168. souleyez/parsers/http_fingerprint_parser.py +350 -103
  169. souleyez/parsers/hydra_parser.py +131 -111
  170. souleyez/parsers/impacket_parser.py +231 -178
  171. souleyez/parsers/john_parser.py +98 -86
  172. souleyez/parsers/katana_parser.py +316 -0
  173. souleyez/parsers/msf_parser.py +943 -498
  174. souleyez/parsers/nikto_parser.py +346 -65
  175. souleyez/parsers/nmap_parser.py +262 -174
  176. souleyez/parsers/nuclei_parser.py +40 -44
  177. souleyez/parsers/responder_parser.py +26 -26
  178. souleyez/parsers/searchsploit_parser.py +74 -74
  179. souleyez/parsers/service_explorer_parser.py +279 -0
  180. souleyez/parsers/smbmap_parser.py +180 -124
  181. souleyez/parsers/sqlmap_parser.py +434 -308
  182. souleyez/parsers/theharvester_parser.py +75 -57
  183. souleyez/parsers/whois_parser.py +135 -94
  184. souleyez/parsers/wpscan_parser.py +278 -190
  185. souleyez/plugins/afp.py +44 -36
  186. souleyez/plugins/afp_brute.py +114 -46
  187. souleyez/plugins/ard.py +48 -37
  188. souleyez/plugins/bloodhound.py +95 -61
  189. souleyez/plugins/certipy.py +303 -0
  190. souleyez/plugins/crackmapexec.py +186 -85
  191. souleyez/plugins/dalfox.py +120 -59
  192. souleyez/plugins/dns_hijack.py +146 -41
  193. souleyez/plugins/dnsrecon.py +97 -61
  194. souleyez/plugins/enum4linux.py +91 -66
  195. souleyez/plugins/evil_winrm.py +291 -0
  196. souleyez/plugins/ffuf.py +166 -90
  197. souleyez/plugins/firmware_extract.py +133 -29
  198. souleyez/plugins/gobuster.py +387 -190
  199. souleyez/plugins/gpp_extract.py +393 -0
  200. souleyez/plugins/hashcat.py +100 -73
  201. souleyez/plugins/http_fingerprint.py +854 -267
  202. souleyez/plugins/hydra.py +566 -200
  203. souleyez/plugins/impacket_getnpusers.py +117 -69
  204. souleyez/plugins/impacket_psexec.py +84 -64
  205. souleyez/plugins/impacket_secretsdump.py +103 -69
  206. souleyez/plugins/impacket_smbclient.py +89 -75
  207. souleyez/plugins/john.py +86 -69
  208. souleyez/plugins/katana.py +313 -0
  209. souleyez/plugins/kerbrute.py +237 -0
  210. souleyez/plugins/lfi_extract.py +541 -0
  211. souleyez/plugins/macos_ssh.py +117 -48
  212. souleyez/plugins/mdns.py +35 -30
  213. souleyez/plugins/msf_auxiliary.py +253 -130
  214. souleyez/plugins/msf_exploit.py +239 -161
  215. souleyez/plugins/nikto.py +134 -78
  216. souleyez/plugins/nmap.py +275 -91
  217. souleyez/plugins/nuclei.py +180 -89
  218. souleyez/plugins/nxc.py +285 -0
  219. souleyez/plugins/plugin_base.py +35 -36
  220. souleyez/plugins/plugin_template.py +13 -5
  221. souleyez/plugins/rdp_sec_check.py +130 -0
  222. souleyez/plugins/responder.py +112 -71
  223. souleyez/plugins/router_http_brute.py +76 -65
  224. souleyez/plugins/router_ssh_brute.py +118 -41
  225. souleyez/plugins/router_telnet_brute.py +124 -42
  226. souleyez/plugins/routersploit.py +91 -59
  227. souleyez/plugins/routersploit_exploit.py +77 -55
  228. souleyez/plugins/searchsploit.py +91 -77
  229. souleyez/plugins/service_explorer.py +1160 -0
  230. souleyez/plugins/smbmap.py +122 -72
  231. souleyez/plugins/smbpasswd.py +215 -0
  232. souleyez/plugins/sqlmap.py +301 -113
  233. souleyez/plugins/theharvester.py +127 -75
  234. souleyez/plugins/tr069.py +79 -57
  235. souleyez/plugins/upnp.py +65 -47
  236. souleyez/plugins/upnp_abuse.py +73 -55
  237. souleyez/plugins/vnc_access.py +129 -42
  238. souleyez/plugins/vnc_brute.py +109 -38
  239. souleyez/plugins/whois.py +77 -58
  240. souleyez/plugins/wpscan.py +173 -69
  241. souleyez/reporting/__init__.py +2 -1
  242. souleyez/reporting/attack_chain.py +411 -346
  243. souleyez/reporting/charts.py +436 -501
  244. souleyez/reporting/compliance_mappings.py +334 -201
  245. souleyez/reporting/detection_report.py +126 -125
  246. souleyez/reporting/formatters.py +828 -591
  247. souleyez/reporting/generator.py +386 -302
  248. souleyez/reporting/metrics.py +72 -75
  249. souleyez/scanner.py +35 -29
  250. souleyez/security/__init__.py +37 -11
  251. souleyez/security/scope_validator.py +175 -106
  252. souleyez/security/validation.py +223 -149
  253. souleyez/security.py +22 -6
  254. souleyez/storage/credentials.py +247 -186
  255. souleyez/storage/crypto.py +296 -129
  256. souleyez/storage/database.py +73 -50
  257. souleyez/storage/db.py +58 -36
  258. souleyez/storage/deliverable_evidence.py +177 -128
  259. souleyez/storage/deliverable_exporter.py +282 -246
  260. souleyez/storage/deliverable_templates.py +134 -116
  261. souleyez/storage/deliverables.py +135 -130
  262. souleyez/storage/engagements.py +109 -56
  263. souleyez/storage/evidence.py +181 -152
  264. souleyez/storage/execution_log.py +31 -17
  265. souleyez/storage/exploit_attempts.py +93 -57
  266. souleyez/storage/exploits.py +67 -36
  267. souleyez/storage/findings.py +48 -61
  268. souleyez/storage/hosts.py +176 -144
  269. souleyez/storage/migrate_to_engagements.py +43 -19
  270. souleyez/storage/migrations/_001_add_credential_enhancements.py +22 -12
  271. souleyez/storage/migrations/_002_add_status_tracking.py +10 -7
  272. souleyez/storage/migrations/_003_add_execution_log.py +14 -8
  273. souleyez/storage/migrations/_005_screenshots.py +13 -5
  274. souleyez/storage/migrations/_006_deliverables.py +13 -5
  275. souleyez/storage/migrations/_007_deliverable_templates.py +12 -7
  276. souleyez/storage/migrations/_008_add_nuclei_table.py +10 -4
  277. souleyez/storage/migrations/_010_evidence_linking.py +17 -10
  278. souleyez/storage/migrations/_011_timeline_tracking.py +20 -13
  279. souleyez/storage/migrations/_012_team_collaboration.py +34 -21
  280. souleyez/storage/migrations/_013_add_host_tags.py +12 -6
  281. souleyez/storage/migrations/_014_exploit_attempts.py +22 -10
  282. souleyez/storage/migrations/_015_add_mac_os_fields.py +15 -7
  283. souleyez/storage/migrations/_016_add_domain_field.py +10 -4
  284. souleyez/storage/migrations/_017_msf_sessions.py +16 -8
  285. souleyez/storage/migrations/_018_add_osint_target.py +10 -6
  286. souleyez/storage/migrations/_019_add_engagement_type.py +10 -6
  287. souleyez/storage/migrations/_020_add_rbac.py +36 -15
  288. souleyez/storage/migrations/_021_wazuh_integration.py +20 -8
  289. souleyez/storage/migrations/_022_wazuh_indexer_columns.py +6 -4
  290. souleyez/storage/migrations/_023_fix_detection_results_fk.py +16 -6
  291. souleyez/storage/migrations/_024_wazuh_vulnerabilities.py +26 -10
  292. souleyez/storage/migrations/_025_multi_siem_support.py +3 -5
  293. souleyez/storage/migrations/_026_add_engagement_scope.py +31 -12
  294. souleyez/storage/migrations/_027_multi_siem_persistence.py +32 -15
  295. souleyez/storage/migrations/__init__.py +26 -26
  296. souleyez/storage/migrations/migration_manager.py +19 -19
  297. souleyez/storage/msf_sessions.py +100 -65
  298. souleyez/storage/osint.py +17 -24
  299. souleyez/storage/recommendation_engine.py +269 -235
  300. souleyez/storage/screenshots.py +33 -32
  301. souleyez/storage/smb_shares.py +136 -92
  302. souleyez/storage/sqlmap_data.py +183 -128
  303. souleyez/storage/team_collaboration.py +135 -141
  304. souleyez/storage/timeline_tracker.py +122 -94
  305. souleyez/storage/wazuh_vulns.py +64 -66
  306. souleyez/storage/web_paths.py +33 -37
  307. souleyez/testing/credential_tester.py +221 -205
  308. souleyez/ui/__init__.py +1 -1
  309. souleyez/ui/ai_quotes.py +12 -12
  310. souleyez/ui/attack_surface.py +2439 -1516
  311. souleyez/ui/chain_rules_view.py +914 -382
  312. souleyez/ui/correlation_view.py +312 -230
  313. souleyez/ui/dashboard.py +2382 -1130
  314. souleyez/ui/deliverables_view.py +148 -62
  315. souleyez/ui/design_system.py +13 -13
  316. souleyez/ui/errors.py +49 -49
  317. souleyez/ui/evidence_linking_view.py +284 -179
  318. souleyez/ui/evidence_vault.py +393 -285
  319. souleyez/ui/exploit_suggestions_view.py +555 -349
  320. souleyez/ui/export_view.py +100 -66
  321. souleyez/ui/gap_analysis_view.py +315 -171
  322. souleyez/ui/help_system.py +105 -97
  323. souleyez/ui/intelligence_view.py +436 -293
  324. souleyez/ui/interactive.py +23142 -10430
  325. souleyez/ui/interactive_selector.py +75 -68
  326. souleyez/ui/log_formatter.py +47 -39
  327. souleyez/ui/menu_components.py +22 -13
  328. souleyez/ui/msf_auxiliary_menu.py +184 -133
  329. souleyez/ui/pending_chains_view.py +336 -172
  330. souleyez/ui/progress_indicators.py +5 -3
  331. souleyez/ui/recommendations_view.py +195 -137
  332. souleyez/ui/rule_builder.py +343 -225
  333. souleyez/ui/setup_wizard.py +678 -284
  334. souleyez/ui/shortcuts.py +217 -165
  335. souleyez/ui/splunk_gap_analysis_view.py +452 -270
  336. souleyez/ui/splunk_vulns_view.py +139 -86
  337. souleyez/ui/team_dashboard.py +498 -335
  338. souleyez/ui/template_selector.py +196 -105
  339. souleyez/ui/terminal.py +6 -6
  340. souleyez/ui/timeline_view.py +198 -127
  341. souleyez/ui/tool_setup.py +264 -164
  342. souleyez/ui/tutorial.py +202 -72
  343. souleyez/ui/tutorial_state.py +40 -40
  344. souleyez/ui/wazuh_vulns_view.py +235 -141
  345. souleyez/ui/wordlist_browser.py +260 -107
  346. souleyez/ui.py +464 -312
  347. souleyez/utils/tool_checker.py +427 -367
  348. souleyez/utils.py +33 -29
  349. souleyez/wordlists.py +134 -167
  350. {souleyez-2.43.28.dist-info → souleyez-2.43.32.dist-info}/METADATA +1 -1
  351. souleyez-2.43.32.dist-info/RECORD +441 -0
  352. {souleyez-2.43.28.dist-info → souleyez-2.43.32.dist-info}/WHEEL +1 -1
  353. souleyez-2.43.28.dist-info/RECORD +0 -379
  354. {souleyez-2.43.28.dist-info → souleyez-2.43.32.dist-info}/entry_points.txt +0 -0
  355. {souleyez-2.43.28.dist-info → souleyez-2.43.32.dist-info}/licenses/LICENSE +0 -0
  356. {souleyez-2.43.28.dist-info → souleyez-2.43.32.dist-info}/top_level.txt +0 -0
@@ -15,10 +15,10 @@ console = Console()
15
15
 
16
16
  # Severity colors
17
17
  SEVERITY_COLORS = {
18
- 'Critical': 'red',
19
- 'High': 'yellow',
20
- 'Medium': 'white',
21
- 'Low': 'bright_black'
18
+ "Critical": "red",
19
+ "High": "yellow",
20
+ "Medium": "white",
21
+ "Low": "bright_black",
22
22
  }
23
23
 
24
24
 
@@ -45,15 +45,29 @@ def show_splunk_vulns_view(engagement_id: int, engagement_name: str = "") -> Non
45
45
 
46
46
  # Header
47
47
  click.echo("\n┌" + "─" * (width - 2) + "┐")
48
- click.echo("│" + click.style(" SPLUNK VULNERABILITIES ".center(width - 2), bold=True, fg='cyan') + "│")
48
+ click.echo(
49
+ "│"
50
+ + click.style(
51
+ " SPLUNK VULNERABILITIES ".center(width - 2), bold=True, fg="cyan"
52
+ )
53
+ + "│"
54
+ )
49
55
  click.echo("└" + "─" * (width - 2) + "┘")
50
56
  click.echo()
51
57
 
52
58
  # Check if Splunk is configured
53
59
  config = WazuhConfig.get_config(engagement_id)
54
60
 
55
- if not config or config.get('siem_type') != 'splunk' or not config.get('enabled'):
56
- click.echo(click.style(" Splunk is not configured for this engagement.", fg='yellow'))
61
+ if (
62
+ not config
63
+ or config.get("siem_type") != "splunk"
64
+ or not config.get("enabled")
65
+ ):
66
+ click.echo(
67
+ click.style(
68
+ " Splunk is not configured for this engagement.", fg="yellow"
69
+ )
70
+ )
57
71
  click.echo()
58
72
  click.echo(" Configure Splunk in Settings -> SIEM Integration")
59
73
  click.echo()
@@ -62,7 +76,7 @@ def show_splunk_vulns_view(engagement_id: int, engagement_name: str = "") -> Non
62
76
  click.echo(" [q] Back")
63
77
  click.echo()
64
78
  try:
65
- if click.getchar().lower() == 'q':
79
+ if click.getchar().lower() == "q":
66
80
  return
67
81
  except (KeyboardInterrupt, EOFError):
68
82
  return
@@ -71,15 +85,18 @@ def show_splunk_vulns_view(engagement_id: int, engagement_name: str = "") -> Non
71
85
  # Get Splunk client
72
86
  try:
73
87
  from souleyez.integrations.siem.splunk import SplunkSIEMClient
74
- client = SplunkSIEMClient.from_config({
75
- 'api_url': config.get('api_url', ''),
76
- 'username': config.get('username', ''),
77
- 'password': config.get('password', ''),
78
- 'verify_ssl': config.get('verify_ssl', False),
79
- 'default_index': config.get('default_index', 'main'),
80
- })
88
+
89
+ client = SplunkSIEMClient.from_config(
90
+ {
91
+ "api_url": config.get("api_url", ""),
92
+ "username": config.get("username", ""),
93
+ "password": config.get("password", ""),
94
+ "verify_ssl": config.get("verify_ssl", False),
95
+ "default_index": config.get("default_index", "main"),
96
+ }
97
+ )
81
98
  except Exception as e:
82
- click.echo(click.style(f" Error connecting to Splunk: {e}", fg='red'))
99
+ click.echo(click.style(f" Error connecting to Splunk: {e}", fg="red"))
83
100
  click.echo()
84
101
  click.pause(" Press any key to return...")
85
102
  return
@@ -88,23 +105,30 @@ def show_splunk_vulns_view(engagement_id: int, engagement_name: str = "") -> Non
88
105
  try:
89
106
  summary = client.get_vulnerability_summary()
90
107
  vulns = client.get_vulnerabilities(
91
- severity=severity_filter,
92
- agent_name=host_filter,
93
- limit=1000
108
+ severity=severity_filter, agent_name=host_filter, limit=1000
94
109
  )
95
110
  except Exception as e:
96
- click.echo(click.style(f" Error querying Splunk: {e}", fg='red'))
111
+ click.echo(click.style(f" Error querying Splunk: {e}", fg="red"))
97
112
  click.echo()
98
113
  click.echo(" Make sure the wazuh_vulns index exists and has data.")
99
- click.echo(" Run the vuln sync script: python3 scripts/wazuh_vuln_to_splunk.py --all")
114
+ click.echo(
115
+ " Run the vuln sync script: python3 scripts/wazuh_vuln_to_splunk.py --all"
116
+ )
100
117
  click.echo()
101
118
  click.pause(" Press any key to return...")
102
119
  return
103
120
 
104
121
  # Display table with summary
105
122
  page, total_pages = _display_vulns_table(
106
- console, vulns, page, page_size, view_all,
107
- severity_filter, host_filter, width, summary
123
+ console,
124
+ vulns,
125
+ page,
126
+ page_size,
127
+ view_all,
128
+ severity_filter,
129
+ host_filter,
130
+ width,
131
+ summary,
108
132
  )
109
133
 
110
134
  # Menu
@@ -123,27 +147,27 @@ def show_splunk_vulns_view(engagement_id: int, engagement_name: str = "") -> Non
123
147
  try:
124
148
  choice = input(" Select option: ").strip().lower()
125
149
 
126
- if choice == 'q':
150
+ if choice == "q":
127
151
  return
128
- elif choice == 'r':
152
+ elif choice == "r":
129
153
  continue # Refresh
130
- elif choice == 'i':
154
+ elif choice == "i":
131
155
  _interactive_vulns_mode(vulns)
132
- elif choice == 't':
156
+ elif choice == "t":
133
157
  view_all = not view_all
134
158
  if not view_all:
135
159
  page = 0
136
- elif choice == 'n' and not view_all and page < total_pages - 1:
160
+ elif choice == "n" and not view_all and page < total_pages - 1:
137
161
  page += 1
138
- elif choice == 'p' and not view_all and page > 0:
162
+ elif choice == "p" and not view_all and page > 0:
139
163
  page -= 1
140
- elif choice == 'f':
164
+ elif choice == "f":
141
165
  severity_filter = _select_severity_filter()
142
166
  page = 0
143
- elif choice == 'h':
167
+ elif choice == "h":
144
168
  host_filter = _select_host_filter()
145
169
  page = 0
146
- elif choice == 'c':
170
+ elif choice == "c":
147
171
  severity_filter = None
148
172
  host_filter = None
149
173
  page = 0
@@ -152,10 +176,10 @@ def show_splunk_vulns_view(engagement_id: int, engagement_name: str = "") -> Non
152
176
  if 0 <= vuln_idx < len(vulns):
153
177
  _show_vuln_detail(vulns[vuln_idx])
154
178
  else:
155
- click.echo(click.style(" Invalid number", fg='red'))
179
+ click.echo(click.style(" Invalid number", fg="red"))
156
180
  click.pause()
157
181
  else:
158
- click.echo(click.style("Invalid option", fg='red'))
182
+ click.echo(click.style("Invalid option", fg="red"))
159
183
  click.pause()
160
184
 
161
185
  except (KeyboardInterrupt, EOFError):
@@ -163,19 +187,31 @@ def show_splunk_vulns_view(engagement_id: int, engagement_name: str = "") -> Non
163
187
 
164
188
 
165
189
  def _display_vulns_table(
166
- console: Console, vulns: List[Dict], page: int, page_size: int,
167
- view_all: bool, severity_filter: Optional[str], host_filter: Optional[str],
168
- width: int, summary: Dict
190
+ console: Console,
191
+ vulns: List[Dict],
192
+ page: int,
193
+ page_size: int,
194
+ view_all: bool,
195
+ severity_filter: Optional[str],
196
+ host_filter: Optional[str],
197
+ width: int,
198
+ summary: Dict,
169
199
  ) -> tuple:
170
200
  """Display vulnerabilities table with summary header.
171
201
 
172
202
  Returns: (current_page, total_pages)
173
203
  """
174
- by_sev = summary.get('by_severity', {})
204
+ by_sev = summary.get("by_severity", {})
175
205
 
176
206
  # Summary header
177
207
  click.echo("═" * width)
178
- click.echo(click.style(f" SPLUNK VULNERABILITIES ({summary.get('total', 0)} total, {summary.get('unique_cves', 0)} unique CVEs)", bold=True, fg='yellow'))
208
+ click.echo(
209
+ click.style(
210
+ f" SPLUNK VULNERABILITIES ({summary.get('total', 0)} total, {summary.get('unique_cves', 0)} unique CVEs)",
211
+ bold=True,
212
+ fg="yellow",
213
+ )
214
+ )
179
215
 
180
216
  # Severity breakdown
181
217
  sev_line = (
@@ -187,7 +223,11 @@ def _display_vulns_table(
187
223
  click.echo(sev_line)
188
224
 
189
225
  # Agents line
190
- click.echo(click.style(f" Agents affected: {summary.get('agents_affected', 0)}", fg='bright_black'))
226
+ click.echo(
227
+ click.style(
228
+ f" Agents affected: {summary.get('agents_affected', 0)}", fg="bright_black"
229
+ )
230
+ )
191
231
 
192
232
  # Show active filters
193
233
  if severity_filter or host_filter:
@@ -196,13 +236,13 @@ def _display_vulns_table(
196
236
  filter_parts.append(f"Severity: {severity_filter}")
197
237
  if host_filter:
198
238
  filter_parts.append(f"Host: {host_filter}")
199
- click.echo(click.style(f" Filters: {', '.join(filter_parts)}", fg='cyan'))
239
+ click.echo(click.style(f" Filters: {', '.join(filter_parts)}", fg="cyan"))
200
240
 
201
241
  click.echo("─" * width)
202
242
  click.echo()
203
243
 
204
244
  if not vulns:
205
- click.echo(" " + click.style("No vulnerabilities found!", fg='green'))
245
+ click.echo(" " + click.style("No vulnerabilities found!", fg="green"))
206
246
  click.echo(" Make sure Wazuh vuln data is synced to Splunk.")
207
247
  click.echo()
208
248
  return 0, 1
@@ -224,7 +264,7 @@ def _display_vulns_table(
224
264
  header_style="bold cyan",
225
265
  box=DesignSystem.TABLE_BOX,
226
266
  padding=(0, 1),
227
- expand=True
267
+ expand=True,
228
268
  )
229
269
 
230
270
  table.add_column("○", width=3, justify="center")
@@ -242,17 +282,17 @@ def _display_vulns_table(
242
282
  else:
243
283
  display_idx = (page * page_size) + idx + 1
244
284
 
245
- cve = vuln.get('cve_id', '-')
246
- severity = vuln.get('severity', 'Medium')
247
- sev_color = SEVERITY_COLORS.get(severity, 'white')
285
+ cve = vuln.get("cve_id", "-")
286
+ severity = vuln.get("severity", "Medium")
287
+ sev_color = SEVERITY_COLORS.get(severity, "white")
248
288
  sev_display = f"[{sev_color}]{severity}[/{sev_color}]"
249
289
 
250
- cvss = vuln.get('cvss_score')
290
+ cvss = vuln.get("cvss_score")
251
291
  cvss_display = f"{cvss:.1f}" if cvss else "-"
252
292
 
253
- host = vuln.get('agent_name', '-')[:15]
254
- package = vuln.get('package_name', '-')[:24]
255
- os_name = vuln.get('os_name', '-')[:11]
293
+ host = vuln.get("agent_name", "-")[:15]
294
+ package = vuln.get("package_name", "-")[:24]
295
+ os_name = vuln.get("os_name", "-")[:11]
256
296
 
257
297
  table.add_row(
258
298
  "○",
@@ -262,7 +302,7 @@ def _display_vulns_table(
262
302
  cvss_display,
263
303
  host,
264
304
  package,
265
- os_name
305
+ os_name,
266
306
  )
267
307
 
268
308
  console.print(" ", table)
@@ -291,9 +331,9 @@ def _select_severity_filter() -> Optional[str]:
291
331
  click.echo()
292
332
 
293
333
  key = click.getchar().lower()
294
- severity_map = {'1': 'Critical', '2': 'High', '3': 'Medium', '4': 'Low'}
334
+ severity_map = {"1": "Critical", "2": "High", "3": "Medium", "4": "Low"}
295
335
 
296
- if key == 'c':
336
+ if key == "c":
297
337
  return None
298
338
  return severity_map.get(key)
299
339
 
@@ -301,9 +341,11 @@ def _select_severity_filter() -> Optional[str]:
301
341
  def _select_host_filter() -> Optional[str]:
302
342
  """Show host filter prompt."""
303
343
  click.echo()
304
- ip = click.prompt(" Enter host/agent name (partial match, or 'c' to clear)", default="")
344
+ ip = click.prompt(
345
+ " Enter host/agent name (partial match, or 'c' to clear)", default=""
346
+ )
305
347
 
306
- if ip.lower() == 'c' or not ip:
348
+ if ip.lower() == "c" or not ip:
307
349
  return None
308
350
  return ip
309
351
 
@@ -313,17 +355,22 @@ def _show_vuln_detail(vuln: Dict) -> None:
313
355
  DesignSystem.clear_screen()
314
356
  width = DesignSystem.get_terminal_width()
315
357
 
316
- cve = vuln.get('cve_id', 'Unknown')
317
- severity = vuln.get('severity', 'Medium')
318
- sev_color = SEVERITY_COLORS.get(severity, 'white')
358
+ cve = vuln.get("cve_id", "Unknown")
359
+ severity = vuln.get("severity", "Medium")
360
+ sev_color = SEVERITY_COLORS.get(severity, "white")
319
361
 
320
362
  click.echo("\n" + "─" * (width - 2) + "┐")
321
- click.echo("│" + click.style(f" {cve} ".center(width - 2), bold=True, fg='cyan') + "│")
363
+ click.echo(
364
+ "│" + click.style(f" {cve} ".center(width - 2), bold=True, fg="cyan") + "│"
365
+ )
322
366
  click.echo("└" + "─" * (width - 2) + "┘")
323
367
  click.echo()
324
368
 
325
- click.echo(f" Severity: " + click.style(severity, fg=sev_color, bold=True) +
326
- f" | CVSS: {vuln.get('cvss_score', '-')}")
369
+ click.echo(
370
+ f" Severity: "
371
+ + click.style(severity, fg=sev_color, bold=True)
372
+ + f" | CVSS: {vuln.get('cvss_score', '-')}"
373
+ )
327
374
  click.echo()
328
375
 
329
376
  click.echo(click.style(" Host/Agent:", bold=True))
@@ -342,7 +389,7 @@ def _show_vuln_detail(vuln: Dict) -> None:
342
389
  click.echo()
343
390
 
344
391
  # Description (truncated)
345
- desc = vuln.get('description', '')
392
+ desc = vuln.get("description", "")
346
393
  if desc:
347
394
  click.echo(click.style(" Description:", bold=True))
348
395
  # Word wrap description
@@ -366,52 +413,58 @@ def _interactive_vulns_mode(vulns: List[Dict]) -> None:
366
413
  from souleyez.ui.interactive_selector import interactive_select
367
414
 
368
415
  if not vulns:
369
- click.echo(click.style(" No vulnerabilities to select.", fg='yellow'))
416
+ click.echo(click.style(" No vulnerabilities to select.", fg="yellow"))
370
417
  click.pause()
371
418
  return
372
419
 
373
420
  # Prepare items for interactive selector
374
421
  vuln_items = []
375
422
  for vuln in vulns:
376
- vuln_items.append({
377
- 'id': id(vuln),
378
- 'cve_id': vuln.get('cve_id', '-'),
379
- 'severity': vuln.get('severity', 'Medium'),
380
- 'cvss': f"{vuln.get('cvss_score', 0):.1f}" if vuln.get('cvss_score') else '-',
381
- 'host': vuln.get('agent_name', '-')[:15],
382
- 'package': vuln.get('package_name', '-')[:20],
383
- 'os': vuln.get('os_name', '-')[:12],
384
- 'raw': vuln
385
- })
423
+ vuln_items.append(
424
+ {
425
+ "id": id(vuln),
426
+ "cve_id": vuln.get("cve_id", "-"),
427
+ "severity": vuln.get("severity", "Medium"),
428
+ "cvss": (
429
+ f"{vuln.get('cvss_score', 0):.1f}"
430
+ if vuln.get("cvss_score")
431
+ else "-"
432
+ ),
433
+ "host": vuln.get("agent_name", "-")[:15],
434
+ "package": vuln.get("package_name", "-")[:20],
435
+ "os": vuln.get("os_name", "-")[:12],
436
+ "raw": vuln,
437
+ }
438
+ )
386
439
 
387
440
  columns = [
388
- {'name': 'CVE', 'key': 'cve_id', 'width': 18},
389
- {'name': 'Severity', 'key': 'severity', 'width': 10},
390
- {'name': 'CVSS', 'key': 'cvss', 'width': 6},
391
- {'name': 'Host', 'key': 'host', 'width': 15},
392
- {'name': 'Package', 'key': 'package', 'width': 20}
441
+ {"name": "CVE", "key": "cve_id", "width": 18},
442
+ {"name": "Severity", "key": "severity", "width": 10},
443
+ {"name": "CVSS", "key": "cvss", "width": 6},
444
+ {"name": "Host", "key": "host", "width": 15},
445
+ {"name": "Package", "key": "package", "width": 20},
393
446
  ]
394
447
 
395
448
  def format_cell(item: Dict, key: str) -> str:
396
- if key == 'severity':
397
- sev = item.get('severity', 'Medium')
398
- color = SEVERITY_COLORS.get(sev, 'white')
449
+ if key == "severity":
450
+ sev = item.get("severity", "Medium")
451
+ color = SEVERITY_COLORS.get(sev, "white")
399
452
  return f"[{color}]{sev}[/{color}]"
400
- return str(item.get(key, '-'))
453
+ return str(item.get(key, "-"))
401
454
 
402
455
  selected_ids: set = set()
403
456
  interactive_select(
404
457
  items=vuln_items,
405
458
  columns=columns,
406
459
  selected_ids=selected_ids,
407
- get_id=lambda v: v['id'],
460
+ get_id=lambda v: v["id"],
408
461
  title="SPLUNK VULNERABILITIES",
409
- format_cell=format_cell
462
+ format_cell=format_cell,
410
463
  )
411
464
 
412
465
  # Show details of first selected
413
466
  if selected_ids:
414
467
  for item in vuln_items:
415
- if item['id'] in selected_ids:
416
- _show_vuln_detail(item['raw'])
468
+ if item["id"] in selected_ids:
469
+ _show_vuln_detail(item["raw"])
417
470
  break