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
souleyez/engine/base.py CHANGED
@@ -17,9 +17,12 @@ class ScannerPlugin:
17
17
  - prepare(target, args, label) -> dict (optional)
18
18
  - run(prepared) -> ScanResult
19
19
  """
20
+
20
21
  name = "base"
21
22
 
22
- def prepare(self, target: str, args: list, label: Optional[str] = None) -> Dict[str, Any]:
23
+ def prepare(
24
+ self, target: str, args: list, label: Optional[str] = None
25
+ ) -> Dict[str, Any]:
23
26
  return {"target": target, "args": args, "label": label}
24
27
 
25
28
  def run(self, prepared: Dict[str, Any]) -> ScanResult:
@@ -6,13 +6,13 @@ Defines the status lifecycle for jobs in the system.
6
6
  """
7
7
 
8
8
  # Job status constants
9
- STATUS_QUEUED = 'queued' # Job waiting to execute
10
- STATUS_RUNNING = 'running' # Job actively executing
11
- STATUS_DONE = 'done' # Completed successfully WITH results
12
- STATUS_NO_RESULTS = 'no_results' # Completed successfully but found NOTHING
13
- STATUS_WARNING = 'warning' # Partial success or non-critical issues
14
- STATUS_ERROR = 'error' # TRUE failures (crashes, timeouts, invalid args)
15
- STATUS_KILLED = 'killed' # User terminated
9
+ STATUS_QUEUED = "queued" # Job waiting to execute
10
+ STATUS_RUNNING = "running" # Job actively executing
11
+ STATUS_DONE = "done" # Completed successfully WITH results
12
+ STATUS_NO_RESULTS = "no_results" # Completed successfully but found NOTHING
13
+ STATUS_WARNING = "warning" # Partial success or non-critical issues
14
+ STATUS_ERROR = "error" # TRUE failures (crashes, timeouts, invalid args)
15
+ STATUS_KILLED = "killed" # User terminated
16
16
 
17
17
  # Valid status values
18
18
  VALID_STATUSES = {
@@ -36,9 +36,9 @@ TERMINAL_STATUSES = {
36
36
 
37
37
  # Statuses that should trigger auto-chaining
38
38
  CHAINABLE_STATUSES = {
39
- STATUS_DONE, # Always chain - results found
39
+ STATUS_DONE, # Always chain - results found
40
40
  STATUS_NO_RESULTS, # May chain if intelligence-driven
41
- STATUS_WARNING, # May chain with special handling
41
+ STATUS_WARNING, # May chain with special handling
42
42
  }
43
43
 
44
44
 
@@ -60,45 +60,13 @@ def get_status_display_info(status: str) -> dict:
60
60
  dict with 'color', 'icon', and 'label' keys
61
61
  """
62
62
  status_info = {
63
- STATUS_QUEUED: {
64
- 'color': 'cyan',
65
- 'icon': '◷',
66
- 'label': 'queued'
67
- },
68
- STATUS_RUNNING: {
69
- 'color': 'yellow',
70
- 'icon': '▶',
71
- 'label': 'running'
72
- },
73
- STATUS_DONE: {
74
- 'color': 'green',
75
- 'icon': '✓',
76
- 'label': 'done'
77
- },
78
- STATUS_NO_RESULTS: {
79
- 'color': 'white',
80
- 'icon': '⊘',
81
- 'label': 'no results'
82
- },
83
- STATUS_WARNING: {
84
- 'color': 'yellow',
85
- 'icon': '⚠',
86
- 'label': 'warning'
87
- },
88
- STATUS_ERROR: {
89
- 'color': 'red',
90
- 'icon': '✗',
91
- 'label': 'error'
92
- },
93
- STATUS_KILLED: {
94
- 'color': 'magenta',
95
- 'icon': '●',
96
- 'label': 'killed'
97
- },
63
+ STATUS_QUEUED: {"color": "cyan", "icon": "◷", "label": "queued"},
64
+ STATUS_RUNNING: {"color": "yellow", "icon": "▶", "label": "running"},
65
+ STATUS_DONE: {"color": "green", "icon": "✓", "label": "done"},
66
+ STATUS_NO_RESULTS: {"color": "white", "icon": "⊘", "label": "no results"},
67
+ STATUS_WARNING: {"color": "yellow", "icon": "⚠", "label": "warning"},
68
+ STATUS_ERROR: {"color": "red", "icon": "✗", "label": "error"},
69
+ STATUS_KILLED: {"color": "magenta", "icon": "●", "label": "killed"},
98
70
  }
99
71
 
100
- return status_info.get(status, {
101
- 'color': 'white',
102
- 'icon': '?',
103
- 'label': status
104
- })
72
+ return status_info.get(status, {"color": "white", "icon": "?", "label": status})
@@ -12,86 +12,112 @@ from typing import Optional
12
12
  class LogSanitizer:
13
13
  """
14
14
  Sanitizes logs by redacting credentials and sensitive information.
15
-
15
+
16
16
  Patterns detected:
17
17
  - Login successful messages with credentials
18
18
  - Username:password combinations
19
19
  - SSH/FTP/MySQL/PostgreSQL credentials
20
20
  - API keys and tokens
21
21
  """
22
-
22
+
23
23
  # Common credential patterns
24
24
  PATTERNS = [
25
25
  # Metasploit successful login: [+] 10.0.0.82:5432 - Login Successful: postgres:postgres@template1
26
- (r'(Login Successful:?\s+)([^:]+):([^@\s]+)(@\S+)?', r'\1\2:[REDACTED]\4'),
27
-
26
+ (r"(Login Successful:?\s+)([^:]+):([^@\s]+)(@\S+)?", r"\1\2:[REDACTED]\4"),
28
27
  # MSF telnet_login format: msfadmin:msfadmin login: Login OK
29
- (r'(\s)([^:\s]+):([^:\s]+)(\s+login:\s+Login OK)', r'\1\2:[REDACTED]\4'),
30
-
28
+ (r"(\s)([^:\s]+):([^:\s]+)(\s+login:\s+Login OK)", r"\1\2:[REDACTED]\4"),
31
29
  # Hydra output format: login: username password: secretpass
32
- (r'(login:\s+)(\S+)(\s+password:\s+)(\S+)', r'\1\2\3[REDACTED]'),
33
-
30
+ (r"(login:\s+)(\S+)(\s+password:\s+)(\S+)", r"\1\2\3[REDACTED]"),
34
31
  # Hydra colon format in output: [port][service] host: X login: Y password: Z
35
- (r'(host:\s+\S+\s+login:\s+)(\S+)(\s+password:\s+)(.+?)(\s|$)', r'\1\2\3[REDACTED]\5'),
36
-
32
+ (
33
+ r"(host:\s+\S+\s+login:\s+)(\S+)(\s+password:\s+)(.+?)(\s|$)",
34
+ r"\1\2\3[REDACTED]\5",
35
+ ),
37
36
  # SSH/FTP success: Successfully authenticated as 'root' with password 'toor'
38
- (r"(authenticated as ['\"]?\w+['\"]? with password ['\"]?)([^'\"]+)(['\"]?)", r'\1[REDACTED]\3'),
39
-
37
+ (
38
+ r"(authenticated as ['\"]?\w+['\"]? with password ['\"]?)([^'\"]+)(['\"]?)",
39
+ r"\1[REDACTED]\3",
40
+ ),
40
41
  # MySQL/PostgreSQL connection strings - capture everything between : and last @
41
42
  # This handles passwords with @ symbols by matching the last @ before a hostname
42
- (r'((?:mysql|postgres|postgresql)://[^:]+:)(.+)(@(?:(?:\d{1,3}\.){3}\d{1,3}(?::\d+)?|[a-zA-Z0-9.-]+(?::\d+)?)(?:/|$))', r'\1[REDACTED]\3'),
43
-
43
+ (
44
+ r"((?:mysql|postgres|postgresql)://[^:]+:)(.+)(@(?:(?:\d{1,3}\.){3}\d{1,3}(?::\d+)?|[a-zA-Z0-9.-]+(?::\d+)?)(?:/|$))",
45
+ r"\1[REDACTED]\3",
46
+ ),
44
47
  # Direct credentials: username:password format (but not URLs)
45
- (r'(?<!://)\b(\w+):([^\s:@]{4,})@', r'\1:[REDACTED]@'),
46
-
48
+ (r"(?<!://)\b(\w+):([^\s:@]{4,})@", r"\1:[REDACTED]@"),
47
49
  # Common password indicators (stop at & to preserve form parameters)
48
- (r'(password[=:\s]+["\']?)([^"\'\s&]{4,})(["\']?)', r'\1[REDACTED]\3', re.IGNORECASE),
49
- (r'(pass[=:\s]+["\']?)([^"\'\s&]{4,})(["\']?)', r'\1[REDACTED]\3', re.IGNORECASE),
50
- (r'(pwd[=:\s]+["\']?)([^"\'\s&]{4,})(["\']?)', r'\1[REDACTED]\3', re.IGNORECASE),
51
-
50
+ (
51
+ r'(password[=:\s]+["\']?)([^"\'\s&]{4,})(["\']?)',
52
+ r"\1[REDACTED]\3",
53
+ re.IGNORECASE,
54
+ ),
55
+ (
56
+ r'(pass[=:\s]+["\']?)([^"\'\s&]{4,})(["\']?)',
57
+ r"\1[REDACTED]\3",
58
+ re.IGNORECASE,
59
+ ),
60
+ (
61
+ r'(pwd[=:\s]+["\']?)([^"\'\s&]{4,})(["\']?)',
62
+ r"\1[REDACTED]\3",
63
+ re.IGNORECASE,
64
+ ),
52
65
  # API keys and tokens (long alphanumeric strings)
53
- (r'(["\']?api[_-]?key["\']?\s*[=:]\s*["\']?)([A-Za-z0-9_-]{20,})(["\']?)', r'\1[REDACTED]\3', re.IGNORECASE),
54
- (r'(["\']?token["\']?\s*[=:]\s*["\']?)([A-Za-z0-9_.-]{20,})(["\']?)', r'\1[REDACTED]\3', re.IGNORECASE),
55
-
66
+ (
67
+ r'(["\']?api[_-]?key["\']?\s*[=:]\s*["\']?)([A-Za-z0-9_-]{20,})(["\']?)',
68
+ r"\1[REDACTED]\3",
69
+ re.IGNORECASE,
70
+ ),
71
+ (
72
+ r'(["\']?token["\']?\s*[=:]\s*["\']?)([A-Za-z0-9_.-]{20,})(["\']?)',
73
+ r"\1[REDACTED]\3",
74
+ re.IGNORECASE,
75
+ ),
56
76
  # SSH private keys
57
- (r'(-----BEGIN[A-Z\s]+PRIVATE KEY-----)(.*?)(-----END[A-Z\s]+PRIVATE KEY-----)', r'\1\n[REDACTED]\n\3', re.DOTALL),
58
-
77
+ (
78
+ r"(-----BEGIN[A-Z\s]+PRIVATE KEY-----)(.*?)(-----END[A-Z\s]+PRIVATE KEY-----)",
79
+ r"\1\n[REDACTED]\n\3",
80
+ re.DOTALL,
81
+ ),
59
82
  # Hashes (common hash formats: MD5, SHA1, SHA256)
60
- (r'\b([a-f0-9]{32})\b', r'[HASH_REDACTED]'), # MD5
61
- (r'\b([a-f0-9]{40})\b', r'[HASH_REDACTED]'), # SHA1
62
- (r'\b([a-f0-9]{64})\b', r'[HASH_REDACTED]'), # SHA256
63
-
83
+ (r"\b([a-f0-9]{32})\b", r"[HASH_REDACTED]"), # MD5
84
+ (r"\b([a-f0-9]{40})\b", r"[HASH_REDACTED]"), # SHA1
85
+ (r"\b([a-f0-9]{64})\b", r"[HASH_REDACTED]"), # SHA256
64
86
  # Generic secret patterns
65
- (r'(secret[=:\s]+["\']?)([^"\'\s]{4,})(["\']?)', r'\1[REDACTED]\3', re.IGNORECASE),
87
+ (
88
+ r'(secret[=:\s]+["\']?)([^"\'\s]{4,})(["\']?)',
89
+ r"\1[REDACTED]\3",
90
+ re.IGNORECASE,
91
+ ),
66
92
  ]
67
-
93
+
68
94
  # Whitelist patterns (don't redact these even if they match)
69
95
  WHITELIST_PATTERNS = [
70
- r'http://',
71
- r'https://',
72
- r'localhost',
73
- r'127\.0\.0\.1',
74
- r'0\.0\.0\.0',
75
- r'example\.com',
96
+ r"http://",
97
+ r"https://",
98
+ r"localhost",
99
+ r"127\.0\.0\.1",
100
+ r"0\.0\.0\.0",
101
+ r"example\.com",
76
102
  ]
77
-
103
+
78
104
  @classmethod
79
105
  def sanitize(cls, log_content: str, aggressive: bool = False) -> str:
80
106
  """
81
107
  Sanitize log content by redacting credentials.
82
-
108
+
83
109
  Args:
84
110
  log_content: Raw log content
85
111
  aggressive: If True, use more aggressive redaction (may over-redact)
86
-
112
+
87
113
  Returns:
88
114
  Sanitized log content with credentials redacted
89
115
  """
90
116
  if not log_content:
91
117
  return log_content
92
-
118
+
93
119
  sanitized = log_content
94
-
120
+
95
121
  # Apply all patterns
96
122
  for pattern_tuple in cls.PATTERNS:
97
123
  if len(pattern_tuple) == 2:
@@ -99,100 +125,100 @@ class LogSanitizer:
99
125
  flags = 0
100
126
  else:
101
127
  pattern, replacement, flags = pattern_tuple
102
-
128
+
103
129
  try:
104
130
  sanitized = re.sub(pattern, replacement, sanitized, flags=flags)
105
131
  except Exception:
106
132
  # If regex fails, continue with next pattern
107
133
  continue
108
-
134
+
109
135
  return sanitized
110
-
136
+
111
137
  @classmethod
112
138
  def contains_credentials(cls, log_content: str) -> bool:
113
139
  """
114
140
  Check if log content appears to contain credentials.
115
-
141
+
116
142
  Args:
117
143
  log_content: Log content to check
118
-
144
+
119
145
  Returns:
120
146
  True if credentials detected, False otherwise
121
147
  """
122
148
  if not log_content:
123
149
  return False
124
-
150
+
125
151
  # Quick checks for common credential indicators
126
152
  indicators = [
127
- 'login successful',
128
- 'login ok', # MSF telnet_login
129
- 'authenticated',
130
- 'password:',
131
- 'credentials',
132
- 'api_key',
133
- 'api-key',
134
- 'token:',
135
- 'secret:',
136
- 'BEGIN PRIVATE KEY',
137
- 'login:', # Hydra output
138
- 'valid pair found', # Hydra success
153
+ "login successful",
154
+ "login ok", # MSF telnet_login
155
+ "authenticated",
156
+ "password:",
157
+ "credentials",
158
+ "api_key",
159
+ "api-key",
160
+ "token:",
161
+ "secret:",
162
+ "BEGIN PRIVATE KEY",
163
+ "login:", # Hydra output
164
+ "valid pair found", # Hydra success
139
165
  ]
140
-
166
+
141
167
  log_lower = log_content.lower()
142
168
  return any(indicator in log_lower for indicator in indicators)
143
-
169
+
144
170
  @classmethod
145
171
  def get_redaction_summary(cls, original: str, sanitized: str) -> Optional[str]:
146
172
  """
147
173
  Generate a summary of what was redacted.
148
-
174
+
149
175
  Args:
150
176
  original: Original log content
151
177
  sanitized: Sanitized log content
152
-
178
+
153
179
  Returns:
154
180
  Summary message or None if nothing redacted
155
181
  """
156
182
  if original == sanitized:
157
183
  return None
158
-
184
+
159
185
  # Count how many times [REDACTED] appears in sanitized version
160
- redaction_count = sanitized.count('[REDACTED]')
161
- hash_count = sanitized.count('[HASH_REDACTED]')
162
-
186
+ redaction_count = sanitized.count("[REDACTED]")
187
+ hash_count = sanitized.count("[HASH_REDACTED]")
188
+
163
189
  parts = []
164
190
  if redaction_count > 0:
165
191
  parts.append(f"{redaction_count} credential(s)")
166
192
  if hash_count > 0:
167
193
  parts.append(f"{hash_count} hash(es)")
168
-
194
+
169
195
  if parts:
170
196
  return f"Redacted: {', '.join(parts)}"
171
-
197
+
172
198
  return "Some sensitive data redacted"
173
199
 
174
200
 
175
201
  def sanitize_log_file(log_path: str, output_path: Optional[str] = None) -> bool:
176
202
  """
177
203
  Sanitize a log file in place or write to new file.
178
-
204
+
179
205
  Args:
180
206
  log_path: Path to log file to sanitize
181
207
  output_path: Optional output path (if None, modifies in place)
182
-
208
+
183
209
  Returns:
184
210
  True if successful, False otherwise
185
211
  """
186
212
  try:
187
- with open(log_path, 'r', encoding='utf-8', errors='replace') as f:
213
+ with open(log_path, "r", encoding="utf-8", errors="replace") as f:
188
214
  original = f.read()
189
-
215
+
190
216
  sanitized = LogSanitizer.sanitize(original)
191
-
217
+
192
218
  target_path = output_path or log_path
193
- with open(target_path, 'w', encoding='utf-8') as f:
219
+ with open(target_path, "w", encoding="utf-8") as f:
194
220
  f.write(sanitized)
195
-
221
+
196
222
  return True
197
223
  except Exception:
198
224
  return False
@@ -17,11 +17,18 @@ import importlib
17
17
 
18
18
  def _run_nmap_adapter(target, args, label, save_xml=False):
19
19
  from .. import scanner as scanner_module
20
+
20
21
  # scanner.run_nmap should return (logpath, rc, xmlpath, summary)
21
22
  return scanner_module.run_nmap(target, args, label, save_xml=save_xml)
22
23
 
23
24
 
24
- def run_scan_sync(tool: str, target: str, args: list, label: Optional[str] = None, save_xml: bool = False) -> int:
25
+ def run_scan_sync(
26
+ tool: str,
27
+ target: str,
28
+ args: list,
29
+ label: Optional[str] = None,
30
+ save_xml: bool = False,
31
+ ) -> int:
25
32
  """
26
33
  Run a scan synchronously and return the DB scan id.
27
34
  Currently supports 'nmap' as a built-in. Creates a DB record, runs, updates DB.
@@ -39,16 +46,26 @@ def run_scan_sync(tool: str, target: str, args: list, label: Optional[str] = Non
39
46
  "summary": {},
40
47
  "per_host": [],
41
48
  "status": "pending",
42
- "rc": None
49
+ "rc": None,
43
50
  }
44
51
  scan_id = insert_scan(entry)
45
52
 
46
53
  try:
47
54
  if tool.lower() == "nmap":
48
- logpath, rc, xmlpath, summary = _run_nmap_adapter(target, args, label, save_xml=save_xml)
55
+ logpath, rc, xmlpath, summary = _run_nmap_adapter(
56
+ target, args, label, save_xml=save_xml
57
+ )
49
58
  # ensure per_host in summary (some parsers provide it)
50
59
  per_host = summary.get("per_host") if isinstance(summary, dict) else []
51
- update_scan(scan_id, status="done", rc=rc, log=logpath, xml=xmlpath, summary=summary, per_host=per_host)
60
+ update_scan(
61
+ scan_id,
62
+ status="done",
63
+ rc=rc,
64
+ log=logpath,
65
+ xml=xmlpath,
66
+ summary=summary,
67
+ per_host=per_host,
68
+ )
52
69
  else:
53
70
  # try to import a plugin module by convention souleyez.plugins.<tool>
54
71
  try:
@@ -58,7 +75,15 @@ def run_scan_sync(tool: str, target: str, args: list, label: Optional[str] = Non
58
75
  plugin = PluginClass()
59
76
  prepared = plugin.prepare(target, args, label)
60
77
  result = plugin.run(prepared)
61
- update_scan(scan_id, status=result.get("status", "done"), rc=result.get("rc"), log=result.get("log"), xml=result.get("xml"), summary=result.get("summary"), per_host=result.get("per_host"))
78
+ update_scan(
79
+ scan_id,
80
+ status=result.get("status", "done"),
81
+ rc=result.get("rc"),
82
+ log=result.get("log"),
83
+ xml=result.get("xml"),
84
+ summary=result.get("summary"),
85
+ per_host=result.get("per_host"),
86
+ )
62
87
  else:
63
88
  update_scan(scan_id, status="failed")
64
89
  except Exception:
@@ -68,7 +93,13 @@ def run_scan_sync(tool: str, target: str, args: list, label: Optional[str] = Non
68
93
  return scan_id
69
94
 
70
95
 
71
- def run_scan_background(tool: str, target: str, args: list, label: Optional[str] = None, save_xml: bool = False) -> int:
96
+ def run_scan_background(
97
+ tool: str,
98
+ target: str,
99
+ args: list,
100
+ label: Optional[str] = None,
101
+ save_xml: bool = False,
102
+ ) -> int:
72
103
  """
73
104
  Run the scan in a background thread and return the DB id immediately.
74
105
  """
@@ -85,7 +116,7 @@ def run_scan_background(tool: str, target: str, args: list, label: Optional[str]
85
116
  "summary": {},
86
117
  "per_host": [],
87
118
  "status": "pending",
88
- "rc": None
119
+ "rc": None,
89
120
  }
90
121
  scan_id = insert_scan(entry)
91
122