Skip to content

Commit 0516156

Browse files
authored
fix(openai): use SSRF-safe transport for image token counting (#36819)
1 parent 338aa81 commit 0516156

2 files changed

Lines changed: 18 additions & 27 deletions

File tree

libs/partners/openai/langchain_openai/chat_models/base.py

Lines changed: 17 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,7 @@
141141
from langchain_openai.data._profiles import _PROFILES
142142

143143
if TYPE_CHECKING:
144+
import httpx
144145
from langchain_core.language_models import ModelProfile
145146
from openai.types.responses import Response
146147

@@ -150,6 +151,20 @@
150151
# https://www.python-httpx.org/advanced/ssl/#configuring-client-instances
151152
global_ssl_context = ssl.create_default_context(cafile=certifi.where())
152153

154+
_ssrf_client: httpx.Client | None = None
155+
156+
157+
def _get_ssrf_safe_client() -> httpx.Client:
158+
global _ssrf_client
159+
if _ssrf_client is None:
160+
from langchain_core._security._transport import ssrf_safe_client
161+
162+
_ssrf_client = ssrf_safe_client(
163+
verify=global_ssl_context, follow_redirects=False
164+
)
165+
return _ssrf_client
166+
167+
153168
_MODEL_PROFILES = cast(ModelProfileRegistry, _PROFILES)
154169

155170

@@ -3638,28 +3653,7 @@ def _url_to_size(image_source: str) -> tuple[int, int] | None:
36383653
)
36393654
return None
36403655
if _is_url(image_source):
3641-
try:
3642-
import httpx
3643-
except ImportError:
3644-
logger.info(
3645-
"Unable to count image tokens. To count image tokens please install "
3646-
"`pip install -U httpx`."
3647-
)
3648-
return None
3649-
3650-
# Validate URL for SSRF protection
3651-
try:
3652-
from langchain_core._security._ssrf_protection import validate_safe_url
3653-
3654-
validate_safe_url(image_source, allow_private=False, allow_http=True)
3655-
except ImportError:
3656-
logger.warning(
3657-
"SSRF protection not available. "
3658-
"Update langchain-core to get SSRF protection."
3659-
)
3660-
except ValueError as e:
3661-
logger.warning("Image URL failed SSRF validation: %s", e)
3662-
return None
3656+
import httpx
36633657

36643658
# Set reasonable limits to prevent resource exhaustion
36653659
# Timeout prevents indefinite hangs on slow/malicious servers
@@ -3668,10 +3662,7 @@ def _url_to_size(image_source: str) -> tuple[int, int] | None:
36683662
max_size = 50 * 1024 * 1024 # 50 MB
36693663

36703664
try:
3671-
response = httpx.get(
3672-
image_source,
3673-
timeout=timeout,
3674-
)
3665+
response = _get_ssrf_safe_client().get(image_source, timeout=timeout)
36753666
response.raise_for_status()
36763667

36773668
# Check response size before loading into memory

libs/partners/openai/pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ classifiers = [
2323
version = "1.1.13"
2424
requires-python = ">=3.10.0,<4.0.0"
2525
dependencies = [
26-
"langchain-core>=1.2.29,<2.0.0",
26+
"langchain-core>=1.2.31,<2.0.0",
2727
"openai>=2.26.0,<3.0.0",
2828
"tiktoken>=0.7.0,<1.0.0",
2929
]

0 commit comments

Comments
 (0)