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
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