{"record":{"id":"0245d0ea2f161143","repo":"sgl-project/sglang","slug":"invalid-allowed-media-domain-domain-r-ports-are","errorCode":null,"errorMessage":"Invalid allowed media domain {domain!r}: ports are not supported","messagePattern":"Invalid allowed media domain (.+?): ports are not supported","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/sglang/srt/utils/common.py","lineNumber":1539,"sourceCode":"    if not isinstance(domain, str):\n        raise ValueError(\"allowed media domains must be strings\")\n\n    domain = domain.strip().rstrip(\".\")\n    if not domain:\n        raise ValueError(\"allowed media domains cannot be empty\")\n    if \"://\" in domain or any(char in domain for char in \"/?#@\"):\n        raise ValueError(\n            f\"Invalid allowed media domain {domain!r}: provide a hostname only\"\n        )\n\n    # Brackets are URL syntax, not part of an IPv6 hostname.\n    if domain.startswith(\"[\") and domain.endswith(\"]\"):\n        domain = domain[1:-1]\n    try:\n        return str(ipaddress.ip_address(domain))\n    except ValueError:\n        if \":\" in domain:\n            raise ValueError(\n                f\"Invalid allowed media domain {domain!r}: ports are not supported\"\n            )\n\n    try:\n        normalized = domain.encode(\"idna\").decode(\"ascii\").lower()\n    except UnicodeError as e:\n        raise ValueError(f\"Invalid allowed media domain {domain!r}\") from e\n    if not normalized:\n        raise ValueError(\"allowed media domains cannot be empty\")\n    return normalized\n\n\ndef configure_media_url_security(\n    allowed_media_domains: Optional[Sequence[str]] = None,\n    max_file_size_mb: int = _DEFAULT_MEDIA_URL_MAX_FILE_SIZE_MB,\n) -> list[str]:\n    \"\"\"Configure process-wide safeguards for client-supplied media URLs.\n","sourceCodeStart":1521,"sourceCodeEnd":1557,"githubUrl":"https://github.com/sgl-project/sglang/blob/0132848349585cfe6aae51c4941cbae872505f8a/python/sglang/srt/utils/common.py#L1521-L1557","documentation":"An allowed-media-domains entry contains a colon after failing to parse as an IP address. Colons only legitimately appear in IPv6 literals (handled by ipaddress.ip_address) or as port separators; since the entry is not a valid IP, the colon must be a port, which the allowlist does not support (port-specific rules would be ambiguous with port-less fetches).","triggerScenarios":"Passing 'example.com:8080' or 'https?blocked-host:443' style entries to configure_media_url_security; note IPv6 with brackets was already unwrapped, so '[::1]' succeeds, but '::1:80' fails here.","commonSituations":"Users include ports from an internal artifact-server URL (e.g. 'internal-artifacts.mycompany.com:9000') in the allowlist.","solutions":["Drop the port: allow 'internal-artifacts.mycompany.com' (all ports on that host are then allowed)","If port restriction is a hard requirement, enforce it with a network-level proxy/firewall since the allowlist is host-only","Document the hostname-only format for operators"],"exampleFix":"# before\nconfigure_media_url_security(allowed_media_domains=['minio.internal:9000'])\n# after\nconfigure_media_url_security(allowed_media_domains=['minio.internal'])","handlingStrategy":"validation","validationCode":"import ipaddress\nfor d in domains:\n    if ':' in d:\n        try: ipaddress.ip_address(d.strip('[]'))\n        except ValueError: raise ConfigError(f'{d!r}: ports not supported; host only')","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Remember the allowlist is host-scoped; enforce port rules at the network layer","Strip ':port' suffixes when importing existing URL allowlists"],"tags":["validation","media","security","ssrf"],"backgroundTag":"config-validation-failed","analyzedSha":"0132848349585cfe6aae51c4941cbae872505f8a","analyzedAt":"2026-08-28T05:10:05.995Z","schemaVersion":2},"datasetVersion":"2026-08-28T06:17:29.519Z"}