{"record":{"id":"07c1781fb119c173","repo":"sgl-project/sglang","slug":"media-url-domain-is-not-allowed-allowed-domains","errorCode":null,"errorMessage":"Media URL domain is not allowed. Allowed domains: {sorted(_allowed_media_domains)}; input domain: {hostname}","messagePattern":"Media URL domain is not allowed\\. Allowed domains: (.+?); input domain: (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/sglang/srt/utils/common.py","lineNumber":1582,"sourceCode":"        raise ValueError(\"media_url_max_file_size_mb must be non-negative\")\n\n    normalized_domains = sorted(\n        {_normalize_media_domain(domain) for domain in allowed_media_domains or []}\n    )\n    global _allowed_media_domains, _media_url_max_file_size_bytes\n    _allowed_media_domains = frozenset(normalized_domains)\n    _media_url_max_file_size_bytes = max_file_size_mb * 1024 * 1024\n    return normalized_domains\n\n\ndef _assert_media_url_allowed(url: str) -> None:\n    parsed = urlparse(url)\n    if parsed.scheme not in {\"http\", \"https\"} or parsed.hostname is None:\n        raise ValueError(f\"Invalid media URL: {url!r}\")\n\n    hostname = _normalize_media_domain(parsed.hostname)\n    if _allowed_media_domains and hostname not in _allowed_media_domains:\n        raise ValueError(\n            \"Media URL domain is not allowed. \"\n            f\"Allowed domains: {sorted(_allowed_media_domains)}; \"\n            f\"input domain: {hostname}\"\n        )\n\n\ndef download_remote_media(url: str, timeout: float) -> bytes:\n    \"\"\"Download one HTTP(S) media object under the configured URL policy.\n\n    Redirects are followed manually so every destination is validated before\n    a connection is made. The response is streamed to enforce both the total\n    request deadline and the configured byte limit without first buffering an\n    attacker-controlled body in memory.\n    \"\"\"\n\n    if timeout <= 0:\n        raise ValueError(\"media URL timeout must be positive\")\n","sourceCodeStart":1564,"sourceCodeEnd":1600,"githubUrl":"https://github.com/sgl-project/sglang/blob/0132848349585cfe6aae51c4941cbae872505f8a/python/sglang/srt/utils/common.py#L1564-L1600","documentation":"The media URL's scheme is valid http(s) but the (IDNA-normalized) hostname is not in the configured allowed-media-domains allowlist. SGLang enforces an egress allowlist on all remote media fetches to block SSRF; if the allowlist is non-empty, only listed exact hostnames may be fetched.","triggerScenarios":"Server started with --allowed-media-domains huggingface.co but a request references https://cdn.other-host.com/img.png; hostname comparison is exact after normalization (no automatic subdomain matching).","commonSituations":"Model card / dataset referencing a CDN not in the allowlist; forgetting that 'example.com' does not cover 'www.example.com'; redirect chains that land on unlisted hosts (redirect targets are re-checked).","solutions":["Add the exact hostname (e.g. 'cdn.other-host.com') to --allowed-media-domains and restart","Use the same hostname your payloads actually reference (check www vs apex)","Leave the allowlist empty to disable the restriction only if your threat model permits"],"exampleFix":"# before\npython -m sglang.launch_server --allowed-media-domains huggingface.co  # request uses cdn-lfs.huggingface.co -> fails\n# after\npython -m sglang.launch_server --allowed-media-domains huggingface.co,cdn-lfs.huggingface.co","handlingStrategy":"validation","validationCode":"from urllib.parse import urlparse\nhost = urlparse(url).hostname or ''\nif host.strip('.').lower() not in configured_allowlist:\n    return error_response(f'media host {host} not allowed')","typeGuard":null,"tryCatchPattern":"try:\n    data = download_remote_media(url, timeout=30)\nexcept ValueError as e:\n    if 'not allowed' in str(e):\n        return HTTPException(403, str(e))\n    raise","preventionTips":["List every hostname (including www and CDN variants) your payloads reference","Remember redirects are re-checked; allowlist redirect targets too","Matching is exact-host, not subdomain-wildcard"],"tags":["media","security","ssrf","allowlist","network"],"backgroundTag":"domain-not-allowlisted","analyzedSha":"0132848349585cfe6aae51c4941cbae872505f8a","analyzedAt":"2026-08-28T05:10:05.995Z","schemaVersion":2},"datasetVersion":"2026-08-28T06:17:29.519Z"}