{"id":"CVE-2026-41488","aliases":["EUVD-2026-25635","GHSA-r7w7-9xr2-qq2r","PYSEC-2026-76"],"status":"published","title":"angchain-openai: Image token counting SSRF protection can be bypassed via DNS rebinding","description":"LangChain is a framework for building agents and LLM-powered applications. Prior to 1.1.14, langchain-openai's _url_to_size() helper (used by get_num_tokens_from_messages for image token counting) validated URLs for SSRF protection and then fetched them in a separate network operation with independent DNS resolution. This left a TOCTOU / DNS rebinding window: an attacker-controlled hostname could resolve to a public IP during validation and then to a private/localhost IP during the actual fetch.","severity":{"version":"3.1","score":3.1,"vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:L/I:N/A:N","level":"low","assessor":"cna","from":"cve"},"epss":{"day":"2026-11-11","score":0.00158,"percentile":0.04996,"model":"v2026.06.15"},"facts":{"in_kev":false,"known_exploited":false,"public_exploit":false,"fix_available":true},"cwes":["CWE-918"],"published":"2026-04-16T23:00:12Z","modified":"2026-10-28T02:30:47Z","fixes":[{"ecosystem":"PyPI","package":"langchain-openai","fixed_in":["1.1.14"],"sources":["ghsa","osv"]}],"affected":[{"source":"ghsa","ecosystem":"PyPI","package":"langchain-openai","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"1.1.14"}]}]},{"source":"osv","ecosystem":"PyPI","package":"langchain-openai","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"1.1.14"}]}],"versions":["0.0.1","0.0.1rc0","0.0.1rc1","0.0.2","0.0.2.post1","0.0.3","0.0.4","0.0.5","0.0.6","0.0.7","0.0.8","0.0.8rc1","0.1.0","0.1.1","0.1.10","0.1.11","0.1.12","0.1.13","0.1.14","0.1.15","0.1.16","0.1.17","0.1.19","0.1.2","0.1.20","0.1.21","0.1.21rc1","0.1.21rc2","0.1.22","0.1.23","0.1.24","0.1.25","0.1.3","0.1.3rc1","0.1.4","0.1.5","0.1.6","0.1.7","0.1.8","0.1.8rc1","0.1.9","0.2.0","0.2.0.dev0","0.2.0.dev1","0.2.0.dev2","0.2.1","0.2.10","0.2.11","0.2.12","0.2.13","0.2.14","0.2.2","0.2.3","0.2.4","0.2.5","0.2.6","0.2.7","0.2.8","0.2.9","0.3.0","0.3.1","0.3.10","0.3.11","0.3.12","0.3.13","0.3.14","0.3.15","0.3.16","0.3.17","0.3.18","0.3.19","0.3.2","0.3.20","0.3.21","0.3.22","0.3.23","0.3.24","0.3.25","0.3.26","0.3.27","0.3.28","0.3.29","0.3.3","0.3.30","0.3.31","0.3.32","0.3.33","0.3.34","0.3.35","0.3.4","0.3.4rc1","0.3.5","0.3.6","0.3.7","0.3.8","0.3.9","0.3.9rc1","0.4.0.dev0","1.0.0","1.0.0a1","1.0.0a2","1.0.0a3","1.0.0a4","1.0.1","1.0.2","1.0.3","1.1.0","1.1.1","1.1.10","1.1.11","1.1.12","1.1.13","1.1.2","1.1.3","1.1.4","1.1.5","1.1.6","1.1.7","1.1.8","1.1.9"]},{"source":"osv","ecosystem":"PyPI","package":"langchain-openai","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"1.1.14"}]}],"versions":["0.0.1","0.0.1rc0","0.0.1rc1","0.0.2","0.0.2.post1","0.0.3","0.0.4","0.0.5","0.0.6","0.0.7","0.0.8","0.0.8rc1","0.1.0","0.1.1","0.1.10","0.1.11","0.1.12","0.1.13","0.1.14","0.1.15","0.1.16","0.1.17","0.1.19","0.1.2","0.1.20","0.1.21","0.1.21rc1","0.1.21rc2","0.1.22","0.1.23","0.1.24","0.1.25","0.1.3","0.1.3rc1","0.1.4","0.1.5","0.1.6","0.1.7","0.1.8","0.1.8rc1","0.1.9","0.2.0","0.2.0.dev0","0.2.0.dev1","0.2.0.dev2","0.2.1","0.2.10","0.2.11","0.2.12","0.2.13","0.2.14","0.2.2","0.2.3","0.2.4","0.2.5","0.2.6","0.2.7","0.2.8","0.2.9","0.3.0","0.3.1","0.3.10","0.3.11","0.3.12","0.3.13","0.3.14","0.3.15","0.3.16","0.3.17","0.3.18","0.3.19","0.3.2","0.3.20","0.3.21","0.3.22","0.3.23","0.3.24","0.3.25","0.3.26","0.3.27","0.3.28","0.3.29","0.3.3","0.3.30","0.3.31","0.3.32","0.3.33","0.3.34","0.3.35","0.3.4","0.3.4rc1","0.3.5","0.3.6","0.3.7","0.3.8","0.3.9","0.3.9rc1","0.4.0.dev0","1.0.0","1.0.0a1","1.0.0a2","1.0.0a3","1.0.0a4","1.0.1","1.0.2","1.0.3","1.1.0","1.1.1","1.1.10","1.1.11","1.1.12","1.1.13","1.1.2","1.1.3","1.1.4","1.1.5","1.1.6","1.1.7","1.1.8","1.1.9"]}],"products":[{"vendor":"langchain","product":"langchain-openai"},{"vendor":"langchain-ai","product":"langchain-openai"}],"references":[{"url":"https://github.com/langchain-ai/langchain/security/advisories/GHSA-r7w7-9xr2-qq2r","tags":["x_refsource_CONFIRM","Mitigation","Vendor Advisory","advisory","web"]},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2026-41488","tags":["advisory"]},{"url":"https://github.com/pypa/advisory-database/tree/main/vulns/langchain-openai/PYSEC-2026-76.yaml","tags":["web"]},{"url":"https://github.com/advisories/GHSA-r7w7-9xr2-qq2r"},{"url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/41xxx/CVE-2026-41488.json","tags":["advisory"]},{"url":"https://github.com/langchain-ai/langchain","tags":["package"]}],"sources":{"cve":[{"id":"CVE-2026-41488","title":"angchain-openai: Image token counting SSRF protection can be bypassed via DNS rebinding","description":"LangChain is a framework for building agents and LLM-powered applications. Prior to 1.1.14, langchain-openai's _url_to_size() helper (used by get_num_tokens_from_messages for image token counting) validated URLs for SSRF protection and then fetched them in a separate network operation with independent DNS resolution. This left a TOCTOU / DNS rebinding window: an attacker-controlled hostname could resolve to a public IP during validation and then to a private/localhost IP during the actual fetch.","status":"published","published":"2026-04-24T20:57:25.658Z","modified":"2026-04-27T13:40:42.065Z","cvss":[{"version":"3.1","score":3.1,"vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:L/I:N/A:N","level":"low","assessor":"cna"}],"cwes":["CWE-918"],"updated_at":"2026-11-02T13:41:08.498858Z"}],"euvd":[{"id":"EUVD-2026-25635","description":"LangChain is a framework for building agents and LLM-powered applications. Prior to 1.1.14, langchain-openai's _url_to_size() helper (used by get_num_tokens_from_messages for image token counting) validated URLs for SSRF protection and then fetched them in a separate network operation with independent DNS resolution. This left a TOCTOU / DNS rebinding window: an attacker-controlled hostname could resolve to a public IP during validation and then to a private/localhost IP during the actual fetch.","status":"published","published":"2026-04-24T20:57:25Z","modified":"2026-04-27T13:40:42Z","cvss":[{"version":"3.1","score":3.1,"vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:L/I:N/A:N","level":"low"}],"updated_at":"2026-11-02T19:24:17.432529Z"}],"ghsa":[{"id":"GHSA-r7w7-9xr2-qq2r","title":"langchain-openai: Image token counting SSRF protection can be bypassed via DNS rebinding","description":"## Summary\n\n`langchain-openai`'s `_url_to_size()` helper (used by `get_num_tokens_from_messages` for image token counting) validated URLs for SSRF protection and then fetched them in a separate network operation with independent DNS resolution. This left a TOCTOU / DNS rebinding window: an attacker-controlled hostname could resolve to a public IP during validation and then to a private/localhost IP during the actual fetch.\n\nThe practical impact is limited because the fetched response body is passed directly to Pillow's `Image.open()` to extract dimensions — the response content is never returned, logged, or otherwise exposed to the caller. An attacker cannot exfiltrate data from internal services through this path. A potential risk is blind probing (inferring whether an internal host/port is open based on timing or error behavior).\n\n## Affected versions\n\n- `langchain-openai` \u003c 1.1.14\n\n## Patched versions\n\n- `langchain-openai` \u003e= 1.1.14 (requires `langchain-core` \u003e= 1.2.31)\n\n## Affected code\n\n**File:** `libs/partners/openai/langchain_openai/chat_models/base.py` — `_url_to_size()`\n\nThe vulnerable pattern was a validate-then-fetch with separate DNS resolution:\n\n```python\nvalidate_safe_url(image_source, allow_private=False, allow_http=True)\n# ... separate network operation with independent DNS resolution ...\nresponse = httpx.get(image_source, timeout=timeout)\n```\n\n## Fix\n\nThe fix replaces the validate-then-fetch pattern with an SSRF-safe httpx transport (`SSRFSafeSyncTransport` from `langchain-core`) that:\n\n- Resolves DNS once and validates all returned IPs against a policy (private ranges, cloud metadata, localhost, k8s internal DNS)\n- Pins the connection to the validated IP, eliminating the DNS rebinding window\n- Disables redirect following to prevent redirect-based SSRF bypasses\n\nThis fix was released in langchain-openai 1.1.14.","status":"published","published":"2026-04-16T23:00:12Z","modified":"2026-06-06T00:59:02Z","cvss":[{"version":"3.1","score":3.1,"vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:L/I:N/A:N","level":"low"}],"cwes":["CWE-918"],"updated_at":"2026-11-02T14:40:18.682012Z"}],"nvd":[{"id":"CVE-2026-41488","description":"LangChain is a framework for building agents and LLM-powered applications. Prior to 1.1.14, langchain-openai's _url_to_size() helper (used by get_num_tokens_from_messages for image token counting) validated URLs for SSRF protection and then fetched them in a separate network operation with independent DNS resolution. This left a TOCTOU / DNS rebinding window: an attacker-controlled hostname could resolve to a public IP during validation and then to a private/localhost IP during the actual fetch.","status":"published","published":"2026-04-24T21:16:19.637Z","modified":"2026-10-26T21:10:00.17Z","cvss":[{"version":"3.1","score":3.1,"vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:L/I:N/A:N","level":"low","assessor":"secondary"}],"cwes":["CWE-918"],"updated_at":"2026-11-02T14:12:16.252509Z"}],"osv":[{"id":"CVE-2026-41488","title":"angchain-openai: Image token counting SSRF protection can be bypassed via DNS rebinding","description":"LangChain is a framework for building agents and LLM-powered applications. Prior to 1.1.14, langchain-openai's _url_to_size() helper (used by get_num_tokens_from_messages for image token counting) validated URLs for SSRF protection and then fetched them in a separate network operation with independent DNS resolution. This left a TOCTOU / DNS rebinding window: an attacker-controlled hostname could resolve to a public IP during validation and then to a private/localhost IP during the actual fetch.","status":"published","published":"2026-04-24T20:57:25.658Z","modified":"2026-10-28T02:30:47.193173441Z","cvss":[{"version":"3.1","score":3.1,"vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:L/I:N/A:N","level":"low"}],"cwes":["CWE-918"],"updated_at":"2026-11-02T15:45:03.764807Z"},{"id":"GHSA-r7w7-9xr2-qq2r","title":"langchain-openai: Image token counting SSRF protection can be bypassed via DNS rebinding","description":"## Summary\n\n`langchain-openai`'s `_url_to_size()` helper (used by `get_num_tokens_from_messages` for image token counting) validated URLs for SSRF protection and then fetched them in a separate network operation with independent DNS resolution. This left a TOCTOU / DNS rebinding window: an attacker-controlled hostname could resolve to a public IP during validation and then to a private/localhost IP during the actual fetch.\n\nThe practical impact is limited because the fetched response body is passed directly to Pillow's `Image.open()` to extract dimensions — the response content is never returned, logged, or otherwise exposed to the caller. An attacker cannot exfiltrate data from internal services through this path. A potential risk is blind probing (inferring whether an internal host/port is open based on timing or error behavior).\n\n## Affected versions\n\n- `langchain-openai` \u003c 1.1.14\n\n## Patched versions\n\n- `langchain-openai` \u003e= 1.1.14 (requires `langchain-core` \u003e= 1.2.31)\n\n## Affected code\n\n**File:** `libs/partners/openai/langchain_openai/chat_models/base.py` — `_url_to_size()`\n\nThe vulnerable pattern was a validate-then-fetch with separate DNS resolution:\n\n```python\nvalidate_safe_url(image_source, allow_private=False, allow_http=True)\n# ... separate network operation with independent DNS resolution ...\nresponse = httpx.get(image_source, timeout=timeout)\n```\n\n## Fix\n\nThe fix replaces the validate-then-fetch pattern with an SSRF-safe httpx transport (`SSRFSafeSyncTransport` from `langchain-core`) that:\n\n- Resolves DNS once and validates all returned IPs against a policy (private ranges, cloud metadata, localhost, k8s internal DNS)\n- Pins the connection to the validated IP, eliminating the DNS rebinding window\n- Disables redirect following to prevent redirect-based SSRF bypasses\n\nThis fix was released in langchain-openai 1.1.14.","status":"published","published":"2026-04-16T23:00:12Z","modified":"2026-06-06T01:15:07.912179267Z","cvss":[{"version":"3.1","score":3.1,"vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:L/I:N/A:N","level":"low"}],"cwes":["CWE-918"],"updated_at":"2026-11-02T15:46:55.480549Z"},{"id":"PYSEC-2026-76","description":"LangChain is a framework for building agents and LLM-powered applications. Prior to 1.1.14, langchain-openai's _url_to_size() helper (used by get_num_tokens_from_messages for image token counting) validated URLs for SSRF protection and then fetched them in a separate network operation with independent DNS resolution. This left a TOCTOU / DNS rebinding window: an attacker-controlled hostname could resolve to a public IP during validation and then to a private/localhost IP during the actual fetch.","status":"published","published":"2026-04-24T21:16:19.637Z","modified":"2026-05-20T09:19:04.187253Z","cvss":[{"version":"3.1","score":3.1,"vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:L/I:N/A:N","level":"low"}],"updated_at":"2026-11-02T15:52:58.117212Z"}]}}
