(
scanner: str,
host: str,
severity: VulnSeverity,
title: str,
description: str,
evidence: str = "",
remediation: str = "",
port: Optional[int] = None,
matched_at: str = "",
)
| 617 | |
| 618 | def _is_ip(host: str) -> bool: |
| 619 | """True if `host` is a literal IP (so TLS SNI must be omitted for it).""" |
| 620 | try: |
| 621 | ipaddress.ip_address(host) |
| 622 | return True |
| 623 | except ValueError: |
| 624 | return False |
| 625 | |
| 626 | |
| 627 | def _split_host_port(target: str, default_port: int) -> tuple[str, int]: |
| 628 | if "://" in target: |
| 629 | parsed = urllib.parse.urlparse(target) |
| 630 | host = parsed.hostname or target |
| 631 | port = parsed.port or (443 if parsed.scheme == "https" else 80 if parsed.scheme == "http" else default_port) |
| 632 | return host, port |
| 633 | if ":" in target and target.count(":") == 1: |
| 634 | host, port_str = target.split(":", 1) |
| 635 | try: |
| 636 | return host, int(port_str) |
| 637 | except ValueError: |
| 638 | pass |
| 639 | return target, default_port |
| 640 | |
| 641 | |
| 642 | def _normalize_base_url(target: str) -> str: |
| 643 | if "://" in target: |
| 644 | parsed = urllib.parse.urlparse(target) |
no test coverage detected