souleyez 2.43.29__py3-none-any.whl → 2.43.34__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 +9526 -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 +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 +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 +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 +854 -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 +173 -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 +223 -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 +22827 -10678
  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-2.43.34.dist-info}/METADATA +1 -1
  353. souleyez-2.43.34.dist-info/RECORD +443 -0
  354. {souleyez-2.43.29.dist-info → souleyez-2.43.34.dist-info}/WHEEL +1 -1
  355. souleyez-2.43.29.dist-info/RECORD +0 -379
  356. {souleyez-2.43.29.dist-info → souleyez-2.43.34.dist-info}/entry_points.txt +0 -0
  357. {souleyez-2.43.29.dist-info → souleyez-2.43.34.dist-info}/licenses/LICENSE +0 -0
  358. {souleyez-2.43.29.dist-info → souleyez-2.43.34.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
+ """