souleyez 2.43.28__py3-none-any.whl → 2.43.32__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (356) hide show
  1. souleyez/__init__.py +1 -2
  2. souleyez/ai/__init__.py +21 -15
  3. souleyez/ai/action_mapper.py +249 -150
  4. souleyez/ai/chain_advisor.py +116 -100
  5. souleyez/ai/claude_provider.py +29 -28
  6. souleyez/ai/context_builder.py +80 -62
  7. souleyez/ai/executor.py +158 -117
  8. souleyez/ai/feedback_handler.py +136 -121
  9. souleyez/ai/llm_factory.py +27 -20
  10. souleyez/ai/llm_provider.py +4 -2
  11. souleyez/ai/ollama_provider.py +6 -9
  12. souleyez/ai/ollama_service.py +44 -37
  13. souleyez/ai/path_scorer.py +91 -76
  14. souleyez/ai/recommender.py +176 -144
  15. souleyez/ai/report_context.py +74 -73
  16. souleyez/ai/report_service.py +84 -66
  17. souleyez/ai/result_parser.py +222 -229
  18. souleyez/ai/safety.py +67 -44
  19. souleyez/auth/__init__.py +23 -22
  20. souleyez/auth/audit.py +36 -26
  21. souleyez/auth/engagement_access.py +65 -48
  22. souleyez/auth/permissions.py +14 -3
  23. souleyez/auth/session_manager.py +54 -37
  24. souleyez/auth/user_manager.py +109 -64
  25. souleyez/commands/audit.py +40 -43
  26. souleyez/commands/auth.py +35 -15
  27. souleyez/commands/deliverables.py +55 -50
  28. souleyez/commands/engagement.py +47 -28
  29. souleyez/commands/license.py +32 -23
  30. souleyez/commands/screenshots.py +36 -32
  31. souleyez/commands/user.py +82 -36
  32. souleyez/config.py +52 -44
  33. souleyez/core/credential_tester.py +87 -81
  34. souleyez/core/cve_mappings.py +179 -192
  35. souleyez/core/cve_matcher.py +162 -148
  36. souleyez/core/msf_auto_mapper.py +100 -83
  37. souleyez/core/msf_chain_engine.py +294 -256
  38. souleyez/core/msf_database.py +153 -70
  39. souleyez/core/msf_integration.py +679 -673
  40. souleyez/core/msf_rpc_client.py +40 -42
  41. souleyez/core/msf_rpc_manager.py +77 -79
  42. souleyez/core/msf_sync_manager.py +241 -181
  43. souleyez/core/network_utils.py +22 -15
  44. souleyez/core/parser_handler.py +34 -25
  45. souleyez/core/pending_chains.py +114 -63
  46. souleyez/core/templates.py +158 -107
  47. souleyez/core/tool_chaining.py +9592 -2879
  48. souleyez/core/version_utils.py +79 -94
  49. souleyez/core/vuln_correlation.py +136 -89
  50. souleyez/core/web_utils.py +33 -32
  51. souleyez/data/wordlists/ad_users.txt +378 -0
  52. souleyez/data/wordlists/api_endpoints_large.txt +769 -0
  53. souleyez/data/wordlists/home_dir_sensitive.txt +39 -0
  54. souleyez/data/wordlists/lfi_payloads.txt +82 -0
  55. souleyez/data/wordlists/passwords_brute.txt +1548 -0
  56. souleyez/data/wordlists/passwords_crack.txt +2479 -0
  57. souleyez/data/wordlists/passwords_spray.txt +386 -0
  58. souleyez/data/wordlists/subdomains_large.txt +5057 -0
  59. souleyez/data/wordlists/usernames_common.txt +694 -0
  60. souleyez/data/wordlists/web_dirs_large.txt +4769 -0
  61. souleyez/detection/__init__.py +1 -1
  62. souleyez/detection/attack_signatures.py +12 -17
  63. souleyez/detection/mitre_mappings.py +61 -55
  64. souleyez/detection/validator.py +97 -86
  65. souleyez/devtools.py +23 -10
  66. souleyez/docs/README.md +4 -4
  67. souleyez/docs/api-reference/cli-commands.md +2 -2
  68. souleyez/docs/developer-guide/adding-new-tools.md +562 -0
  69. souleyez/docs/user-guide/auto-chaining.md +30 -8
  70. souleyez/docs/user-guide/getting-started.md +1 -1
  71. souleyez/docs/user-guide/installation.md +26 -3
  72. souleyez/docs/user-guide/metasploit-integration.md +2 -2
  73. souleyez/docs/user-guide/rbac.md +1 -1
  74. souleyez/docs/user-guide/scope-management.md +1 -1
  75. souleyez/docs/user-guide/siem-integration.md +1 -1
  76. souleyez/docs/user-guide/tools-reference.md +1 -8
  77. souleyez/docs/user-guide/worker-management.md +1 -1
  78. souleyez/engine/background.py +1238 -535
  79. souleyez/engine/base.py +4 -1
  80. souleyez/engine/job_status.py +17 -49
  81. souleyez/engine/log_sanitizer.py +103 -77
  82. souleyez/engine/manager.py +38 -7
  83. souleyez/engine/result_handler.py +2198 -1550
  84. souleyez/engine/worker_manager.py +50 -41
  85. souleyez/export/evidence_bundle.py +72 -62
  86. souleyez/feature_flags/features.py +16 -20
  87. souleyez/feature_flags.py +5 -9
  88. souleyez/handlers/__init__.py +11 -0
  89. souleyez/handlers/base.py +188 -0
  90. souleyez/handlers/bash_handler.py +277 -0
  91. souleyez/handlers/bloodhound_handler.py +243 -0
  92. souleyez/handlers/certipy_handler.py +311 -0
  93. souleyez/handlers/crackmapexec_handler.py +486 -0
  94. souleyez/handlers/dnsrecon_handler.py +344 -0
  95. souleyez/handlers/enum4linux_handler.py +400 -0
  96. souleyez/handlers/evil_winrm_handler.py +493 -0
  97. souleyez/handlers/ffuf_handler.py +815 -0
  98. souleyez/handlers/gobuster_handler.py +1114 -0
  99. souleyez/handlers/gpp_extract_handler.py +334 -0
  100. souleyez/handlers/hashcat_handler.py +444 -0
  101. souleyez/handlers/hydra_handler.py +563 -0
  102. souleyez/handlers/impacket_getuserspns_handler.py +343 -0
  103. souleyez/handlers/impacket_psexec_handler.py +222 -0
  104. souleyez/handlers/impacket_secretsdump_handler.py +426 -0
  105. souleyez/handlers/john_handler.py +286 -0
  106. souleyez/handlers/katana_handler.py +425 -0
  107. souleyez/handlers/kerbrute_handler.py +298 -0
  108. souleyez/handlers/ldapsearch_handler.py +636 -0
  109. souleyez/handlers/lfi_extract_handler.py +464 -0
  110. souleyez/handlers/msf_auxiliary_handler.py +408 -0
  111. souleyez/handlers/msf_exploit_handler.py +380 -0
  112. souleyez/handlers/nikto_handler.py +413 -0
  113. souleyez/handlers/nmap_handler.py +821 -0
  114. souleyez/handlers/nuclei_handler.py +359 -0
  115. souleyez/handlers/nxc_handler.py +371 -0
  116. souleyez/handlers/rdp_sec_check_handler.py +353 -0
  117. souleyez/handlers/registry.py +288 -0
  118. souleyez/handlers/responder_handler.py +232 -0
  119. souleyez/handlers/service_explorer_handler.py +434 -0
  120. souleyez/handlers/smbclient_handler.py +344 -0
  121. souleyez/handlers/smbmap_handler.py +510 -0
  122. souleyez/handlers/smbpasswd_handler.py +296 -0
  123. souleyez/handlers/sqlmap_handler.py +1116 -0
  124. souleyez/handlers/theharvester_handler.py +601 -0
  125. souleyez/handlers/whois_handler.py +277 -0
  126. souleyez/handlers/wpscan_handler.py +554 -0
  127. souleyez/history.py +32 -16
  128. souleyez/importers/msf_importer.py +106 -75
  129. souleyez/importers/smart_importer.py +208 -147
  130. souleyez/integrations/siem/__init__.py +10 -10
  131. souleyez/integrations/siem/base.py +17 -18
  132. souleyez/integrations/siem/elastic.py +108 -122
  133. souleyez/integrations/siem/factory.py +207 -80
  134. souleyez/integrations/siem/googlesecops.py +146 -154
  135. souleyez/integrations/siem/rule_mappings/__init__.py +1 -1
  136. souleyez/integrations/siem/rule_mappings/wazuh_rules.py +8 -5
  137. souleyez/integrations/siem/sentinel.py +107 -109
  138. souleyez/integrations/siem/splunk.py +246 -212
  139. souleyez/integrations/siem/wazuh.py +65 -71
  140. souleyez/integrations/wazuh/__init__.py +5 -5
  141. souleyez/integrations/wazuh/client.py +70 -93
  142. souleyez/integrations/wazuh/config.py +85 -57
  143. souleyez/integrations/wazuh/host_mapper.py +28 -36
  144. souleyez/integrations/wazuh/sync.py +78 -68
  145. souleyez/intelligence/__init__.py +4 -5
  146. souleyez/intelligence/correlation_analyzer.py +309 -295
  147. souleyez/intelligence/exploit_knowledge.py +661 -623
  148. souleyez/intelligence/exploit_suggestions.py +159 -139
  149. souleyez/intelligence/gap_analyzer.py +132 -97
  150. souleyez/intelligence/gap_detector.py +251 -214
  151. souleyez/intelligence/sensitive_tables.py +266 -129
  152. souleyez/intelligence/service_parser.py +137 -123
  153. souleyez/intelligence/surface_analyzer.py +407 -268
  154. souleyez/intelligence/target_parser.py +159 -162
  155. souleyez/licensing/__init__.py +6 -6
  156. souleyez/licensing/validator.py +17 -19
  157. souleyez/log_config.py +79 -54
  158. souleyez/main.py +1505 -687
  159. souleyez/migrations/fix_job_counter.py +16 -14
  160. souleyez/parsers/bloodhound_parser.py +41 -39
  161. souleyez/parsers/crackmapexec_parser.py +178 -111
  162. souleyez/parsers/dalfox_parser.py +72 -77
  163. souleyez/parsers/dnsrecon_parser.py +103 -91
  164. souleyez/parsers/enum4linux_parser.py +183 -153
  165. souleyez/parsers/ffuf_parser.py +29 -25
  166. souleyez/parsers/gobuster_parser.py +301 -41
  167. souleyez/parsers/hashcat_parser.py +324 -79
  168. souleyez/parsers/http_fingerprint_parser.py +350 -103
  169. souleyez/parsers/hydra_parser.py +131 -111
  170. souleyez/parsers/impacket_parser.py +231 -178
  171. souleyez/parsers/john_parser.py +98 -86
  172. souleyez/parsers/katana_parser.py +316 -0
  173. souleyez/parsers/msf_parser.py +943 -498
  174. souleyez/parsers/nikto_parser.py +346 -65
  175. souleyez/parsers/nmap_parser.py +262 -174
  176. souleyez/parsers/nuclei_parser.py +40 -44
  177. souleyez/parsers/responder_parser.py +26 -26
  178. souleyez/parsers/searchsploit_parser.py +74 -74
  179. souleyez/parsers/service_explorer_parser.py +279 -0
  180. souleyez/parsers/smbmap_parser.py +180 -124
  181. souleyez/parsers/sqlmap_parser.py +434 -308
  182. souleyez/parsers/theharvester_parser.py +75 -57
  183. souleyez/parsers/whois_parser.py +135 -94
  184. souleyez/parsers/wpscan_parser.py +278 -190
  185. souleyez/plugins/afp.py +44 -36
  186. souleyez/plugins/afp_brute.py +114 -46
  187. souleyez/plugins/ard.py +48 -37
  188. souleyez/plugins/bloodhound.py +95 -61
  189. souleyez/plugins/certipy.py +303 -0
  190. souleyez/plugins/crackmapexec.py +186 -85
  191. souleyez/plugins/dalfox.py +120 -59
  192. souleyez/plugins/dns_hijack.py +146 -41
  193. souleyez/plugins/dnsrecon.py +97 -61
  194. souleyez/plugins/enum4linux.py +91 -66
  195. souleyez/plugins/evil_winrm.py +291 -0
  196. souleyez/plugins/ffuf.py +166 -90
  197. souleyez/plugins/firmware_extract.py +133 -29
  198. souleyez/plugins/gobuster.py +387 -190
  199. souleyez/plugins/gpp_extract.py +393 -0
  200. souleyez/plugins/hashcat.py +100 -73
  201. souleyez/plugins/http_fingerprint.py +854 -267
  202. souleyez/plugins/hydra.py +566 -200
  203. souleyez/plugins/impacket_getnpusers.py +117 -69
  204. souleyez/plugins/impacket_psexec.py +84 -64
  205. souleyez/plugins/impacket_secretsdump.py +103 -69
  206. souleyez/plugins/impacket_smbclient.py +89 -75
  207. souleyez/plugins/john.py +86 -69
  208. souleyez/plugins/katana.py +313 -0
  209. souleyez/plugins/kerbrute.py +237 -0
  210. souleyez/plugins/lfi_extract.py +541 -0
  211. souleyez/plugins/macos_ssh.py +117 -48
  212. souleyez/plugins/mdns.py +35 -30
  213. souleyez/plugins/msf_auxiliary.py +253 -130
  214. souleyez/plugins/msf_exploit.py +239 -161
  215. souleyez/plugins/nikto.py +134 -78
  216. souleyez/plugins/nmap.py +275 -91
  217. souleyez/plugins/nuclei.py +180 -89
  218. souleyez/plugins/nxc.py +285 -0
  219. souleyez/plugins/plugin_base.py +35 -36
  220. souleyez/plugins/plugin_template.py +13 -5
  221. souleyez/plugins/rdp_sec_check.py +130 -0
  222. souleyez/plugins/responder.py +112 -71
  223. souleyez/plugins/router_http_brute.py +76 -65
  224. souleyez/plugins/router_ssh_brute.py +118 -41
  225. souleyez/plugins/router_telnet_brute.py +124 -42
  226. souleyez/plugins/routersploit.py +91 -59
  227. souleyez/plugins/routersploit_exploit.py +77 -55
  228. souleyez/plugins/searchsploit.py +91 -77
  229. souleyez/plugins/service_explorer.py +1160 -0
  230. souleyez/plugins/smbmap.py +122 -72
  231. souleyez/plugins/smbpasswd.py +215 -0
  232. souleyez/plugins/sqlmap.py +301 -113
  233. souleyez/plugins/theharvester.py +127 -75
  234. souleyez/plugins/tr069.py +79 -57
  235. souleyez/plugins/upnp.py +65 -47
  236. souleyez/plugins/upnp_abuse.py +73 -55
  237. souleyez/plugins/vnc_access.py +129 -42
  238. souleyez/plugins/vnc_brute.py +109 -38
  239. souleyez/plugins/whois.py +77 -58
  240. souleyez/plugins/wpscan.py +173 -69
  241. souleyez/reporting/__init__.py +2 -1
  242. souleyez/reporting/attack_chain.py +411 -346
  243. souleyez/reporting/charts.py +436 -501
  244. souleyez/reporting/compliance_mappings.py +334 -201
  245. souleyez/reporting/detection_report.py +126 -125
  246. souleyez/reporting/formatters.py +828 -591
  247. souleyez/reporting/generator.py +386 -302
  248. souleyez/reporting/metrics.py +72 -75
  249. souleyez/scanner.py +35 -29
  250. souleyez/security/__init__.py +37 -11
  251. souleyez/security/scope_validator.py +175 -106
  252. souleyez/security/validation.py +223 -149
  253. souleyez/security.py +22 -6
  254. souleyez/storage/credentials.py +247 -186
  255. souleyez/storage/crypto.py +296 -129
  256. souleyez/storage/database.py +73 -50
  257. souleyez/storage/db.py +58 -36
  258. souleyez/storage/deliverable_evidence.py +177 -128
  259. souleyez/storage/deliverable_exporter.py +282 -246
  260. souleyez/storage/deliverable_templates.py +134 -116
  261. souleyez/storage/deliverables.py +135 -130
  262. souleyez/storage/engagements.py +109 -56
  263. souleyez/storage/evidence.py +181 -152
  264. souleyez/storage/execution_log.py +31 -17
  265. souleyez/storage/exploit_attempts.py +93 -57
  266. souleyez/storage/exploits.py +67 -36
  267. souleyez/storage/findings.py +48 -61
  268. souleyez/storage/hosts.py +176 -144
  269. souleyez/storage/migrate_to_engagements.py +43 -19
  270. souleyez/storage/migrations/_001_add_credential_enhancements.py +22 -12
  271. souleyez/storage/migrations/_002_add_status_tracking.py +10 -7
  272. souleyez/storage/migrations/_003_add_execution_log.py +14 -8
  273. souleyez/storage/migrations/_005_screenshots.py +13 -5
  274. souleyez/storage/migrations/_006_deliverables.py +13 -5
  275. souleyez/storage/migrations/_007_deliverable_templates.py +12 -7
  276. souleyez/storage/migrations/_008_add_nuclei_table.py +10 -4
  277. souleyez/storage/migrations/_010_evidence_linking.py +17 -10
  278. souleyez/storage/migrations/_011_timeline_tracking.py +20 -13
  279. souleyez/storage/migrations/_012_team_collaboration.py +34 -21
  280. souleyez/storage/migrations/_013_add_host_tags.py +12 -6
  281. souleyez/storage/migrations/_014_exploit_attempts.py +22 -10
  282. souleyez/storage/migrations/_015_add_mac_os_fields.py +15 -7
  283. souleyez/storage/migrations/_016_add_domain_field.py +10 -4
  284. souleyez/storage/migrations/_017_msf_sessions.py +16 -8
  285. souleyez/storage/migrations/_018_add_osint_target.py +10 -6
  286. souleyez/storage/migrations/_019_add_engagement_type.py +10 -6
  287. souleyez/storage/migrations/_020_add_rbac.py +36 -15
  288. souleyez/storage/migrations/_021_wazuh_integration.py +20 -8
  289. souleyez/storage/migrations/_022_wazuh_indexer_columns.py +6 -4
  290. souleyez/storage/migrations/_023_fix_detection_results_fk.py +16 -6
  291. souleyez/storage/migrations/_024_wazuh_vulnerabilities.py +26 -10
  292. souleyez/storage/migrations/_025_multi_siem_support.py +3 -5
  293. souleyez/storage/migrations/_026_add_engagement_scope.py +31 -12
  294. souleyez/storage/migrations/_027_multi_siem_persistence.py +32 -15
  295. souleyez/storage/migrations/__init__.py +26 -26
  296. souleyez/storage/migrations/migration_manager.py +19 -19
  297. souleyez/storage/msf_sessions.py +100 -65
  298. souleyez/storage/osint.py +17 -24
  299. souleyez/storage/recommendation_engine.py +269 -235
  300. souleyez/storage/screenshots.py +33 -32
  301. souleyez/storage/smb_shares.py +136 -92
  302. souleyez/storage/sqlmap_data.py +183 -128
  303. souleyez/storage/team_collaboration.py +135 -141
  304. souleyez/storage/timeline_tracker.py +122 -94
  305. souleyez/storage/wazuh_vulns.py +64 -66
  306. souleyez/storage/web_paths.py +33 -37
  307. souleyez/testing/credential_tester.py +221 -205
  308. souleyez/ui/__init__.py +1 -1
  309. souleyez/ui/ai_quotes.py +12 -12
  310. souleyez/ui/attack_surface.py +2439 -1516
  311. souleyez/ui/chain_rules_view.py +914 -382
  312. souleyez/ui/correlation_view.py +312 -230
  313. souleyez/ui/dashboard.py +2382 -1130
  314. souleyez/ui/deliverables_view.py +148 -62
  315. souleyez/ui/design_system.py +13 -13
  316. souleyez/ui/errors.py +49 -49
  317. souleyez/ui/evidence_linking_view.py +284 -179
  318. souleyez/ui/evidence_vault.py +393 -285
  319. souleyez/ui/exploit_suggestions_view.py +555 -349
  320. souleyez/ui/export_view.py +100 -66
  321. souleyez/ui/gap_analysis_view.py +315 -171
  322. souleyez/ui/help_system.py +105 -97
  323. souleyez/ui/intelligence_view.py +436 -293
  324. souleyez/ui/interactive.py +23142 -10430
  325. souleyez/ui/interactive_selector.py +75 -68
  326. souleyez/ui/log_formatter.py +47 -39
  327. souleyez/ui/menu_components.py +22 -13
  328. souleyez/ui/msf_auxiliary_menu.py +184 -133
  329. souleyez/ui/pending_chains_view.py +336 -172
  330. souleyez/ui/progress_indicators.py +5 -3
  331. souleyez/ui/recommendations_view.py +195 -137
  332. souleyez/ui/rule_builder.py +343 -225
  333. souleyez/ui/setup_wizard.py +678 -284
  334. souleyez/ui/shortcuts.py +217 -165
  335. souleyez/ui/splunk_gap_analysis_view.py +452 -270
  336. souleyez/ui/splunk_vulns_view.py +139 -86
  337. souleyez/ui/team_dashboard.py +498 -335
  338. souleyez/ui/template_selector.py +196 -105
  339. souleyez/ui/terminal.py +6 -6
  340. souleyez/ui/timeline_view.py +198 -127
  341. souleyez/ui/tool_setup.py +264 -164
  342. souleyez/ui/tutorial.py +202 -72
  343. souleyez/ui/tutorial_state.py +40 -40
  344. souleyez/ui/wazuh_vulns_view.py +235 -141
  345. souleyez/ui/wordlist_browser.py +260 -107
  346. souleyez/ui.py +464 -312
  347. souleyez/utils/tool_checker.py +427 -367
  348. souleyez/utils.py +33 -29
  349. souleyez/wordlists.py +134 -167
  350. {souleyez-2.43.28.dist-info → souleyez-2.43.32.dist-info}/METADATA +1 -1
  351. souleyez-2.43.32.dist-info/RECORD +441 -0
  352. {souleyez-2.43.28.dist-info → souleyez-2.43.32.dist-info}/WHEEL +1 -1
  353. souleyez-2.43.28.dist-info/RECORD +0 -379
  354. {souleyez-2.43.28.dist-info → souleyez-2.43.32.dist-info}/entry_points.txt +0 -0
  355. {souleyez-2.43.28.dist-info → souleyez-2.43.32.dist-info}/licenses/LICENSE +0 -0
  356. {souleyez-2.43.28.dist-info → souleyez-2.43.32.dist-info}/top_level.txt +0 -0
@@ -13,12 +13,13 @@ from typing import List, Optional, Tuple
13
13
 
14
14
  class VersionOperator(Enum):
15
15
  """Comparison operators for version conditions."""
16
- LT = '<'
17
- LE = '<='
18
- GT = '>'
19
- GE = '>='
20
- EQ = '='
21
- NE = '!='
16
+
17
+ LT = "<"
18
+ LE = "<="
19
+ GT = ">"
20
+ GE = ">="
21
+ EQ = "="
22
+ NE = "!="
22
23
 
23
24
 
24
25
  @dataclass
@@ -31,23 +32,24 @@ class SemanticVersion:
31
32
  - 2.4.49, 8.2p1
32
33
  - 1.19.0-alpine, 7.4.3-fpm
33
34
  """
35
+
34
36
  major: int
35
37
  minor: int = 0
36
38
  patch: int = 0
37
39
  extra: int = 0
38
- prerelease: str = ''
39
- raw: str = ''
40
+ prerelease: str = ""
41
+ raw: str = ""
40
42
 
41
- def __lt__(self, other: 'SemanticVersion') -> bool:
43
+ def __lt__(self, other: "SemanticVersion") -> bool:
42
44
  return self._compare(other) < 0
43
45
 
44
- def __le__(self, other: 'SemanticVersion') -> bool:
46
+ def __le__(self, other: "SemanticVersion") -> bool:
45
47
  return self._compare(other) <= 0
46
48
 
47
- def __gt__(self, other: 'SemanticVersion') -> bool:
49
+ def __gt__(self, other: "SemanticVersion") -> bool:
48
50
  return self._compare(other) > 0
49
51
 
50
- def __ge__(self, other: 'SemanticVersion') -> bool:
52
+ def __ge__(self, other: "SemanticVersion") -> bool:
51
53
  return self._compare(other) >= 0
52
54
 
53
55
  def __eq__(self, other: object) -> bool:
@@ -58,7 +60,7 @@ class SemanticVersion:
58
60
  def __ne__(self, other: object) -> bool:
59
61
  return not self.__eq__(other)
60
62
 
61
- def _compare(self, other: 'SemanticVersion') -> int:
63
+ def _compare(self, other: "SemanticVersion") -> int:
62
64
  """Compare two versions. Returns -1, 0, or 1."""
63
65
  # Compare major.minor.patch.extra
64
66
  for self_val, other_val in [
@@ -99,6 +101,7 @@ class SemanticVersion:
99
101
  @dataclass
100
102
  class VersionCondition:
101
103
  """Single version comparison condition."""
104
+
102
105
  operator: VersionOperator
103
106
  version: SemanticVersion
104
107
 
@@ -122,20 +125,20 @@ class VersionCondition:
122
125
  # Regex for parsing version strings
123
126
  # Matches: 1.0, 1.0.0, 2.4.49, 8.2p1, 1.19.0-alpine, 7.4.3.1
124
127
  VERSION_PATTERN = re.compile(
125
- r'^(\d+)' # Major (required)
126
- r'(?:\.(\d+))?' # Minor (optional)
127
- r'(?:\.(\d+))?' # Patch (optional)
128
- r'(?:\.(\d+))?' # Extra (optional, for versions like 1.0.0.1)
129
- r'(?:[p\-_]([a-zA-Z0-9\-_.]+))?' # Prerelease (optional, after p/- or _)
128
+ r"^(\d+)" # Major (required)
129
+ r"(?:\.(\d+))?" # Minor (optional)
130
+ r"(?:\.(\d+))?" # Patch (optional)
131
+ r"(?:\.(\d+))?" # Extra (optional, for versions like 1.0.0.1)
132
+ r"(?:[p\-_]([a-zA-Z0-9\-_.]+))?" # Prerelease (optional, after p/- or _)
130
133
  )
131
134
 
132
135
  # Regex for parsing version conditions
133
136
  # Matches: <1.19, >=2.4.49, =1.0.0, !=2.0
134
137
  CONDITION_PATTERN = re.compile(
135
- r'^(<=?|>=?|!=|=)?' # Operator (optional, defaults to =)
136
- r'(\d+(?:\.\d+)*' # Version numbers
137
- r'(?:[p\-_][a-zA-Z0-9\-_.]+)?)' # Optional prerelease
138
- r'$'
138
+ r"^(<=?|>=?|!=|=)?" # Operator (optional, defaults to =)
139
+ r"(\d+(?:\.\d+)*" # Version numbers
140
+ r"(?:[p\-_][a-zA-Z0-9\-_.]+)?)" # Optional prerelease
141
+ r"$"
139
142
  )
140
143
 
141
144
 
@@ -159,7 +162,9 @@ def parse_version(version_str: str) -> Optional[SemanticVersion]:
159
162
 
160
163
  # Handle versions like "OpenSSH 8.2p1" - extract just the version part
161
164
  # Look for first digit sequence that looks like a version
162
- version_match = re.search(r'(\d+(?:\.\d+)*(?:[p\-_][a-zA-Z0-9\-_.]*)?)', version_str)
165
+ version_match = re.search(
166
+ r"(\d+(?:\.\d+)*(?:[p\-_][a-zA-Z0-9\-_.]*)?)", version_str
167
+ )
163
168
  if not version_match:
164
169
  return None
165
170
 
@@ -173,7 +178,7 @@ def parse_version(version_str: str) -> Optional[SemanticVersion]:
173
178
  minor = int(match.group(2)) if match.group(2) else 0
174
179
  patch = int(match.group(3)) if match.group(3) else 0
175
180
  extra = int(match.group(4)) if match.group(4) else 0
176
- prerelease = match.group(5) or ''
181
+ prerelease = match.group(5) or ""
177
182
 
178
183
  return SemanticVersion(
179
184
  major=major,
@@ -181,7 +186,7 @@ def parse_version(version_str: str) -> Optional[SemanticVersion]:
181
186
  patch=patch,
182
187
  extra=extra,
183
188
  prerelease=prerelease,
184
- raw=version_str
189
+ raw=version_str,
185
190
  )
186
191
 
187
192
 
@@ -202,17 +207,17 @@ def parse_condition(condition_str: str) -> Optional[VersionCondition]:
202
207
  if not match:
203
208
  return None
204
209
 
205
- operator_str = match.group(1) or '='
210
+ operator_str = match.group(1) or "="
206
211
  version_str = match.group(2)
207
212
 
208
213
  # Map operator string to enum
209
214
  operator_map = {
210
- '<': VersionOperator.LT,
211
- '<=': VersionOperator.LE,
212
- '>': VersionOperator.GT,
213
- '>=': VersionOperator.GE,
214
- '=': VersionOperator.EQ,
215
- '!=': VersionOperator.NE,
215
+ "<": VersionOperator.LT,
216
+ "<=": VersionOperator.LE,
217
+ ">": VersionOperator.GT,
218
+ ">=": VersionOperator.GE,
219
+ "=": VersionOperator.EQ,
220
+ "!=": VersionOperator.NE,
216
221
  }
217
222
  operator = operator_map.get(operator_str, VersionOperator.EQ)
218
223
 
@@ -237,7 +242,7 @@ def parse_version_conditions(condition_str: str) -> List[VersionCondition]:
237
242
  return []
238
243
 
239
244
  conditions = []
240
- for part in condition_str.split(','):
245
+ for part in condition_str.split(","):
241
246
  part = part.strip()
242
247
  if part:
243
248
  cond = parse_condition(part)
@@ -259,10 +264,10 @@ def parse_version_spec(spec: str) -> Tuple[str, List[VersionCondition]]:
259
264
 
260
265
  Returns (product_name, conditions_list).
261
266
  """
262
- if ':' not in spec:
263
- return ('', [])
267
+ if ":" not in spec:
268
+ return ("", [])
264
269
 
265
- parts = spec.split(':', 1)
270
+ parts = spec.split(":", 1)
266
271
  product = parts[0].strip().lower()
267
272
  conditions = parse_version_conditions(parts[1]) if len(parts) > 1 else []
268
273
 
@@ -294,73 +299,57 @@ def matches_version(detected_version: str, conditions: List[VersionCondition]) -
294
299
  # Product name normalization mapping
295
300
  PRODUCT_ALIASES = {
296
301
  # Apache
297
- 'apache httpd': 'apache',
298
- 'apache http server': 'apache',
299
- 'apache/': 'apache',
300
- 'httpd': 'apache',
301
-
302
+ "apache httpd": "apache",
303
+ "apache http server": "apache",
304
+ "apache/": "apache",
305
+ "httpd": "apache",
302
306
  # nginx
303
- 'nginx/': 'nginx',
304
-
307
+ "nginx/": "nginx",
305
308
  # OpenSSH
306
- 'openssh': 'ssh',
307
- 'openssh_': 'ssh',
308
- 'ssh': 'ssh',
309
-
309
+ "openssh": "ssh",
310
+ "openssh_": "ssh",
311
+ "ssh": "ssh",
310
312
  # PHP
311
- 'php/': 'php',
312
- 'php-fpm': 'php',
313
-
313
+ "php/": "php",
314
+ "php-fpm": "php",
314
315
  # MySQL
315
- 'mysql': 'mysql',
316
- 'mariadb': 'mysql',
317
-
316
+ "mysql": "mysql",
317
+ "mariadb": "mysql",
318
318
  # PostgreSQL
319
- 'postgresql': 'postgres',
320
- 'postgres': 'postgres',
321
-
319
+ "postgresql": "postgres",
320
+ "postgres": "postgres",
322
321
  # vsftpd
323
- 'vsftpd': 'vsftpd',
324
- 'vsftp': 'vsftpd',
325
-
322
+ "vsftpd": "vsftpd",
323
+ "vsftp": "vsftpd",
326
324
  # ProFTPD
327
- 'proftpd': 'proftpd',
328
-
325
+ "proftpd": "proftpd",
329
326
  # Samba
330
- 'samba': 'samba',
331
- 'smbd': 'samba',
332
-
327
+ "samba": "samba",
328
+ "smbd": "samba",
333
329
  # Tomcat
334
- 'apache tomcat': 'tomcat',
335
- 'tomcat': 'tomcat',
336
- 'coyote': 'tomcat',
337
-
330
+ "apache tomcat": "tomcat",
331
+ "tomcat": "tomcat",
332
+ "coyote": "tomcat",
338
333
  # WordPress
339
- 'wordpress': 'wordpress',
340
- 'wp': 'wordpress',
341
-
334
+ "wordpress": "wordpress",
335
+ "wp": "wordpress",
342
336
  # Drupal
343
- 'drupal': 'drupal',
344
-
337
+ "drupal": "drupal",
345
338
  # IIS
346
- 'microsoft-iis': 'iis',
347
- 'iis': 'iis',
348
-
339
+ "microsoft-iis": "iis",
340
+ "iis": "iis",
349
341
  # Node.js/Express
350
- 'node': 'nodejs',
351
- 'nodejs': 'nodejs',
352
- 'express': 'express',
353
-
342
+ "node": "nodejs",
343
+ "nodejs": "nodejs",
344
+ "express": "express",
354
345
  # Redis
355
- 'redis': 'redis',
356
-
346
+ "redis": "redis",
357
347
  # MongoDB
358
- 'mongodb': 'mongodb',
359
- 'mongo': 'mongodb',
360
-
348
+ "mongodb": "mongodb",
349
+ "mongo": "mongodb",
361
350
  # Elasticsearch
362
- 'elasticsearch': 'elasticsearch',
363
- 'elastic': 'elasticsearch',
351
+ "elasticsearch": "elasticsearch",
352
+ "elastic": "elasticsearch",
364
353
  }
365
354
 
366
355
 
@@ -374,7 +363,7 @@ def normalize_product_name(product: str) -> str:
374
363
  normalize_product_name('OpenSSH') -> 'ssh'
375
364
  """
376
365
  if not product:
377
- return ''
366
+ return ""
378
367
 
379
368
  product_lower = product.lower().strip()
380
369
 
@@ -388,14 +377,10 @@ def normalize_product_name(product: str) -> str:
388
377
  return normalized
389
378
 
390
379
  # Return lowercase if no alias found
391
- return product_lower.split('/')[0].split(' ')[0]
380
+ return product_lower.split("/")[0].split(" ")[0]
392
381
 
393
382
 
394
- def check_version_condition(
395
- product: str,
396
- version: str,
397
- condition_spec: str
398
- ) -> bool:
383
+ def check_version_condition(product: str, version: str, condition_spec: str) -> bool:
399
384
  """
400
385
  Main entry point: check if a product/version matches a condition spec.
401
386