{"record":{"id":"a7198766c3a795ef","repo":"langchain-ai/langchain","slug":"missing-hostname","errorCode":null,"errorMessage":"missing hostname","messagePattern":"missing hostname","errorType":"exception","errorClass":"SSRFBlockedError","httpStatus":null,"severity":"error","filePath":"libs/core/langchain_core/_security/_policy.py","lineNumber":297,"sourceCode":"    \"\"\"Synchronous URL validation (no DNS resolution).\n\n    Suitable for Pydantic validators and other sync contexts. Checks scheme\n    and hostname patterns only - use `validate_url` for full DNS-aware checking.\n\n    Raises:\n        SSRFBlockedError: If the URL violates the policy.\n    \"\"\"\n    parsed = urllib.parse.urlparse(url)\n\n    scheme = (parsed.scheme or \"\").lower()\n    if scheme not in policy.allowed_schemes:\n        msg = f\"scheme '{scheme}' not allowed\"\n        raise SSRFBlockedError(msg)\n\n    hostname = parsed.hostname\n    if not hostname:\n        msg = \"missing hostname\"\n        raise SSRFBlockedError(msg)\n\n    allowed = _effective_allowed_hosts(policy)\n    if hostname.lower() in {h.lower() for h in allowed}:\n        return\n\n    try:\n        ipaddress.ip_address(hostname)\n        validate_resolved_ip(hostname, policy)\n    except SSRFBlockedError:\n        raise\n    except ValueError:\n        pass\n    else:\n        return\n\n    validate_hostname(hostname, policy)\n","sourceCodeStart":279,"sourceCodeEnd":314,"githubUrl":"https://github.com/langchain-ai/langchain/blob/e32fa9a52eab3b61ad7a45399bfde59b3e580fc4/libs/core/langchain_core/_security/_policy.py#L279-L314","documentation":"Raised by `validate_url_sync` when `urllib.parse.urlparse(url).hostname` is empty — the URL parses but has no host component, so hostname-level policy checks cannot run and the guard fails closed. Typical shapes are scheme-only URLs, opaque URIs, or relative paths where the authority component (`//host`) is absent.","triggerScenarios":"`validate_url_sync('mailto:user@x.com')`, `validate_url_sync('/relative/path')`, `validate_url_sync('https:///path')` (empty authority), or `validate_url_sync('javascript:alert(1)')` after widening allowed_schemes. Note ordering: the scheme check runs first, so a non-allowed scheme on the same URL raises 'scheme ... not allowed' instead.","commonSituations":"Config/env-var URLs missing the host ('https:///api'), relative endpoint paths concatenated in the wrong order (base omitted), or user input like an email `mailto:` link fed into a URL-fetch validator. Also common in tests using path-only fixtures.","solutions":["Fix the URL construction: ensure base URL is present and joined properly (`urljoin(base, path)`), producing e.g. `https://host/api/thing`.","Reject host-less URLs at input validation (they are not fetchable anyway).","If opaque schemes like mailto: are valid input for your field, validate them with a different rule instead of the SSRF fetch validator."],"exampleFix":"# before\nurl = '/v1/chat'  # base URL lost\nvalidate_url_sync(url, policy)  # missing hostname\n\n# after\nfrom urllib.parse import urljoin\nurl = urljoin('https://api.example.com', '/v1/chat')\nvalidate_url_sync(url, policy)","handlingStrategy":"validation","validationCode":"from urllib.parse import urlparse\n\ndef has_hostname(url: str) -> bool:\n    return bool(urlparse(url).hostname)","typeGuard":null,"tryCatchPattern":"from langchain_core._security._policy import SSRFBlockedError\n\ntry:\n    validate_url_sync(url, policy)\nexcept SSRFBlockedError as e:\n    if str(e) == \"missing hostname\":\n        url = urljoin(settings.base_url, url)  # repair relative path and revalidate\n        validate_url_sync(url, policy)\n    else:\n        raise","preventionTips":["Always build fetch URLs with urljoin(base_url, path) so a host is guaranteed.","Validate URL shape (scheme + host) at input time with a 4xx response for user data.","Treat relative URLs in config as a base-url wiring bug, not an SSRF event."],"tags":["ssrf","url-validation","misconfiguration"],"backgroundTag":null,"analyzedSha":"e32fa9a52eab3b61ad7a45399bfde59b3e580fc4","analyzedAt":"2026-08-14T18:42:09.092Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}