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
@@ -13,18 +13,25 @@ def is_worker_running() -> Tuple[bool, Optional[int]]:
13
13
 
14
14
  Returns: (is_running, pid)
15
15
  """
16
- for proc in psutil.process_iter(['pid', 'cmdline']):
16
+ for proc in psutil.process_iter(["pid", "cmdline"]):
17
17
  try:
18
- cmdline = proc.info.get('cmdline', [])
18
+ cmdline = proc.info.get("cmdline", [])
19
19
  if not cmdline:
20
20
  continue
21
- cmdline_str = ' '.join(str(arg) for arg in cmdline)
21
+ cmdline_str = " ".join(str(arg) for arg in cmdline)
22
22
  # Check for Python-based worker (dev mode)
23
- if 'souleyez.engine.background' in cmdline_str and 'worker_loop' in cmdline_str:
24
- return True, proc.info['pid']
23
+ if (
24
+ "souleyez.engine.background" in cmdline_str
25
+ and "worker_loop" in cmdline_str
26
+ ):
27
+ return True, proc.info["pid"]
25
28
  # Check for binary-based worker (compiled mode)
26
- if 'souleyez' in cmdline_str and 'worker' in cmdline_str and 'start' in cmdline_str:
27
- return True, proc.info['pid']
29
+ if (
30
+ "souleyez" in cmdline_str
31
+ and "worker" in cmdline_str
32
+ and "start" in cmdline_str
33
+ ):
34
+ return True, proc.info["pid"]
28
35
  except (psutil.NoSuchProcess, psutil.AccessDenied):
29
36
  continue
30
37
  return False, None
@@ -42,9 +49,7 @@ def is_worker_healthy() -> Tuple[bool, Optional[int], Optional[str]]:
42
49
  - pid: Worker PID if found, None otherwise
43
50
  - issue: Description of issue if not healthy, None otherwise
44
51
  """
45
- from souleyez.engine.background import (
46
- get_heartbeat_age, HEARTBEAT_STALE_THRESHOLD
47
- )
52
+ from souleyez.engine.background import get_heartbeat_age, HEARTBEAT_STALE_THRESHOLD
48
53
 
49
54
  is_running, pid = is_worker_running()
50
55
 
@@ -59,7 +64,11 @@ def is_worker_healthy() -> Tuple[bool, Optional[int], Optional[str]]:
59
64
  return True, pid, "No heartbeat yet (may be starting)"
60
65
 
61
66
  if heartbeat_age > HEARTBEAT_STALE_THRESHOLD:
62
- return False, pid, f"Heartbeat stale ({int(heartbeat_age)}s old, threshold: {HEARTBEAT_STALE_THRESHOLD}s)"
67
+ return (
68
+ False,
69
+ pid,
70
+ f"Heartbeat stale ({int(heartbeat_age)}s old, threshold: {HEARTBEAT_STALE_THRESHOLD}s)",
71
+ )
63
72
 
64
73
  return True, pid, None
65
74
 
@@ -76,6 +85,7 @@ def start_worker_if_needed() -> bool:
76
85
 
77
86
  # Start the worker
78
87
  from souleyez.engine.background import start_worker
88
+
79
89
  start_worker(detach=True)
80
90
  time.sleep(1) # Give it a moment to start
81
91
 
@@ -125,19 +135,19 @@ def get_worker_status() -> dict:
125
135
  is_running, pid = is_worker_running()
126
136
 
127
137
  status = {
128
- 'running': is_running,
129
- 'pid': pid,
130
- 'uptime': None,
131
- 'cpu_percent': None,
132
- 'memory_mb': None
138
+ "running": is_running,
139
+ "pid": pid,
140
+ "uptime": None,
141
+ "cpu_percent": None,
142
+ "memory_mb": None,
133
143
  }
134
144
 
135
145
  if is_running and pid:
136
146
  try:
137
147
  proc = psutil.Process(pid)
138
- status['uptime'] = int(time.time() - proc.create_time())
139
- status['cpu_percent'] = proc.cpu_percent(interval=0.1)
140
- status['memory_mb'] = proc.memory_info().rss / 1024 / 1024
148
+ status["uptime"] = int(time.time() - proc.create_time())
149
+ status["cpu_percent"] = proc.cpu_percent(interval=0.1)
150
+ status["memory_mb"] = proc.memory_info().rss / 1024 / 1024
141
151
  except (psutil.NoSuchProcess, psutil.AccessDenied):
142
152
  pass
143
153
 
@@ -159,47 +169,46 @@ def get_worker_health() -> Dict[str, Any]:
159
169
  - cpu_percent: CPU usage percentage
160
170
  - memory_mb: Memory usage in MB
161
171
  """
162
- from souleyez.engine.background import (
163
- get_heartbeat_age, HEARTBEAT_STALE_THRESHOLD
164
- )
172
+ from souleyez.engine.background import get_heartbeat_age, HEARTBEAT_STALE_THRESHOLD
165
173
 
166
174
  is_running, pid = is_worker_running()
167
175
  heartbeat_age = get_heartbeat_age()
168
176
 
169
177
  health = {
170
- 'running': is_running,
171
- 'healthy': False,
172
- 'pid': pid,
173
- 'uptime': None,
174
- 'heartbeat_age': heartbeat_age,
175
- 'heartbeat_stale': heartbeat_age is None or heartbeat_age > HEARTBEAT_STALE_THRESHOLD,
176
- 'issue': None,
177
- 'cpu_percent': None,
178
- 'memory_mb': None
178
+ "running": is_running,
179
+ "healthy": False,
180
+ "pid": pid,
181
+ "uptime": None,
182
+ "heartbeat_age": heartbeat_age,
183
+ "heartbeat_stale": heartbeat_age is None
184
+ or heartbeat_age > HEARTBEAT_STALE_THRESHOLD,
185
+ "issue": None,
186
+ "cpu_percent": None,
187
+ "memory_mb": None,
179
188
  }
180
189
 
181
190
  if not is_running:
182
- health['issue'] = "Worker process not found"
191
+ health["issue"] = "Worker process not found"
183
192
  return health
184
193
 
185
194
  # Get process info
186
195
  try:
187
196
  proc = psutil.Process(pid)
188
- health['uptime'] = int(time.time() - proc.create_time())
189
- health['cpu_percent'] = proc.cpu_percent(interval=0.1)
190
- health['memory_mb'] = round(proc.memory_info().rss / 1024 / 1024, 1)
197
+ health["uptime"] = int(time.time() - proc.create_time())
198
+ health["cpu_percent"] = proc.cpu_percent(interval=0.1)
199
+ health["memory_mb"] = round(proc.memory_info().rss / 1024 / 1024, 1)
191
200
  except (psutil.NoSuchProcess, psutil.AccessDenied):
192
- health['issue'] = "Cannot access worker process"
201
+ health["issue"] = "Cannot access worker process"
193
202
  return health
194
203
 
195
204
  # Check heartbeat
196
205
  if heartbeat_age is None:
197
- health['issue'] = "No heartbeat yet (worker may be starting)"
198
- health['healthy'] = True # Give benefit of doubt for new workers
206
+ health["issue"] = "No heartbeat yet (worker may be starting)"
207
+ health["healthy"] = True # Give benefit of doubt for new workers
199
208
  elif heartbeat_age > HEARTBEAT_STALE_THRESHOLD:
200
- health['issue'] = f"Worker unresponsive (heartbeat {int(heartbeat_age)}s old)"
201
- health['healthy'] = False
209
+ health["issue"] = f"Worker unresponsive (heartbeat {int(heartbeat_age)}s old)"
210
+ health["healthy"] = False
202
211
  else:
203
- health['healthy'] = True
212
+ health["healthy"] = True
204
213
 
205
214
  return health
@@ -9,62 +9,68 @@ from datetime import datetime
9
9
  from typing import Dict, List
10
10
 
11
11
 
12
- def create_evidence_bundle(engagement_id: int, engagement: Dict, evidence: Dict[str, List[Dict]]) -> str:
12
+ def create_evidence_bundle(
13
+ engagement_id: int, engagement: Dict, evidence: Dict[str, List[Dict]]
14
+ ) -> str:
13
15
  """
14
16
  Create ZIP bundle of all evidence.
15
-
17
+
16
18
  Returns:
17
19
  Path to created ZIP file
18
20
  """
19
21
  # Create output directory
20
22
  output_dir = os.path.expanduser("~/.souleyez/exports")
21
23
  os.makedirs(output_dir, exist_ok=True)
22
-
24
+
23
25
  # Generate filename
24
26
  timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
25
- safe_name = engagement['name'].replace(' ', '_').replace('/', '_').replace('\\', '_')
27
+ safe_name = (
28
+ engagement["name"].replace(" ", "_").replace("/", "_").replace("\\", "_")
29
+ )
26
30
  zip_filename = f"{safe_name}_evidence_{timestamp}.zip"
27
31
  zip_path = os.path.join(output_dir, zip_filename)
28
-
32
+
29
33
  # Create ZIP
30
- with zipfile.ZipFile(zip_path, 'w', zipfile.ZIP_DEFLATED) as zipf:
34
+ with zipfile.ZipFile(zip_path, "w", zipfile.ZIP_DEFLATED) as zipf:
31
35
  # Add README
32
36
  readme = generate_readme(engagement, evidence)
33
37
  zipf.writestr("README.txt", readme)
34
-
38
+
35
39
  # Add evidence by phase
36
40
  for phase, items in evidence.items():
37
- phase_dir = phase.replace('_', '-')
38
-
41
+ phase_dir = phase.replace("_", "-")
42
+
39
43
  # Create phase summary
40
44
  phase_summary = generate_phase_summary(phase, items)
41
45
  zipf.writestr(f"{phase_dir}/SUMMARY.txt", phase_summary)
42
-
46
+
43
47
  for idx, item in enumerate(items, 1):
44
- if item['type'] == 'job':
48
+ if item["type"] == "job":
45
49
  # Add job log if exists
46
- log_path = item.get('log_path')
50
+ log_path = item.get("log_path")
47
51
  if log_path and os.path.exists(log_path):
48
- safe_tool = item['tool'].replace('/', '_')
49
- safe_target = item['target'].replace('/', '_').replace(':', '_')[:50]
52
+ safe_tool = item["tool"].replace("/", "_")
53
+ safe_target = (
54
+ item["target"].replace("/", "_").replace(":", "_")[:50]
55
+ )
50
56
  arcname = f"{phase_dir}/{idx:03d}_{safe_tool}_{safe_target}.log"
51
57
  zipf.write(log_path, arcname)
52
-
58
+
53
59
  # Add credentials file
54
60
  creds_content = export_credentials(engagement_id)
55
61
  if creds_content:
56
62
  zipf.writestr("CREDENTIALS.txt", creds_content)
57
-
63
+
58
64
  # Add findings file
59
65
  findings_content = export_findings(engagement_id)
60
66
  if findings_content:
61
67
  zipf.writestr("FINDINGS.txt", findings_content)
62
-
68
+
63
69
  # Add hosts summary
64
70
  hosts_content = export_hosts(engagement_id)
65
71
  if hosts_content:
66
72
  zipf.writestr("HOSTS.txt", hosts_content)
67
-
73
+
68
74
  return zip_path
69
75
 
70
76
 
@@ -77,18 +83,18 @@ def generate_readme(engagement: Dict, evidence: Dict[str, List[Dict]]) -> str:
77
83
  lines.append(f"Generated: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
78
84
  lines.append(f"Engagement ID: {engagement['id']}")
79
85
  lines.append("")
80
-
86
+
81
87
  # Summary
82
88
  total = sum(len(items) for items in evidence.values())
83
89
  lines.append(f"Total Evidence Items: {total}")
84
90
  lines.append("")
85
-
91
+
86
92
  lines.append("Evidence by Phase:")
87
93
  lines.append("-" * 70)
88
94
  for phase, items in evidence.items():
89
- phase_name = phase.replace('_', ' ').title()
95
+ phase_name = phase.replace("_", " ").title()
90
96
  lines.append(f" {phase_name:30} {len(items):3} items")
91
-
97
+
92
98
  lines.append("")
93
99
  lines.append("=" * 70)
94
100
  lines.append("")
@@ -131,151 +137,155 @@ def generate_readme(engagement: Dict, evidence: Dict[str, List[Dict]]) -> str:
131
137
  lines.append("- Timestamps are in UTC")
132
138
  lines.append("- Sensitive data (passwords) may be redacted")
133
139
  lines.append("")
134
-
140
+
135
141
  return "\n".join(lines)
136
142
 
137
143
 
138
144
  def generate_phase_summary(phase: str, items: List[Dict]) -> str:
139
145
  """Generate summary for a phase."""
140
146
  lines = []
141
- phase_name = phase.replace('_', ' ').upper()
142
-
147
+ phase_name = phase.replace("_", " ").upper()
148
+
143
149
  lines.append("=" * 70)
144
150
  lines.append(f"{phase_name} - EVIDENCE SUMMARY")
145
151
  lines.append("=" * 70)
146
152
  lines.append("")
147
153
  lines.append(f"Total Items: {len(items)}")
148
154
  lines.append("")
149
-
155
+
150
156
  for idx, item in enumerate(items, 1):
151
157
  lines.append(f"[{idx:03d}] {item['title']}")
152
158
  lines.append(f" Tool: {item['tool']}")
153
159
  lines.append(f" Target: {item['target']}")
154
160
  lines.append(f" Date: {item['created_at']}")
155
161
  lines.append(f" Description: {item['description']}")
156
-
157
- if item['type'] == 'finding':
162
+
163
+ if item["type"] == "finding":
158
164
  lines.append(f" Severity: {item['severity'].upper()}")
159
- elif item['type'] == 'credential':
165
+ elif item["type"] == "credential":
160
166
  lines.append(f" Type: Credential Discovery")
161
-
167
+
162
168
  lines.append("")
163
-
169
+
164
170
  return "\n".join(lines)
165
171
 
166
172
 
167
173
  def export_credentials(engagement_id: int) -> str:
168
174
  """Export credentials as text."""
169
175
  from souleyez.storage.credentials import CredentialsManager
170
-
176
+
171
177
  cm = CredentialsManager()
172
178
  creds = cm.list_credentials(engagement_id)
173
-
179
+
174
180
  if not creds:
175
181
  return ""
176
-
182
+
177
183
  lines = []
178
184
  lines.append("=" * 70)
179
185
  lines.append("CREDENTIALS DISCOVERED")
180
186
  lines.append("=" * 70)
181
187
  lines.append(f"Total: {len(creds)} credentials")
182
188
  lines.append("")
183
-
189
+
184
190
  for idx, cred in enumerate(creds, 1):
185
- lines.append(f"[{idx:03d}] Host: {cred.get('host', 'N/A')}:{cred.get('port', '?')}")
191
+ lines.append(
192
+ f"[{idx:03d}] Host: {cred.get('host', 'N/A')}:{cred.get('port', '?')}"
193
+ )
186
194
  lines.append(f" Service: {cred.get('service', 'unknown')}")
187
195
  lines.append(f" Username: {cred.get('username', 'N/A')}")
188
196
  lines.append(f" Status: {cred.get('status', 'unknown')}")
189
197
  lines.append(f" Source: {cred.get('source', 'unknown')}")
190
198
  lines.append(f" Created: {cred.get('created_at', 'N/A')}")
191
199
  lines.append("-" * 70)
192
-
200
+
193
201
  return "\n".join(lines)
194
202
 
195
203
 
196
204
  def export_findings(engagement_id: int) -> str:
197
205
  """Export findings as text."""
198
206
  from souleyez.storage.findings import FindingsManager
199
-
207
+
200
208
  fm = FindingsManager()
201
209
  findings = fm.list_findings(engagement_id)
202
-
210
+
203
211
  if not findings:
204
212
  return ""
205
-
213
+
206
214
  lines = []
207
215
  lines.append("=" * 70)
208
216
  lines.append("SECURITY FINDINGS")
209
217
  lines.append("=" * 70)
210
218
  lines.append(f"Total: {len(findings)} findings")
211
219
  lines.append("")
212
-
220
+
213
221
  # Group by severity
214
222
  by_severity = {}
215
223
  for finding in findings:
216
- sev = finding.get('severity', 'info')
224
+ sev = finding.get("severity", "info")
217
225
  if sev not in by_severity:
218
226
  by_severity[sev] = []
219
227
  by_severity[sev].append(finding)
220
-
221
- for severity in ['critical', 'high', 'medium', 'low', 'info']:
228
+
229
+ for severity in ["critical", "high", "medium", "low", "info"]:
222
230
  sev_findings = by_severity.get(severity, [])
223
231
  if sev_findings:
224
232
  lines.append(f"\n{severity.upper()}: {len(sev_findings)} findings")
225
233
  lines.append("-" * 70)
226
-
234
+
227
235
  for finding in sev_findings:
228
236
  lines.append(f"\nTitle: {finding['title']}")
229
237
  lines.append(f"Tool: {finding.get('tool', 'Unknown')}")
230
- target = finding.get('host') or finding.get('url', 'Unknown')
238
+ target = finding.get("host") or finding.get("url", "Unknown")
231
239
  lines.append(f"Target: {target}")
232
-
233
- if finding.get('cve'):
240
+
241
+ if finding.get("cve"):
234
242
  lines.append(f"CVE: {finding['cve']}")
235
- if finding.get('cvss'):
243
+ if finding.get("cvss"):
236
244
  lines.append(f"CVSS: {finding['cvss']}")
237
-
238
- desc = finding.get('description', '')
245
+
246
+ desc = finding.get("description", "")
239
247
  if desc:
240
248
  lines.append(f"Description: {desc[:500]}")
241
-
249
+
242
250
  lines.append("")
243
-
251
+
244
252
  return "\n".join(lines)
245
253
 
246
254
 
247
255
  def export_hosts(engagement_id: int) -> str:
248
256
  """Export hosts summary."""
249
257
  from souleyez.storage.hosts import HostManager
250
-
258
+
251
259
  hm = HostManager()
252
260
  hosts = hm.list_hosts(engagement_id)
253
-
261
+
254
262
  if not hosts:
255
263
  return ""
256
-
264
+
257
265
  lines = []
258
266
  lines.append("=" * 70)
259
267
  lines.append("DISCOVERED HOSTS")
260
268
  lines.append("=" * 70)
261
269
  lines.append(f"Total: {len(hosts)} hosts")
262
270
  lines.append("")
263
-
271
+
264
272
  for host in hosts:
265
273
  lines.append(f"Host: {host.get('ip', 'N/A')}")
266
274
  lines.append(f" Hostname: {host.get('hostname', 'N/A')}")
267
275
  lines.append(f" Status: {host.get('status', 'unknown')}")
268
276
  lines.append(f" OS: {host.get('os', 'Unknown')}")
269
-
277
+
270
278
  # Get services count
271
- services = host.get('services', [])
279
+ services = host.get("services", [])
272
280
  if services:
273
281
  lines.append(f" Services: {len(services)}")
274
282
  for svc in services[:5]: # First 5 services
275
- lines.append(f" - {svc.get('port', '?')}/{svc.get('protocol', 'tcp')}: {svc.get('service', 'unknown')}")
283
+ lines.append(
284
+ f" - {svc.get('port', '?')}/{svc.get('protocol', 'tcp')}: {svc.get('service', 'unknown')}"
285
+ )
276
286
  if len(services) > 5:
277
287
  lines.append(f" (and {len(services) - 5} more...)")
278
-
288
+
279
289
  lines.append("")
280
-
290
+
281
291
  return "\n".join(lines)
@@ -11,11 +11,12 @@ from typing import Dict, Optional
11
11
 
12
12
  class FeatureStatus(Enum):
13
13
  """Status of a feature."""
14
- ENABLED = "enabled" # Feature is fully implemented and available
15
- DISABLED = "disabled" # Feature is hidden from users
16
- BETA = "beta" # Feature is available but marked as beta
17
- DEVELOPMENT = "development" # Feature is under development (hidden in production)
18
- PRO = "pro" # Feature requires Pro tier
14
+
15
+ ENABLED = "enabled" # Feature is fully implemented and available
16
+ DISABLED = "disabled" # Feature is hidden from users
17
+ BETA = "beta" # Feature is available but marked as beta
18
+ DEVELOPMENT = "development" # Feature is under development (hidden in production)
19
+ PRO = "pro" # Feature requires Pro tier
19
20
 
20
21
 
21
22
  class Feature(Enum):
@@ -62,28 +63,23 @@ class FeatureFlags:
62
63
  # Export Features - Placeholder implementations
63
64
  Feature.JSON_EXPORT: FeatureStatus.DISABLED,
64
65
  Feature.HOSTS_SERVICES_EXPORT: FeatureStatus.DISABLED,
65
-
66
66
  # Import Features - Placeholder implementations
67
67
  Feature.NMAP_XML_IMPORT: FeatureStatus.DISABLED,
68
68
  Feature.NESSUS_IMPORT: FeatureStatus.DISABLED,
69
-
70
69
  # Analysis Features
71
- Feature.EVIDENCE_LINKING: FeatureStatus.ENABLED, # FREE - basic feature
72
- Feature.CORRELATION_ENGINE: FeatureStatus.PRO, # PRO - advanced analysis
73
- Feature.ATTACK_SURFACE: FeatureStatus.PRO, # PRO - priority scoring
74
- Feature.EXPLOIT_SUGGESTIONS: FeatureStatus.PRO, # PRO - CVE/MSF recommendations
75
-
70
+ Feature.EVIDENCE_LINKING: FeatureStatus.ENABLED, # FREE - basic feature
71
+ Feature.CORRELATION_ENGINE: FeatureStatus.PRO, # PRO - advanced analysis
72
+ Feature.ATTACK_SURFACE: FeatureStatus.PRO, # PRO - priority scoring
73
+ Feature.EXPLOIT_SUGGESTIONS: FeatureStatus.PRO, # PRO - CVE/MSF recommendations
76
74
  # Dashboard Features
77
- Feature.TEAM_DASHBOARD: FeatureStatus.PRO, # PRO - collaboration
78
- Feature.TIMELINE_VIEW: FeatureStatus.ENABLED, # FREE - basic timeline
79
-
75
+ Feature.TEAM_DASHBOARD: FeatureStatus.PRO, # PRO - collaboration
76
+ Feature.TIMELINE_VIEW: FeatureStatus.ENABLED, # FREE - basic timeline
80
77
  # Reporting Features
81
- Feature.DELIVERABLES: FeatureStatus.ENABLED, # FREE - basic tracking
82
- Feature.EXPORT_VIEW: FeatureStatus.PRO, # PRO - report export
83
-
78
+ Feature.DELIVERABLES: FeatureStatus.ENABLED, # FREE - basic tracking
79
+ Feature.EXPORT_VIEW: FeatureStatus.PRO, # PRO - report export
84
80
  # Advanced Features
85
- Feature.AUTO_CHAINING: FeatureStatus.PRO, # PRO - automation
86
- Feature.AI_RECOMMENDATIONS: FeatureStatus.PRO, # PRO - AI features
81
+ Feature.AUTO_CHAINING: FeatureStatus.PRO, # PRO - automation
82
+ Feature.AI_RECOMMENDATIONS: FeatureStatus.PRO, # PRO - AI features
87
83
  }
88
84
 
89
85
  @classmethod
souleyez/feature_flags.py CHANGED
@@ -11,10 +11,11 @@ from typing import Dict, Optional
11
11
 
12
12
  class FeatureStatus(Enum):
13
13
  """Status of a feature."""
14
- ENABLED = "enabled" # Feature is fully implemented and available
15
- DISABLED = "disabled" # Feature is hidden from users
16
- BETA = "beta" # Feature is available but marked as beta
17
- DEVELOPMENT = "development" # Feature is under development (hidden in production)
14
+
15
+ ENABLED = "enabled" # Feature is fully implemented and available
16
+ DISABLED = "disabled" # Feature is hidden from users
17
+ BETA = "beta" # Feature is available but marked as beta
18
+ DEVELOPMENT = "development" # Feature is under development (hidden in production)
18
19
 
19
20
 
20
21
  class Feature(Enum):
@@ -61,25 +62,20 @@ class FeatureFlags:
61
62
  # Export Features - Placeholder implementations
62
63
  Feature.JSON_EXPORT: FeatureStatus.DISABLED,
63
64
  Feature.HOSTS_SERVICES_EXPORT: FeatureStatus.DISABLED,
64
-
65
65
  # Import Features - Placeholder implementations
66
66
  Feature.NMAP_XML_IMPORT: FeatureStatus.DISABLED,
67
67
  Feature.NESSUS_IMPORT: FeatureStatus.DISABLED,
68
-
69
68
  # Analysis Features - Implemented
70
69
  Feature.EVIDENCE_LINKING: FeatureStatus.ENABLED,
71
70
  Feature.CORRELATION_ENGINE: FeatureStatus.ENABLED,
72
71
  Feature.ATTACK_SURFACE: FeatureStatus.ENABLED,
73
72
  Feature.EXPLOIT_SUGGESTIONS: FeatureStatus.ENABLED,
74
-
75
73
  # Dashboard Features - Implemented
76
74
  Feature.TEAM_DASHBOARD: FeatureStatus.ENABLED,
77
75
  Feature.TIMELINE_VIEW: FeatureStatus.ENABLED,
78
-
79
76
  # Reporting Features - Implemented
80
77
  Feature.DELIVERABLES: FeatureStatus.ENABLED,
81
78
  Feature.EXPORT_VIEW: FeatureStatus.ENABLED,
82
-
83
79
  # Advanced Features
84
80
  Feature.AUTO_CHAINING: FeatureStatus.ENABLED,
85
81
  Feature.AI_RECOMMENDATIONS: FeatureStatus.ENABLED,
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Tool handlers package.
4
+
5
+ Each tool has a handler class that consolidates:
6
+ - Parsing logic (from result_handler.py)
7
+ - Display logic (from interactive.py)
8
+ - Capability flags (replaces manual lists)
9
+
10
+ Auto-discovery: Handlers are registered automatically when imported.
11
+ """