{"record":{"id":"ce34e10366e35fcf","repo":"langchain-ai/langchain","slug":"blocked-cidr","errorCode":null,"errorMessage":"blocked CIDR","messagePattern":"blocked CIDR","errorType":"exception","errorClass":"SSRFBlockedError","httpStatus":null,"severity":"error","filePath":"libs/core/langchain_core/_security/_policy.py","lineNumber":212,"sourceCode":"def validate_resolved_ip(ip_str: str, policy: SSRFPolicy) -> None:\n    \"\"\"Validate a resolved IP address against the SSRF policy.\n\n    Raises SSRFBlockedError if the IP is blocked.\n    \"\"\"\n    try:\n        addr = ipaddress.ip_address(ip_str)\n    except ValueError as exc:\n        msg = \"invalid IP address\"\n        raise SSRFBlockedError(msg) from exc\n\n    if isinstance(addr, ipaddress.IPv6Address):\n        inner = _extract_embedded_ipv4(addr)\n        if inner is not None:\n            addr = inner\n\n    reason = _ip_in_blocked_networks(addr, policy)\n    if reason is not None:\n        raise SSRFBlockedError(reason)\n\n\ndef validate_hostname(hostname: str, policy: SSRFPolicy) -> None:\n    \"\"\"Validate a hostname against the SSRF policy.\n\n    Raises SSRFBlockedError if the hostname is blocked.\n    \"\"\"\n    lower = hostname.lower()\n\n    if policy.block_localhost and lower in _LOCALHOST_NAMES:\n        msg = \"localhost address\"\n        raise SSRFBlockedError(msg)\n\n    if policy.block_cloud_metadata and lower in _CLOUD_METADATA_HOSTNAMES:\n        msg = \"cloud metadata endpoint\"\n        raise SSRFBlockedError(msg)\n\n    if policy.block_k8s_internal and lower.endswith(_K8S_SUFFIX):","sourceCodeStart":194,"sourceCodeEnd":230,"githubUrl":"https://github.com/langchain-ai/langchain/blob/e32fa9a52eab3b61ad7a45399bfde59b3e580fc4/libs/core/langchain_core/_security/_policy.py#L194-L230","documentation":"`\"blocked CIDR\"` is the reason emitted by `_ip_in_blocked_networks` when the resolved IP matches a network explicitly listed in the policy's `blocked_cidrs` (as opposed to the built-in private/localhost/metadata categories). It propagates as `SSRFBlockedError` from the same `raise SSRFBlockedError(reason)` line in `validate_resolved_ip`, reached both from `validate_url` (per resolved addrinfo entry) and `validate_url_sync` (for IP-literal hostnames).","triggerScenarios":"A policy configured like `SSRFPolicy(blocked_cidrs=[ipaddress.ip_network('203.0.113.0/24')])` and a URL whose host resolves into 203.0.113.0/24; or using a shipped policy preset that blocklists a specific corporate/external range and the fetched URL lands in it.","commonSituations":"Org-level deployments where a security team blocklists specific egress ranges; after a policy file is tightened, previously working document-loader/tool URLs (web research tools, URL fetch utilities) suddenly fail with a bare 'blocked CIDR' message; or DNS rebinding changes a hostname's resolution into a blocked range overnight.","solutions":["Check the policy's `blocked_cidrs` and confirm the target IP genuinely should be allowed; if so, remove/adjust that network in the policy you construct.","If the block is correct, switch the tool to an allowed mirror/CDN hostname or route via an approved proxy.","Re-resolve the hostname — a stale DNS entry or rebinding may put it in the blocked range; pin the hostname to `allowed_hosts` only if it is trusted."],"exampleFix":"# before\npolicy = SSRFPolicy(blocked_cidrs=[ipaddress.ip_network('203.0.113.0/24')])\nawait validate_url('http://203.0.113.5/docs', policy)  # blocked CIDR\n\n# after\npolicy = SSRFPolicy(blocked_cidrs=[ipaddress.ip_network('203.0.113.0/25')])\nawait validate_url('http://203.0.113.5/docs', policy)  # outside /25","handlingStrategy":"try-catch","validationCode":"import ipaddress\n\ndef in_blocked_cidr(host: str, cidrs: list[str]) -> bool:\n    try:\n        ip = ipaddress.ip_address(host)\n    except ValueError:\n        return False\n    return any(ip in ipaddress.ip_network(c) for c in cidrs)","typeGuard":null,"tryCatchPattern":"from langchain_core._security._policy import SSRFBlockedError\n\ntry:\n    await validate_url(url, policy)\nexcept SSRFBlockedError as e:\n    if \"blocked CIDR\" in str(e):\n        raise PermanentlyBlockedURL(url) from e  # do not retry; policy is deterministic\n    raise","preventionTips":["Keep the blocked_cidrs list in version control with an owner; surface it in error dashboards when fetches fail.","Treat CIDR blocks as permanent (no retry) — only DNS-transient failures are worth retrying.","Log the resolved IP alongside the block reason so on-call can distinguish policy hits from DNS rebinding."],"tags":["ssrf","security","network","cidr"],"backgroundTag":null,"analyzedSha":"e32fa9a52eab3b61ad7a45399bfde59b3e580fc4","analyzedAt":"2026-08-14T18:42:09.092Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}