langchain-ai/langchain · error · SSRFBlockedError

blocked CIDR

Error message

blocked CIDR

What it means

`"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).

Source

Thrown at libs/core/langchain_core/_security/_policy.py:212

def validate_resolved_ip(ip_str: str, policy: SSRFPolicy) -> None:
    """Validate a resolved IP address against the SSRF policy.

    Raises SSRFBlockedError if the IP is blocked.
    """
    try:
        addr = ipaddress.ip_address(ip_str)
    except ValueError as exc:
        msg = "invalid IP address"
        raise SSRFBlockedError(msg) from exc

    if isinstance(addr, ipaddress.IPv6Address):
        inner = _extract_embedded_ipv4(addr)
        if inner is not None:
            addr = inner

    reason = _ip_in_blocked_networks(addr, policy)
    if reason is not None:
        raise SSRFBlockedError(reason)


def validate_hostname(hostname: str, policy: SSRFPolicy) -> None:
    """Validate a hostname against the SSRF policy.

    Raises SSRFBlockedError if the hostname is blocked.
    """
    lower = hostname.lower()

    if policy.block_localhost and lower in _LOCALHOST_NAMES:
        msg = "localhost address"
        raise SSRFBlockedError(msg)

    if policy.block_cloud_metadata and lower in _CLOUD_METADATA_HOSTNAMES:
        msg = "cloud metadata endpoint"
        raise SSRFBlockedError(msg)

    if policy.block_k8s_internal and lower.endswith(_K8S_SUFFIX):

View on GitHub (pinned to e32fa9a52e)

Solutions

  1. 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.
  2. If the block is correct, switch the tool to an allowed mirror/CDN hostname or route via an approved proxy.
  3. 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.

Example fix

# before
policy = SSRFPolicy(blocked_cidrs=[ipaddress.ip_network('203.0.113.0/24')])
await validate_url('http://203.0.113.5/docs', policy)  # blocked CIDR

# after
policy = SSRFPolicy(blocked_cidrs=[ipaddress.ip_network('203.0.113.0/25')])
await validate_url('http://203.0.113.5/docs', policy)  # outside /25
Defensive patterns

Strategy: try-catch

Validate before calling

import ipaddress

def in_blocked_cidr(host: str, cidrs: list[str]) -> bool:
    try:
        ip = ipaddress.ip_address(host)
    except ValueError:
        return False
    return any(ip in ipaddress.ip_network(c) for c in cidrs)

Try / catch

from langchain_core._security._policy import SSRFBlockedError

try:
    await validate_url(url, policy)
except SSRFBlockedError as e:
    if "blocked CIDR" in str(e):
        raise PermanentlyBlockedURL(url) from e  # do not retry; policy is deterministic
    raise

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of langchain-ai/langchain@e32fa9a52e (2026-08-14). Data as JSON: /api/errors/ce34e10366e35fcf. Report an issue: GitHub.