souleyez 2.43.29__py3-none-any.whl → 3.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.
Files changed (358) 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 +9564 -2881
  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 +1239 -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 +2200 -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 +564 -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 +409 -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 +417 -0
  116. souleyez/handlers/rdp_sec_check_handler.py +353 -0
  117. souleyez/handlers/registry.py +292 -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/web_login_test_handler.py +327 -0
  126. souleyez/handlers/whois_handler.py +277 -0
  127. souleyez/handlers/wpscan_handler.py +554 -0
  128. souleyez/history.py +32 -16
  129. souleyez/importers/msf_importer.py +106 -75
  130. souleyez/importers/smart_importer.py +208 -147
  131. souleyez/integrations/siem/__init__.py +10 -10
  132. souleyez/integrations/siem/base.py +17 -18
  133. souleyez/integrations/siem/elastic.py +108 -122
  134. souleyez/integrations/siem/factory.py +207 -80
  135. souleyez/integrations/siem/googlesecops.py +146 -154
  136. souleyez/integrations/siem/rule_mappings/__init__.py +1 -1
  137. souleyez/integrations/siem/rule_mappings/wazuh_rules.py +8 -5
  138. souleyez/integrations/siem/sentinel.py +107 -109
  139. souleyez/integrations/siem/splunk.py +246 -212
  140. souleyez/integrations/siem/wazuh.py +65 -71
  141. souleyez/integrations/wazuh/__init__.py +5 -5
  142. souleyez/integrations/wazuh/client.py +70 -93
  143. souleyez/integrations/wazuh/config.py +85 -57
  144. souleyez/integrations/wazuh/host_mapper.py +28 -36
  145. souleyez/integrations/wazuh/sync.py +78 -68
  146. souleyez/intelligence/__init__.py +4 -5
  147. souleyez/intelligence/correlation_analyzer.py +309 -295
  148. souleyez/intelligence/exploit_knowledge.py +661 -623
  149. souleyez/intelligence/exploit_suggestions.py +159 -139
  150. souleyez/intelligence/gap_analyzer.py +132 -97
  151. souleyez/intelligence/gap_detector.py +251 -214
  152. souleyez/intelligence/sensitive_tables.py +266 -129
  153. souleyez/intelligence/service_parser.py +137 -123
  154. souleyez/intelligence/surface_analyzer.py +407 -268
  155. souleyez/intelligence/target_parser.py +159 -162
  156. souleyez/licensing/__init__.py +6 -6
  157. souleyez/licensing/validator.py +17 -19
  158. souleyez/log_config.py +79 -54
  159. souleyez/main.py +1505 -687
  160. souleyez/migrations/fix_job_counter.py +16 -14
  161. souleyez/parsers/bloodhound_parser.py +41 -39
  162. souleyez/parsers/crackmapexec_parser.py +178 -111
  163. souleyez/parsers/dalfox_parser.py +72 -77
  164. souleyez/parsers/dnsrecon_parser.py +103 -91
  165. souleyez/parsers/enum4linux_parser.py +183 -153
  166. souleyez/parsers/ffuf_parser.py +29 -25
  167. souleyez/parsers/gobuster_parser.py +301 -41
  168. souleyez/parsers/hashcat_parser.py +324 -79
  169. souleyez/parsers/http_fingerprint_parser.py +350 -103
  170. souleyez/parsers/hydra_parser.py +131 -111
  171. souleyez/parsers/impacket_parser.py +231 -178
  172. souleyez/parsers/john_parser.py +98 -86
  173. souleyez/parsers/katana_parser.py +316 -0
  174. souleyez/parsers/msf_parser.py +943 -498
  175. souleyez/parsers/nikto_parser.py +346 -65
  176. souleyez/parsers/nmap_parser.py +262 -174
  177. souleyez/parsers/nuclei_parser.py +40 -44
  178. souleyez/parsers/responder_parser.py +26 -26
  179. souleyez/parsers/searchsploit_parser.py +74 -74
  180. souleyez/parsers/service_explorer_parser.py +279 -0
  181. souleyez/parsers/smbmap_parser.py +180 -124
  182. souleyez/parsers/sqlmap_parser.py +434 -308
  183. souleyez/parsers/theharvester_parser.py +75 -57
  184. souleyez/parsers/whois_parser.py +135 -94
  185. souleyez/parsers/wpscan_parser.py +278 -190
  186. souleyez/plugins/afp.py +44 -36
  187. souleyez/plugins/afp_brute.py +114 -46
  188. souleyez/plugins/ard.py +48 -37
  189. souleyez/plugins/bloodhound.py +95 -61
  190. souleyez/plugins/certipy.py +303 -0
  191. souleyez/plugins/crackmapexec.py +186 -85
  192. souleyez/plugins/dalfox.py +120 -59
  193. souleyez/plugins/dns_hijack.py +146 -41
  194. souleyez/plugins/dnsrecon.py +97 -61
  195. souleyez/plugins/enum4linux.py +91 -66
  196. souleyez/plugins/evil_winrm.py +291 -0
  197. souleyez/plugins/ffuf.py +166 -90
  198. souleyez/plugins/firmware_extract.py +133 -29
  199. souleyez/plugins/gobuster.py +387 -190
  200. souleyez/plugins/gpp_extract.py +393 -0
  201. souleyez/plugins/hashcat.py +100 -73
  202. souleyez/plugins/http_fingerprint.py +913 -267
  203. souleyez/plugins/hydra.py +566 -200
  204. souleyez/plugins/impacket_getnpusers.py +117 -69
  205. souleyez/plugins/impacket_psexec.py +84 -64
  206. souleyez/plugins/impacket_secretsdump.py +103 -69
  207. souleyez/plugins/impacket_smbclient.py +89 -75
  208. souleyez/plugins/john.py +86 -69
  209. souleyez/plugins/katana.py +313 -0
  210. souleyez/plugins/kerbrute.py +237 -0
  211. souleyez/plugins/lfi_extract.py +541 -0
  212. souleyez/plugins/macos_ssh.py +117 -48
  213. souleyez/plugins/mdns.py +35 -30
  214. souleyez/plugins/msf_auxiliary.py +253 -130
  215. souleyez/plugins/msf_exploit.py +239 -161
  216. souleyez/plugins/nikto.py +134 -78
  217. souleyez/plugins/nmap.py +275 -91
  218. souleyez/plugins/nuclei.py +180 -89
  219. souleyez/plugins/nxc.py +285 -0
  220. souleyez/plugins/plugin_base.py +35 -36
  221. souleyez/plugins/plugin_template.py +13 -5
  222. souleyez/plugins/rdp_sec_check.py +130 -0
  223. souleyez/plugins/responder.py +112 -71
  224. souleyez/plugins/router_http_brute.py +76 -65
  225. souleyez/plugins/router_ssh_brute.py +118 -41
  226. souleyez/plugins/router_telnet_brute.py +124 -42
  227. souleyez/plugins/routersploit.py +91 -59
  228. souleyez/plugins/routersploit_exploit.py +77 -55
  229. souleyez/plugins/searchsploit.py +91 -77
  230. souleyez/plugins/service_explorer.py +1160 -0
  231. souleyez/plugins/smbmap.py +122 -72
  232. souleyez/plugins/smbpasswd.py +215 -0
  233. souleyez/plugins/sqlmap.py +301 -113
  234. souleyez/plugins/theharvester.py +127 -75
  235. souleyez/plugins/tr069.py +79 -57
  236. souleyez/plugins/upnp.py +65 -47
  237. souleyez/plugins/upnp_abuse.py +73 -55
  238. souleyez/plugins/vnc_access.py +129 -42
  239. souleyez/plugins/vnc_brute.py +109 -38
  240. souleyez/plugins/web_login_test.py +417 -0
  241. souleyez/plugins/whois.py +77 -58
  242. souleyez/plugins/wpscan.py +219 -69
  243. souleyez/reporting/__init__.py +2 -1
  244. souleyez/reporting/attack_chain.py +411 -346
  245. souleyez/reporting/charts.py +436 -501
  246. souleyez/reporting/compliance_mappings.py +334 -201
  247. souleyez/reporting/detection_report.py +126 -125
  248. souleyez/reporting/formatters.py +828 -591
  249. souleyez/reporting/generator.py +386 -302
  250. souleyez/reporting/metrics.py +72 -75
  251. souleyez/scanner.py +35 -29
  252. souleyez/security/__init__.py +37 -11
  253. souleyez/security/scope_validator.py +175 -106
  254. souleyez/security/validation.py +237 -149
  255. souleyez/security.py +22 -6
  256. souleyez/storage/credentials.py +247 -186
  257. souleyez/storage/crypto.py +296 -129
  258. souleyez/storage/database.py +73 -50
  259. souleyez/storage/db.py +58 -36
  260. souleyez/storage/deliverable_evidence.py +177 -128
  261. souleyez/storage/deliverable_exporter.py +282 -246
  262. souleyez/storage/deliverable_templates.py +134 -116
  263. souleyez/storage/deliverables.py +135 -130
  264. souleyez/storage/engagements.py +109 -56
  265. souleyez/storage/evidence.py +181 -152
  266. souleyez/storage/execution_log.py +31 -17
  267. souleyez/storage/exploit_attempts.py +93 -57
  268. souleyez/storage/exploits.py +67 -36
  269. souleyez/storage/findings.py +48 -61
  270. souleyez/storage/hosts.py +176 -144
  271. souleyez/storage/migrate_to_engagements.py +43 -19
  272. souleyez/storage/migrations/_001_add_credential_enhancements.py +22 -12
  273. souleyez/storage/migrations/_002_add_status_tracking.py +10 -7
  274. souleyez/storage/migrations/_003_add_execution_log.py +14 -8
  275. souleyez/storage/migrations/_005_screenshots.py +13 -5
  276. souleyez/storage/migrations/_006_deliverables.py +13 -5
  277. souleyez/storage/migrations/_007_deliverable_templates.py +12 -7
  278. souleyez/storage/migrations/_008_add_nuclei_table.py +10 -4
  279. souleyez/storage/migrations/_010_evidence_linking.py +17 -10
  280. souleyez/storage/migrations/_011_timeline_tracking.py +20 -13
  281. souleyez/storage/migrations/_012_team_collaboration.py +34 -21
  282. souleyez/storage/migrations/_013_add_host_tags.py +12 -6
  283. souleyez/storage/migrations/_014_exploit_attempts.py +22 -10
  284. souleyez/storage/migrations/_015_add_mac_os_fields.py +15 -7
  285. souleyez/storage/migrations/_016_add_domain_field.py +10 -4
  286. souleyez/storage/migrations/_017_msf_sessions.py +16 -8
  287. souleyez/storage/migrations/_018_add_osint_target.py +10 -6
  288. souleyez/storage/migrations/_019_add_engagement_type.py +10 -6
  289. souleyez/storage/migrations/_020_add_rbac.py +36 -15
  290. souleyez/storage/migrations/_021_wazuh_integration.py +20 -8
  291. souleyez/storage/migrations/_022_wazuh_indexer_columns.py +6 -4
  292. souleyez/storage/migrations/_023_fix_detection_results_fk.py +16 -6
  293. souleyez/storage/migrations/_024_wazuh_vulnerabilities.py +26 -10
  294. souleyez/storage/migrations/_025_multi_siem_support.py +3 -5
  295. souleyez/storage/migrations/_026_add_engagement_scope.py +31 -12
  296. souleyez/storage/migrations/_027_multi_siem_persistence.py +32 -15
  297. souleyez/storage/migrations/__init__.py +26 -26
  298. souleyez/storage/migrations/migration_manager.py +19 -19
  299. souleyez/storage/msf_sessions.py +100 -65
  300. souleyez/storage/osint.py +17 -24
  301. souleyez/storage/recommendation_engine.py +269 -235
  302. souleyez/storage/screenshots.py +33 -32
  303. souleyez/storage/smb_shares.py +136 -92
  304. souleyez/storage/sqlmap_data.py +183 -128
  305. souleyez/storage/team_collaboration.py +135 -141
  306. souleyez/storage/timeline_tracker.py +122 -94
  307. souleyez/storage/wazuh_vulns.py +64 -66
  308. souleyez/storage/web_paths.py +33 -37
  309. souleyez/testing/credential_tester.py +221 -205
  310. souleyez/ui/__init__.py +1 -1
  311. souleyez/ui/ai_quotes.py +12 -12
  312. souleyez/ui/attack_surface.py +2439 -1516
  313. souleyez/ui/chain_rules_view.py +914 -382
  314. souleyez/ui/correlation_view.py +312 -230
  315. souleyez/ui/dashboard.py +2382 -1130
  316. souleyez/ui/deliverables_view.py +148 -62
  317. souleyez/ui/design_system.py +13 -13
  318. souleyez/ui/errors.py +49 -49
  319. souleyez/ui/evidence_linking_view.py +284 -179
  320. souleyez/ui/evidence_vault.py +393 -285
  321. souleyez/ui/exploit_suggestions_view.py +555 -349
  322. souleyez/ui/export_view.py +100 -66
  323. souleyez/ui/gap_analysis_view.py +315 -171
  324. souleyez/ui/help_system.py +105 -97
  325. souleyez/ui/intelligence_view.py +436 -293
  326. souleyez/ui/interactive.py +23034 -10679
  327. souleyez/ui/interactive_selector.py +75 -68
  328. souleyez/ui/log_formatter.py +47 -39
  329. souleyez/ui/menu_components.py +22 -13
  330. souleyez/ui/msf_auxiliary_menu.py +184 -133
  331. souleyez/ui/pending_chains_view.py +336 -172
  332. souleyez/ui/progress_indicators.py +5 -3
  333. souleyez/ui/recommendations_view.py +195 -137
  334. souleyez/ui/rule_builder.py +343 -225
  335. souleyez/ui/setup_wizard.py +678 -284
  336. souleyez/ui/shortcuts.py +217 -165
  337. souleyez/ui/splunk_gap_analysis_view.py +452 -270
  338. souleyez/ui/splunk_vulns_view.py +139 -86
  339. souleyez/ui/team_dashboard.py +498 -335
  340. souleyez/ui/template_selector.py +196 -105
  341. souleyez/ui/terminal.py +6 -6
  342. souleyez/ui/timeline_view.py +198 -127
  343. souleyez/ui/tool_setup.py +264 -164
  344. souleyez/ui/tutorial.py +202 -72
  345. souleyez/ui/tutorial_state.py +40 -40
  346. souleyez/ui/wazuh_vulns_view.py +235 -141
  347. souleyez/ui/wordlist_browser.py +260 -107
  348. souleyez/ui.py +464 -312
  349. souleyez/utils/tool_checker.py +427 -367
  350. souleyez/utils.py +33 -29
  351. souleyez/wordlists.py +134 -167
  352. {souleyez-2.43.29.dist-info → souleyez-3.0.0.dist-info}/METADATA +2 -2
  353. souleyez-3.0.0.dist-info/RECORD +443 -0
  354. {souleyez-2.43.29.dist-info → souleyez-3.0.0.dist-info}/WHEEL +1 -1
  355. souleyez-2.43.29.dist-info/RECORD +0 -379
  356. {souleyez-2.43.29.dist-info → souleyez-3.0.0.dist-info}/entry_points.txt +0 -0
  357. {souleyez-2.43.29.dist-info → souleyez-3.0.0.dist-info}/licenses/LICENSE +0 -0
  358. {souleyez-2.43.29.dist-info → souleyez-3.0.0.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