souleyez 2.43.29__py3-none-any.whl → 3.0.0__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 +9564 -2881
  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 +564 -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 +409 -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 +417 -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 +913 -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 +219 -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 +237 -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 +23034 -10679
  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-3.0.0.dist-info}/METADATA +2 -2
  353. souleyez-3.0.0.dist-info/RECORD +443 -0
  354. {souleyez-2.43.29.dist-info → souleyez-3.0.0.dist-info}/WHEEL +1 -1
  355. souleyez-2.43.29.dist-info/RECORD +0 -379
  356. {souleyez-2.43.29.dist-info → souleyez-3.0.0.dist-info}/entry_points.txt +0 -0
  357. {souleyez-2.43.29.dist-info → souleyez-3.0.0.dist-info}/licenses/LICENSE +0 -0
  358. {souleyez-2.43.29.dist-info → souleyez-3.0.0.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