GHSA-v359-jj2v-j536 CVE-2026-25960 PYSEC-2026-3411
vLLM has SSRF Protection Bypass
- Severity
- 5.4 / 10
- Critical · CVSS 3.1
- Exploit chance (EPSS)
- 0.57%
- Chance of exploitation in the next 30 days. Higher than 47.00% of scored vulnerabilities.
- Known exploited
- No
- Not in CISA's catalog
- Weakness
- CWE-918 Server-Side Request Forgery (SSRF)
- Fix
0.17.0- Upgrade vllm to this version or later
Description
Summary
The SSRF protection fix for https://github.com/vllm-project/vllm/security/advisories/GHSA-qh4c-xf7m-gxfc can be bypassed in the load_from_url_async method due to inconsistent URL parsing behavior between the validation layer and the actual HTTP client.
Affected Component
- File:
vllm/connections.py - Function:
load_from_url_async
Vulnerability Details
Root Cause
The SSRF fix uses urllib3.util.parse_url() to validate and extract the hostname from user-provided URLs. However, load_from_url_async uses aiohttp for making the actual HTTP requests, and aiohttp internally uses the yarl library for URL parsing.
These two URL parsers handle backslash characters (\) differently:
| Parser | Input URL | Parsed Host | Parsed Path | Behavior |
|---|---|---|---|---|
urllib3.parse_url() |
https://httpbin.org\@evil.com/ |
httpbin.org |
/%5C@evil.com/ |
URL-encodes \ as %5C, treats \@evil.com/ as part of the path |
yarl (via aiohttp) |
https://httpbin.org\@evil.com/ |
evil.com |
/ |
Treats \ as part of userinfo (user: httpbin.org\), the @ acts as the userinfo/host separator |
Attack Scenario
# Attacker provides this URL
malicious_url = "https://httpbin.org\\@evil.com/"
# 1. Validation layer (urllib3.parse_url)
parsed = urllib3.util.parse_url(malicious_url)
# parsed.host == "httpbin.org" ✅ Passes validation
# 2. Actual request (aiohttp with yarl)
async with aiohttp.ClientSession() as session:
async with session.get(malicious_url) as response:
# Request actually goes to evil.com! ❌ Bypass!
Why This Happens
- yarl: Interprets
httpbin.org\as the userinfo component, and@as the userinfo/host separator, so the URL is parsed asuser=httpbin.org\,host=evil.com,path=/ - urllib3: URL-encodes the backslash as
%5C, so\@evil.com/becomes/%5C@evil.com/which is treated as part of the path, leavinghost=httpbin.org
This inconsistency allows an attacker to:
- Bypass the hostname allowlist check
- Access arbitrary internal/external services
- Perform full SSRF attacks
Fixes
Affected versions
PyPI
| Package | Vulnerable | Fixed in |
|---|---|---|
| vllm | >= 0.15.1, < 0.17.0 |
0.17.0 |
How to fix
Move to the fixed version or later with your package manager, update the lockfile, and run your tests. If the package only arrives through another dependency, upgrade that dependency first. If none of its releases pulls a fixed version yet, force the version with your package manager's override.
vllm PyPI → 0.17.0
- pip
pip install --upgrade "vllm>=0.17.0"- poetry
poetry add "vllm>=0.17.0"- uv
uv add "vllm>=0.17.0"
Severity breakdown
CVSS 3.1 5.4
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:L
- Attack vector
- Network
- Attack complexity
- Low
- Privileges required
- Low
- User interaction
- None
- Scope
- Unchanged
- Confidentiality
- Low
- Integrity
- None
- Availability
- Low
Weakness
CWE-918: Server-Side Request Forgery (SSRF)
The web server receives a URL or similar request from an upstream component and retrieves the contents of this URL, but it does not sufficiently ensure that the request is being sent to the expected destination.
References
Advisories
Packages
Other links
- github.com/vllm-project/vllm/security/advisories/GHSA-qh4c-xf7m-gxfc
- github.com/vllm-project/vllm/security/advisories/GHSA-v359-jj2v-j536
- github.com/vllm-project/vllm/pull/34743
- github.com/vllm-project/vllm/commit/6f3b2047abd4a748e3db4a68543f8221358002c0
- access.redhat.com/errata/RHSA-2026:24977
- access.redhat.com/security/cve/CVE-2026-25960
- bugzilla.redhat.com/show_bug.cgi
- github.com/pypa/advisory-database/tree/main/vulns/vllm/PYSEC-2026-3411.yaml
- pypi.org/project/vllm
- security.access.redhat.com/data/csaf/v2/vex/2026/cve-2026-25960.json
- access.redhat.com/errata/RHSA-2026:42644
Timeline
- Published
- Last updated by the source
- Latest EPSS score
Related advisories
| Advisory | Severity | Why it's related |
|---|---|---|
| GHSA-8397-8qf6-f2gm vLLM: Phi-4 multimodal audio encoder materializes and retains full attention matrices: a single max-length audio OOM-crashes the vLLM engine | Medium | Also affects vllm |
| GHSA-x567-49g5-p4cf vLLM: Responses API bypasses trust_request_chat_template for chat_template_kwargs | Medium | Also affects vllm |
| GHSA-vvpg-rrww-wpmh vLLM: Permissive default CORS origins allow cross-origin requests to the vLLM HTTP server | Medium | Also affects vllm |
| GHSA-q97c-p368-75c4 vLLM: Out-of-vocabulary prompt token id passes input validation and triggers a CUDA device-side assert (engine crash / DoS) | Medium | Also affects vllm |
| GHSA-h3rc-j82p-2c3h vLLM: Untrusted EPS inputs can trigger denial of service or Ghostscript RCE | High | Also affects vllm |
| GHSA-gq5q-89c7-vhvx vLLM DeepSeek-OCR image processing vulnerable to denial of service | Medium | Also affects vllm |
| GHSA-6757-hggm-hp2w vLLM: Public multimodal SHM handle forgery reaches worker-side `pickle.loads()` with insecure serialization disabled | High | Also affects vllm |
| GHSA-542m-9234-8gvf vLLM: DoS via unbounded chat_template Jinja2 rendering exhausts the renderer thread pool | Medium | Also affects vllm |
MergeHarbor checks every repository's dependencies against this database, ranks what matters by exploitability and reachability, routes it to the owning team and opens the fix pull request.
Check your repos with MergeHarbor