{"record":{"id":"b4535d50a6e7a643","repo":"langchain-ai/langchain","slug":"invalid-ip-address","errorCode":null,"errorMessage":"invalid IP address","messagePattern":"invalid IP address","errorType":"exception","errorClass":"SSRFBlockedError","httpStatus":null,"severity":"error","filePath":"libs/core/langchain_core/_security/_policy.py","lineNumber":203,"sourceCode":"\n    return None\n\n\n# ---------------------------------------------------------------------------\n# Public validation functions\n# ---------------------------------------------------------------------------\n\n\ndef 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","sourceCodeStart":185,"sourceCodeEnd":221,"githubUrl":"https://github.com/langchain-ai/langchain/blob/e32fa9a52eab3b61ad7a45399bfde59b3e580fc4/libs/core/langchain_core/_security/_policy.py#L185-L221","documentation":"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.","triggerScenarios":"`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.","commonSituations":"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.","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."],"exampleFix":"# before\nvalidate_resolved_ip(request.host, policy)  # host is 'example.com'\n\n# after\ninfos = socket.getaddrinfo(request.host, 443, type=socket.SOCK_STREAM)\nfor info in infos:\n    validate_resolved_ip(info[4][0], policy)","handlingStrategy":"validation","validationCode":"import ipaddress\n\ndef is_valid_ip(value: str) -> bool:\n    try:\n        ipaddress.ip_address(value)\n        return True\n    except ValueError:\n        return False\n\nassert is_valid_ip(\"127.0.0.1\") and not is_valid_ip(\"example.com\")","typeGuard":"import ipaddress\n\ndef is_ip_literal(value: str) -> bool:\n    \"\"\"True only for strings ipaddress can parse (v4 or v6, no zone index).\"\"\"\n    try:\n        ipaddress.ip_address(value)\n        return True\n    except ValueError:\n        return False","tryCatchPattern":"from langchain_core._security._policy import SSRFBlockedError\n\ntry:\n    validate_resolved_ip(ip_str, policy)\nexcept SSRFBlockedError as e:\n    if str(e) == \"invalid IP address\":\n        log.error(\"caller passed a non-IP %r to validate_resolved_ip\", ip_str)\n    raise","preventionTips":["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."],"tags":["ssrf","security","network","validation"],"backgroundTag":null,"analyzedSha":"e32fa9a52eab3b61ad7a45399bfde59b3e580fc4","analyzedAt":"2026-08-14T18:42:09.092Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}