{"record":{"id":"22131a5707aadfbb","repo":"langchain-ai/langchain","slug":"dns-resolution-failed-22131a","errorCode":null,"errorMessage":"DNS resolution failed","messagePattern":"DNS resolution failed","errorType":"exception","errorClass":"SSRFBlockedError","httpStatus":null,"severity":"error","filePath":"libs/core/langchain_core/_security/_transport.py","lineNumber":84,"sourceCode":"        validate_url_sync(str(request.url), self._policy)\n\n        # Allowed-hosts bypass - skip DNS/IP validation entirely.\n        allowed = {h.lower() for h in _effective_allowed_hosts(self._policy)}\n        if hostname.lower() in allowed:\n            return await self._inner.handle_async_request(request)\n\n        # 4. DNS resolution\n        port = request.url.port or (443 if scheme == \"https\" else 80)\n        try:\n            addrinfo = await asyncio.to_thread(\n                socket.getaddrinfo,\n                hostname,\n                port,\n                type=socket.SOCK_STREAM,\n            )\n        except socket.gaierror as exc:\n            msg = \"DNS resolution failed\"\n            raise SSRFBlockedError(msg) from exc\n\n        if not addrinfo:\n            msg = \"DNS resolution returned no results\"\n            raise SSRFBlockedError(msg)\n\n        # 5. Validate ALL resolved IPs - any blocked means reject.\n        for _family, _type, _proto, _canonname, sockaddr in addrinfo:\n            ip_str: str = sockaddr[0]  # type: ignore[assignment]\n            validate_resolved_ip(ip_str, self._policy)\n\n        # 6. Pin to first resolved IP.\n        pinned_ip = addrinfo[0][4][0]\n\n        # 7. Rewrite URL to use pinned IP, preserving Host header and SNI.\n        pinned_url = request.url.copy_with(host=pinned_ip)\n\n        # Build extensions dict, adding sni_hostname for HTTPS so TLS\n        # certificate validation uses the original hostname.","sourceCodeStart":66,"sourceCodeEnd":102,"githubUrl":"https://github.com/langchain-ai/langchain/blob/e32fa9a52eab3b61ad7a45399bfde59b3e580fc4/libs/core/langchain_core/_security/_transport.py#L66-L102","documentation":"The async SSRF-guard httpx transport (`libs/core/langchain_core/_security/_transport.py`, `handle_async_request`) resolves the request hostname via `socket.getaddrinfo` before connecting; a `socket.gaierror` becomes `SSRFBlockedError('DNS resolution failed')`. DNS failure is treated as a block so the request never proceeds with an unvalidated destination.","triggerScenarios":"Issuing a request through an httpx client configured with the SSRF-guard async transport where the URL hostname does not resolve (NXDOMAIN, SERVFAIL, no resolver). Affects GETs to mistyped domains or hostnames only resolvable inside another network.","commonSituations":"Offline CI; containers with broken DNS; internal hostnames in one environment used in another; testing SSRF protection itself with dead hostnames.","solutions":["Confirm the hostname resolves from the same runtime: `python -c \"import socket; socket.getaddrinfo('host', 443)\"`","Fix or fully qualify the target hostname / use an IP literal if policy allows","Repair container DNS configuration (resolv.conf, k8s CoreDNS, docker --dns)","If the host is a trusted internal allow-listed name, add it to the transport's allowed-hostnames set so it bypasses resolution-based checks"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"import socket\n\ndef resolves(host: str, port: int) -> bool:\n    try:\n        return bool(socket.getaddrinfo(host, port, type=socket.SOCK_STREAM))\n    except socket.gaierror:\n        return False","typeGuard":null,"tryCatchPattern":"try:\n    resp = await client.get(url)\nexcept SSRFBlockedError as e:\n    if 'DNS resolution failed' in str(e):\n        logger.warning('unresolvable target %s', url)\n        return None\n    raise","preventionTips":["Validate external hostnames at configuration load time","Keep an allow-list for trusted internal hosts so they bypass DNS validation","In tests, monkeypatch getaddrinfo with realistic addrinfo tuples"],"tags":["ssrf","httpx","dns","network","async"],"backgroundTag":null,"analyzedSha":"e32fa9a52eab3b61ad7a45399bfde59b3e580fc4","analyzedAt":"2026-08-14T18:42:09.092Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}