CVE-2026-34755 is a medium-severity (CVSS 6.5) CWE-770 vulnerability in vllm. A fix is available for vllm — see the affected versions and patch details below.
vLLM Affected by Denial of Service via Unbounded Frame Count in video/jpeg Base64 Processing
Exploitation Status
No confirmed exploitation observed yet
- CISA’s own triage has not observed active exploitation or public proof-of-concept code for this CVE as of its last assessment.
Exploitation and automatability from CISA’s SSVC triage for CVE-2026-34755.
EPSS Exploitation Probability
EPSS (Exploit Prediction Scoring System) is a daily probability model maintained by FIRST.org. It estimates the likelihood a CVE will be exploited in production environments within the next 30 days, derived from real-world threat intelligence signals.
How urgent is this, really
CVE-2026-34755 plotted by exploitation likelihood (EPSS) against impact (CVSS). The shaded corner — EPSS 50%+ and CVSS 7.0+ — is where this CVE doesn't sit, though severity or exploitability alone can still warrant action.
Where this sits among everything scored
Of 378,156 CVEs with a current EPSS score, this one falls in the < 10% band (highlighted). Real counts from FIRST.org, not a sample — log-scaled since the landscape is heavily right-skewed.
Real-World Exposure
vllmReal-time download stats are indexed for npm and PyPI packages. This vulnerability affects PyPI packages — download data is not available via public APIs for these ecosystems.
Description
Summary
The VideoMediaIO.load_base64() method at vllm/multimodal/media/video.py:51-62 splits video/jpeg data URLs by comma to extract individual JPEG frames, but does not enforce a frame count limit. The num_frames parameter (default: 32), which is enforced by the load_bytes() code path at line 47-48, is completely bypassed in the video/jpeg base64 path. An attacker can send a single API request containing thousands of comma-separated base64-encoded JPEG frames, causing the server to decode all frames into memory and crash with OOM.
Details
Vulnerable code
# video.py:51-62
def load_base64(self, media_type: str, data: str) -> tuple[npt.NDArray, dict[str, Any]]:
if media_type.lower() == "video/jpeg":
load_frame = partial(self.image_io.load_base64, "image/jpeg")
return np.stack(
[np.asarray(load_frame(frame_data)) for frame_data in data.split(",")]
# ^^^^^^^^^^
# Unbounded split — no frame count limit
), {}
return self.load_bytes(base64.b64decode(data))
The load_bytes() path (line 47-48) properly delegates to a video loader that respects self.num_frames (default 32). The load_base64("video/jpeg", ...) path bypasses this limit entirely — data.split(",") produces an unbounded list and every frame is decoded into a numpy array.
video/jpeg is part of vLLM's public API
video/jpeg is a vLLM-specific MIME type, not IANA-registered. However it is part of the public API surface:
encode_video_url()atvllm/multimodal/utils.py:96-108generatesdata:video/jpeg;base64,...URLs- Official test suites at
tests/entrypoints/openai/test_video.py:62andtests/entrypoints/test_chat_utils.py:153both use this format
Memory amplification
Each JPEG frame decodes to a full numpy array. For 640x480 RGB images, each frame is ~921 KB decoded. 5000 frames = ~4.6 GB. np.stack() then creates an additional copy. The compressed JPEG payload is small (~100 KB for 5000 frames) but decompresses to gigabytes.
Data flow
POST /v1/chat/completions
→ chat_utils.py:1434 video_url type → mm_parser.parse_video()
→ chat_utils.py:872 parse_video() → self._connector.fetch_video()
→ connector.py:295 fetch_video() → load_from_url(url, self.video_io)
→ connector.py:91 _load_data_url(): url_spec.path.split(",", 1)
→ media_type = "video/jpeg"
→ data = "<frame1>,<frame2>,...,<frame10000>"
→ connector.py:100 media_io.load_base64("video/jpeg", data)
→ video.py:54 data.split(",") ← UNBOUNDED
→ video.py:55-57 all frames decoded into numpy arrays
→ video.py:56 np.stack([...]) ← massive combined array → OOM
connector.py:91 uses split(",", 1) which splits on only the first comma. All remaining commas stay in data and are later split by video.py:54.
Comparison with existing protections
| Code Path | Frame Limit | File |
|---|---|---|
load_bytes() (binary video) | Yes — num_frames (default 32) | video.py:46-49 |
load_base64("video/jpeg", ...) | No — unlimited data.split(",") | video.py:51-62 |
Affected Packages
| Ecosystem | Package | Vulnerable range | Fix |
|---|---|---|---|
| 🐍PyPI | vllm | ≥ 0.7.0&&< 0.19.0 | 0.19.0pip install --upgrade 'vllm==0.19.0' |
Detection & mitigation playbook
Open-source dependencyDetect
Scan your dependency tree (package-lock.json, pnpm-lock.yaml, requirements.txt, go.sum, etc.) for vllm, including transitive dependencies — a direct dependency you never call can still pull in a vulnerable version.
Fix
Update vllm to 0.19.0 or later, then make sure no transitive (indirect) dependency still pins the vulnerable range — O3 confirms CVE-2026-34755 is resolved across your whole dependency graph.
Workarounds
If you can't upgrade right away: gate or disable the affected feature, validate untrusted input at the boundary, and avoid passing attacker-controlled data into the vulnerable path. O3's runtime protection blocks exploitation in production as an interim safeguard until the upgrade lands.
How O3 protects you
O3 Security's impact-aware SCA analyses which vulnerable code paths your application actually calls, so a match like CVE-2026-34755 can be triaged on real exposure rather than presence alone.
Tailored to CVE-2026-34755. Runtime protection reduces exposure until a permanent patch is applied and verified — it complements patching, it doesn't replace it.
Fixing This On Your OS
If you run this on a Linux distribution, patch through your package manager against the distro's own security advisory below — it tracks the exact backported fix for your release, which can ship on a different timeline (and sometimes a different severity) than the upstream project.
| Product | Fixed in | Advisory |
|---|---|---|
| Red Hat AI Inference Server 3.2 | rhaiis/vllm-cuda-rhel9:1782951012 | RHSA-2026:36005 |
| Red Hat AI Inference Server 3.2 | rhaiis/vllm-rocm-rhel9:1782951244 | RHSA-2026:36006 |
| Red Hat AI Inference Server 3.4 | rhaii/vllm-cpu-rhel9:1787151769 | RHSA-2026:57380 |
| Red Hat AI Inference Server 3.4 | rhaii/vllm-spyre-rhel9:1787151840 | RHSA-2026:57387 |
| Red Hat AI Inference Server 3.4 | rhaii/vllm-cuda-rhel9:1787151771 | RHSA-2026:57389 |
| Red Hat AI Inference Server 3.4 | rhaii/vllm-rocm-rhel9:1787151774 | RHSA-2026:57390 |
| Red Hat Enterprise Linux AI 3.4 | rhelai3/disk-image-cuda-rhel9:1787310717 | RHSA-2026:59144 |
| Red Hat Enterprise Linux AI 3.4 | rhelai3/bootc-aws-cuda-rhel9:1787253912 | RHSA-2026:59151 |
Frequently Asked Questions
Is CVE-2026-34755 in your dependencies?
O3 Security finds CVE-2026-34755 across PyPI dependencies, including transitive ones, and its impact-aware SCA ranks findings by whether your code actually calls the vulnerable path.