Skip to content
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 40 additions & 1 deletion components/src/dynamo/trtllm/multimodal_processor.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,37 @@ def is_url(self, path: str) -> bool:
return False
return bool(parsed.scheme and parsed.netloc)

@staticmethod
def _assert_public_url(url: str) -> None:
"""Reject a URL that resolves to a non-public address (SSRF guard).

The embedding path is a request-supplied input, so a client must not be
able to steer the fetch to an internal or cloud-metadata address.
"""
import ipaddress
import socket
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Resolved

parsed = urlparse(url)
if parsed.scheme not in ("http", "https") or not parsed.hostname:
raise RuntimeError("Invalid embedding URL")
default_port = 443 if parsed.scheme == "https" else 80
for info in socket.getaddrinfo(
parsed.hostname, parsed.port or default_port, type=socket.SOCK_STREAM
):
ip_str = str(info[4][0]).split("%", 1)[0]
addr = ipaddress.ip_address(ip_str)
if (
addr.is_private
or addr.is_loopback
or addr.is_link_local
or addr.is_reserved
or addr.is_multicast
or addr.is_unspecified
):
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Resolved
raise RuntimeError(
f"Embedding URL resolves to blocked address: {addr}"
)

def _unwrap_safetensors(
self, data: Dict[str, torch.Tensor]
) -> "torch.Tensor | Dict[str, torch.Tensor]":
Expand Down Expand Up @@ -122,9 +153,17 @@ def load_tensor_from_path_or_url(
if self.is_url(path):
if parsed.scheme not in ("http", "https"):
raise RuntimeError(f"Unsupported URL scheme: {parsed.scheme}")
self._assert_public_url(path)
try:
with httpx.Client(timeout=300.0) as client:
# Do not follow redirects automatically: a public URL could
# otherwise redirect the fetch into an internal/metadata address
# (the initial-URL check would not see it).
with httpx.Client(timeout=300.0, follow_redirects=False) as client:
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Resolved
with client.stream("GET", path) as resp:
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Resolved
if resp.is_redirect:
raise RuntimeError(
"Redirects are not allowed when fetching embeddings"
)
resp.raise_for_status()
content_length = resp.headers.get("content-length")
if (
Expand Down
Loading