langchain-ai/langchain · error · SSRFBlockedError
invalid IP address
Error message
invalid IP address
What it means
Raised by `validate_resolved_ip` in langchain_core's SSRF policy engine when the string handed to it cannot be parsed by `ipaddress.ip_address()`. This is a defensive guard: DNS-resolved addresses normally parse, so an unparseable value means the caller fed it a hostname, a malformed IP, or garbage. It is wrapped in `SSRFBlockedError` (fail-closed) rather than passed through as ValueError.
Source
Thrown at libs/core/langchain_core/_security/_policy.py:203
return None
# ---------------------------------------------------------------------------
# Public validation functions
# ---------------------------------------------------------------------------
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()
View on GitHub (pinned to e32fa9a52e)
Solutions
- Resolve the hostname first (e.g. `socket.getaddrinfo`) and pass `sockaddr[0]` — the parsed IP string — to `validate_resolved_ip`.
- Sanitize/normalize the IP string before validation (strip zone index, brackets from `[::1]`, port suffixes).
- In tests, use real IP literals (`127.0.0.1`, `::1`) rather than placeholder strings in fake addrinfo.
Example fix
# before
validate_resolved_ip(request.host, policy) # host is 'example.com'
# after
infos = socket.getaddrinfo(request.host, 443, type=socket.SOCK_STREAM)
for info in infos:
validate_resolved_ip(info[4][0], policy) Defensive patterns
Strategy: validation
Validate before calling
import ipaddress
def is_valid_ip(value: str) -> bool:
try:
ipaddress.ip_address(value)
return True
except ValueError:
return False
assert is_valid_ip("127.0.0.1") and not is_valid_ip("example.com") Type guard
import ipaddress
def is_ip_literal(value: str) -> bool:
"""True only for strings ipaddress can parse (v4 or v6, no zone index)."""
try:
ipaddress.ip_address(value)
return True
except ValueError:
return False Try / catch
from langchain_core._security._policy import SSRFBlockedError
try:
validate_resolved_ip(ip_str, policy)
except SSRFBlockedError as e:
if str(e) == "invalid IP address":
log.error("caller passed a non-IP %r to validate_resolved_ip", ip_str)
raise Prevention
- Always resolve hostnames via getaddrinfo and pass sockaddr[0]; never pass user input straight to IP validators.
- Strip IPv6 zone indices and bracket/port artifacts before validating.
- Use real IP literals in test fixtures, not placeholder strings.
When it happens
Trigger: `validate_resolved_ip('not-an-ip', policy)`, `validate_resolved_ip('192.168.1', policy)` (truncated IPv4), or passing a hostname like `'example.com'` directly instead of a resolved address. Also reachable via `validate_url` if a hostname that is neither in allowed_hosts nor DNS-resolvable reaches the IP check path, or via `validate_url_sync` which calls `validate_resolved_ip(hostname, policy)` after a successful `ipaddress.ip_address(hostname)` — where exotic IPv6 forms can slip through urlparse and fail here.
Common situations: Custom integrations calling the SSRF validators with raw user input instead of socket-resolved addresses; unit tests that synthesize fake addrinfo tuples with placeholder strings; or IPv6 literals with zone indices (`fe80::1%eth0`) that `ip_address` rejects on some Python versions.
Related errors
AI-assisted analysis of langchain-ai/langchain@e32fa9a52e (2026-08-14).
Data as JSON: /api/errors/b4535d50a6e7a643.
Report an issue: GitHub.