{"record":{"id":"027980dde19263b9","repo":"langchain-ai/langchain","slug":"scheme-scheme-not-allowed","errorCode":null,"errorMessage":"scheme '{scheme}' not allowed","messagePattern":"scheme '(.+?)' not allowed","errorType":"exception","errorClass":"SSRFBlockedError","httpStatus":null,"severity":"error","filePath":"libs/core/langchain_core/_security/_policy.py","lineNumber":292,"sourceCode":"    for _family, _type, _proto, _canonname, sockaddr in addrinfo:\n        validate_resolved_ip(str(sockaddr[0]), policy)\n\n\ndef validate_url_sync(url: str, policy: SSRFPolicy = DEFAULT_SSRF_POLICY) -> None:\n    \"\"\"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:","sourceCodeStart":274,"sourceCodeEnd":310,"githubUrl":"https://github.com/langchain-ai/langchain/blob/e32fa9a52eab3b61ad7a45399bfde59b3e580fc4/libs/core/langchain_core/_security/_policy.py#L274-L310","documentation":"Raised by `validate_url_sync` (and the shared scheme check) when the URL's scheme, lowercased, is not in `policy.allowed_schemes` — the default allows only http/https. This is the first guard in the chain: schemes like `file://`, `ftp://`, `gopher://`, or javascript/data URIs are rejected before hostname or DNS checks run, since non-HTTP fetchers routinely bypass IP-level protections.","triggerScenarios":"`validate_url_sync('file:///etc/passwd')`, `validate_url_sync('ftp://host/file')`, or an empty/relative URL like `'/api/thing'` where `parsed.scheme` is `''` (empty scheme fails the membership test and renders as \"scheme '' not allowed\"). Also triggered when a custom policy restricts to `frozenset({'https'})` and an http:// URL is passed.","commonSituations":"User- or model-supplied URLs in fetch tools that smuggle `file://` reads (the exact attack the guard exists for); misconfigured base URLs missing the scheme; and legitimate-but-blocked schemes when someone points a loader at an internal `ftp://` or custom-scheme endpoint.","solutions":["Normalize URLs to include an allowed scheme (`https://`) — check for a missing scheme prefix when the error shows `scheme ''`.","If a non-default scheme is genuinely required, construct the policy with `allowed_schemes=frozenset({'https', 'ftp'})` — but only for trusted internal use.","Reject/repair at input time: validate user URLs before they reach the fetch layer."],"exampleFix":"# before\nvalidate_url_sync('example.com/api', policy)  # scheme '' not allowed\n\n# after\nfrom urllib.parse import urlunparse\nurl = url if '://' in url else f'https://{url}'\nvalidate_url_sync(url, policy)","handlingStrategy":"validation","validationCode":"from urllib.parse import urlparse\n\ndef has_allowed_scheme(url: str, allowed={\"http\", \"https\"}) -> bool:\n    return (urlparse(url).scheme or \"\").lower() in allowed\n\ndef normalize_url(url: str) -> str:\n    return url if \"://\" in url else f\"https://{url}\"","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).startswith(\"scheme\"):\n        raise InvalidUserInput(url) from e  # input problem, not policy — no retry\n    raise","preventionTips":["Normalize user-supplied URLs (default scheme, strip whitespace) before validation.","Validate scheme at the API boundary so bad URLs are rejected with a 4xx, not a fetch-time error.","Never widen allowed_schemes for untrusted input; file:// and ftp:// are blocked for good reason."],"tags":["ssrf","security","url-validation","scheme"],"backgroundTag":null,"analyzedSha":"e32fa9a52eab3b61ad7a45399bfde59b3e580fc4","analyzedAt":"2026-08-14T18:42:09.092Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}