Apr 17, 2026·7 min read·3 visits
LangChain's OpenAI integration is vulnerable to a low-severity blind SSRF via DNS rebinding in its image token counter. The flaw allows attackers to probe internal networks, though data exfiltration is prevented by strict image parsing constraints.
A Server-Side Request Forgery (SSRF) vulnerability exists in the langchain-openai package before version 1.1.14 due to a Time-of-Check Time-of-Use (TOCTOU) race condition in the image token calculation logic. The _url_to_size function evaluates URL safety and performs the HTTP fetch using separate DNS resolutions, permitting a DNS rebinding attack.
The langchain-openai package provides the official LangChain integration for OpenAI's language models. Applications using this package often process multi-modal chat messages containing text and image URLs. To accurately estimate token usage and calculate costs prior to dispatching requests to OpenAI APIs, the framework must determine the dimensions of provided images. This task is handled by the _url_to_size() helper function located in libs/partners/openai/langchain_openai/chat_models/base.py.
When a multi-modal message contains an external image URL, the application calculates the total token count by fetching the image and extracting its metadata. The vulnerability resides in how this external HTTP fetch is implemented and secured. Specifically, the framework attempts to prevent Server-Side Request Forgery (SSRF) by validating the destination URL against a list of forbidden private and internal IP ranges before initializing the connection.
The original implementation relied on a fundamentally flawed "validate-then-fetch" pattern. This pattern introduces a Time-of-Check Time-of-Use (TOCTOU) race condition mapped to CWE-367. The underlying vulnerability allows an external attacker to bypass the SSRF protections and compel the hosting server to initiate HTTP requests toward restricted internal infrastructure.
The root cause of GHSA-R7W7-9XR2-QQ2R is the lack of DNS pinning between the security validation phase and the subsequent network request. In the vulnerable code, the _url_to_size() function executes two distinct operations that independently perform DNS resolution. The initial validation step invokes validate_safe_url(), which resolves the provided hostname to an IP address and verifies that the IP does not fall within RFC 1918 private address spaces, loopback ranges, or known cloud metadata service endpoints.
Following successful validation, the code proceeds to download the image using the httpx.get(image_source) method. The httpx library, operating entirely unaware of the preceding validation step, performs a secondary DNS resolution for the same hostname. This secondary resolution is mandated by the standard TCP connection establishment sequence. Because DNS records can be configured with extremely short Time-To-Live (TTL) values, the hostname may resolve to a different IP address during this second query.
This discrepancy creates the necessary conditions for a DNS rebinding attack. An attacker can control an authoritative DNS server for a custom domain and configure it to respond to the initial query with a benign, publicly routable IP address. When the httpx library issues the subsequent query milliseconds later, the attacker's DNS server responds with a private, internal IP address (e.g., 127.0.0.1 or 169.254.169.254). The application, having already completed the validation checks, connects to the internal service.
The vulnerable implementation exposes the TOCTOU gap clearly by separating the validation function from the network transport layer. The code imports a validation utility from langchain-core but fails to pass the validated IP address forward to the HTTP client.
# Vulnerable Implementation
# libs/partners/openai/langchain_openai/chat_models/base.py
# Phase 1: DNS resolution occurs here for validation
validate_safe_url(image_source, allow_private=False, allow_http=True)
# Phase 2: A secondary, independent DNS resolution occurs here
response = httpx.get(image_source, timeout=timeout)The fix introduced in Pull Request 36819 abandons the "validate-then-fetch" paradigm in favor of a customized, SSRF-safe network transport. By utilizing SSRFSafeSyncTransport provided by langchain-core version 1.2.31 or greater, the application delegates both validation and connection establishment to a unified component.
# Patched Implementation
# Uses SSRFSafeSyncTransport to enforce single-resolution and DNS pinning
with httpx.Client(transport=SSRFSafeSyncTransport()) as client:
response = client.get(image_source, timeout=timeout)The SSRFSafeSyncTransport mechanism operates by overriding the default connection pooling and resolution logic within the HTTP client. It resolves the hostname exactly once, validates the resulting IP address against the strict internal exclusion policy, and subsequently binds the TCP socket directly to that validated IP address. Additionally, the updated transport disables automatic redirect following, preventing attackers from bypassing the initial check via HTTP 302 redirects to internal resources.
Exploiting this vulnerability requires the attacker to submit a crafted multi-modal prompt containing an image URL pointing to an attacker-controlled domain. The domain must be delegated to a custom authoritative name server configured to execute the DNS rebinding sequence. The attack process initiates when the application parses the prompt and triggers the _url_to_size() helper to calculate token dimensions.
The attacker's name server responds to the initial DNS A-record request with a benign external IP address and an aggressively short TTL, typically zero. When httpx.get() invokes the system's resolver shortly after, the cache has expired, forcing a second query. The custom name server intercepts this subsequent request and responds with the targeted internal IP address, directing the HTTP request into the protected network segment.
Due to the specific architecture of the vulnerable function, the attacker never receives the direct HTTP response body. The framework pipes the response content directly into the Pillow library's Image.open() function to parse height and width. If the internal service responds with non-image data (such as JSON from an internal API), Pillow raises a parsing exception. The attacker leverages these exceptions, or the lack thereof, alongside request timing differentials, to perform blind SSRF mapping of the internal environment.
The vulnerability carries a CVSS 3.1 score of 3.1 (Low), reflecting its strictly limited exploitation outcomes. The vector is evaluated as CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:L/I:N/A:N. High attack complexity is attributed to the necessity of reliable DNS rebinding, which is frequently disrupted by modern operating system and runtime DNS caching mechanisms.
The primary security impact is limited to internal network reconnaissance and blind probing. Because the HTTP response body is exclusively consumed by Pillow's image parsing routines, direct data exfiltration is categorically impossible. An attacker cannot retrieve sensitive credentials, metadata tokens, or configuration files from internal endpoints, as these text-based payloads will immediately cause Image.open() to fail and discard the data.
Despite the lack of direct data exposure, the vulnerability does permit an attacker to map internal network topology. By iteratively submitting requests to various internal IP addresses and ports, the attacker measures response delays and observes error signatures. A connection timeout indicates an unreachable host or filtered port, whereas a rapid image parsing exception confirms the existence of an active service responding with non-image data.
The definitive remediation for this vulnerability is upgrading the affected dependencies to their patched versions. Organizations must update langchain-openai to version 1.1.14 or later. Because the protective transport mechanism was implemented in the core framework, the environment also requires langchain-core to be updated to version 1.2.31 or greater.
For environments where immediate patching is administratively blocked, mitigation can be achieved by intercepting and filtering outbound requests at the network perimeter. Implementing egress filtering on the application servers prevents unauthorized connections to internal infrastructure, regardless of the application's internal DNS resolution flaws. Rules should explicitly deny outbound traffic from the application layer to 127.0.0.0/8, 169.254.169.254, and any internal VPC CIDR blocks.
Developers building custom integrations using LangChain should audit their own codebase for similar "validate-then-fetch" patterns. All external HTTP requests initiated by backend services must utilize pinned DNS resolutions and explicitly disable HTTP redirect following unless strictly necessary. Adopting the SSRFSafeSyncTransport class for custom httpx clients provides a robust, centralized defense against DNS rebinding and associated SSRF techniques.
CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:L/I:N/A:N| Product | Affected Versions | Fixed Version |
|---|---|---|
langchain-openai LangChain | < 1.1.14 | 1.1.14 |
| Attribute | Detail |
|---|---|
| Vulnerability Class | CWE-918 (SSRF) / CWE-367 (TOCTOU) |
| Attack Vector | Network |
| CVSS v3.1 Score | 3.1 (Low) |
| Impact | Blind Internal Network Probing |
| Exploit Status | Proof of Concept |
| KEV Status | Not Listed |
The application fails to securely validate the destination of network requests, leading to Server-Side Request Forgery due to a Time-of-Check Time-of-Use race condition.