Skip to content

Commit 9d9a2b7

Browse files
huachenhelisimon-mo
authored andcommitted
[Small] Prevent bypassing media domain restriction via HTTP redirects (#26035)
Signed-off-by: Chenheli Hua <[email protected]> Signed-off-by: simon-mo <[email protected]>
1 parent 6040e0b commit 9d9a2b7

File tree

5 files changed

+40
-8
lines changed

5 files changed

+40
-8
lines changed

docs/features/multimodal_inputs.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ This page teaches you how to pass multi-modal inputs to [multi-modal models][sup
88

99
!!! tip
1010
When serving multi-modal models, consider setting `--allowed-media-domains` to restrict domain that vLLM can access to prevent it from accessing arbitrary endpoints that can potentially be vulnerable to Server-Side Request Forgery (SSRF) attacks. You can provide a list of domains for this arg. For example: `--allowed-media-domains upload.wikimedia.org github.com www.bogotobogo.com`
11+
12+
Also, consider setting `VLLM_MEDIA_URL_ALLOW_REDIRECTS=0` to prevent HTTP redirects from being followed to bypass domain restrictions.
13+
1114
This restriction is especially important if you run vLLM in a containerized environment where the vLLM pods may have unrestricted access to internal networks.
1215

1316
## Offline Inference

docs/usage/security.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,9 @@ Restrict domains that vLLM can access for media URLs by setting
6666
`--allowed-media-domains` to prevent Server-Side Request Forgery (SSRF) attacks.
6767
(e.g. `--allowed-media-domains upload.wikimedia.org github.com www.bogotobogo.com`)
6868

69+
Also, consider setting `VLLM_MEDIA_URL_ALLOW_REDIRECTS=0` to prevent HTTP
70+
redirects from being followed to bypass domain restrictions.
71+
6972
## Security and Firewalls: Protecting Exposed vLLM Systems
7073

7174
While vLLM is designed to allow unsafe network services to be isolated to

vllm/connections.py

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ def get_response(
5454
stream: bool = False,
5555
timeout: Optional[float] = None,
5656
extra_headers: Optional[Mapping[str, str]] = None,
57+
allow_redirects: bool = True,
5758
):
5859
self._validate_http_url(url)
5960

@@ -63,14 +64,16 @@ def get_response(
6364
return client.get(url,
6465
headers=self._headers(**extra_headers),
6566
stream=stream,
66-
timeout=timeout)
67+
timeout=timeout,
68+
allow_redirects=allow_redirects)
6769

6870
async def get_async_response(
6971
self,
7072
url: str,
7173
*,
7274
timeout: Optional[float] = None,
7375
extra_headers: Optional[Mapping[str, str]] = None,
76+
allow_redirects: bool = True,
7477
):
7578
self._validate_http_url(url)
7679

@@ -79,10 +82,17 @@ async def get_async_response(
7982

8083
return client.get(url,
8184
headers=self._headers(**extra_headers),
82-
timeout=timeout)
83-
84-
def get_bytes(self, url: str, *, timeout: Optional[float] = None) -> bytes:
85-
with self.get_response(url, timeout=timeout) as r:
85+
timeout=timeout,
86+
allow_redirects=allow_redirects)
87+
88+
def get_bytes(self,
89+
url: str,
90+
*,
91+
timeout: Optional[float] = None,
92+
allow_redirects: bool = True) -> bytes:
93+
with self.get_response(url,
94+
timeout=timeout,
95+
allow_redirects=allow_redirects) as r:
8696
r.raise_for_status()
8797

8898
return r.content
@@ -92,8 +102,10 @@ async def async_get_bytes(
92102
url: str,
93103
*,
94104
timeout: Optional[float] = None,
105+
allow_redirects: bool = True,
95106
) -> bytes:
96-
async with await self.get_async_response(url, timeout=timeout) as r:
107+
async with await self.get_async_response(
108+
url, timeout=timeout, allow_redirects=allow_redirects) as r:
97109
r.raise_for_status()
98110

99111
return await r.read()

vllm/envs.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@
6868
VLLM_IMAGE_FETCH_TIMEOUT: int = 5
6969
VLLM_VIDEO_FETCH_TIMEOUT: int = 30
7070
VLLM_AUDIO_FETCH_TIMEOUT: int = 10
71+
VLLM_MEDIA_URL_ALLOW_REDIRECTS: bool = True
7172
VLLM_MEDIA_LOADING_THREAD_COUNT: int = 8
7273
VLLM_MAX_AUDIO_CLIP_FILESIZE_MB: int = 25
7374
VLLM_VIDEO_LOADER_BACKEND: str = "opencv"
@@ -725,6 +726,11 @@ def get_vllm_port() -> Optional[int]:
725726
"VLLM_AUDIO_FETCH_TIMEOUT":
726727
lambda: int(os.getenv("VLLM_AUDIO_FETCH_TIMEOUT", "10")),
727728

729+
# Whether to allow HTTP redirects when fetching from media URLs.
730+
# Default to True
731+
"VLLM_MEDIA_URL_ALLOW_REDIRECTS":
732+
lambda: bool(int(os.getenv("VLLM_MEDIA_URL_ALLOW_REDIRECTS", "1"))),
733+
728734
# Max number of workers for the thread pool handling
729735
# media bytes loading. Set to 1 to disable parallel processing.
730736
# Default is 8

vllm/multimodal/utils.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,11 @@ def load_from_url(
140140
self._assert_url_in_allowed_media_domains(url_spec)
141141

142142
connection = self.connection
143-
data = connection.get_bytes(url, timeout=fetch_timeout)
143+
data = connection.get_bytes(
144+
url,
145+
timeout=fetch_timeout,
146+
allow_redirects=envs.VLLM_MEDIA_URL_ALLOW_REDIRECTS,
147+
)
144148

145149
return media_io.load_bytes(data)
146150

@@ -167,7 +171,11 @@ async def load_from_url_async(
167171
self._assert_url_in_allowed_media_domains(url_spec)
168172

169173
connection = self.connection
170-
data = await connection.async_get_bytes(url, timeout=fetch_timeout)
174+
data = await connection.async_get_bytes(
175+
url,
176+
timeout=fetch_timeout,
177+
allow_redirects=envs.VLLM_MEDIA_URL_ALLOW_REDIRECTS,
178+
)
171179
future = loop.run_in_executor(global_thread_pool,
172180
media_io.load_bytes, data)
173181
return await future

0 commit comments

Comments
 (0)