vLLM has RCE In Video Processing
Critical9.8CVE-2026-22778 · Published Feb 2, 2026 · updated Sep 10, 2026
Affected versions
| Package | Affected | Fixed in |
|---|---|---|
| vllm PyPI | >= 0.8.3, < 0.14.1 | 0.14.1 |
Details and references
## Summary **A chain of vulnerabilities in vLLM allow Remote Code Execution (RCE):** 1. **Info Leak** - PIL error messages expose memory addresses, bypassing ASLR 2. **Heap Overflow** - JPEG2000 decoder in OpenCV/FFmpeg has a heap overflow that lets us hijack code execution **Result:** Send a malicious video URL to vLLM Completions or Invocations **for a video model** -> Execute arbitrary commands on the server Completely default vLLM instance directly from pip, or docker, does not have authentication so "None" privileges are required, but even with non-default api-key enabled configuration this exploit is feasible through invocations route that allows payload to execute pre-auth. Example heap target is provided, other heap targets can be exploited as well to achieve rce. Leak allows for simple ASLR bypass. Leak + heap overflow achieves RCE on versions prior to 0.14.1. Deployments not serving a video model are not affected. --- ## 1. Vulnerability Overview ### 1.1 The Bug: JPEG2000 cdef Box Heap Overflow The JPEG2000 decoder used by OpenCV (cv2) honors a `cdef` box that can remap color channels. When Y (luma) is mapped into the U (chroma) plane buffer, the decoder writes a large Y plane into the smaller U buffer, causing a heap overflow. **Root Cause** - `cdef` allows channel remapping (e.g., Y→U, U→Y). - Y plane size: `W×H`; U plane size: `(W/2)×(H/2)`. - Overflow size = `W×H - (W/2×H/2)` = `0.75 × W × H` bytes. **Example (150×64)** - Y plane: 150×64 = 9,600 bytes - U plane: 75×32 = 2,400 bytes - Overflow: 7,200 bytes past the U buffer ### 1.2 Malicious cdef Box ``` Offset Size Field Value 0 4 Box Length 0x00000016 (22 bytes) 4 4 Box Type 'cdef' 8 2 N (channels) 0x0003 10 2 Channel 0 Cn 0x0000 (Y channel) 12 2 Channel 0 Typ 0x0000 (color) 14 2 Channel 0 Asoc 0x0002 (→ maps Y into U plane) 16 2 Channel 1 Cn 0x0001 (U channel) 18 2 Channel 1 Typ 0x0000 (color) 20 2 Channel 1 Asoc 0x0001 (→ maps U into Y plane) 22 2 Channel 2 Cn 0x0002 (V channel) 24 2 Channel 2 Typ 0x0000 (color) 26 2 Channel 2 Asoc 0x0003 (→ maps V plane) ``` Key control: `Asoc=2` for channel 0 forces Y data into the U buffer, triggering the overflow. --- ## Vulnerable Code Chain ### 1) Entry: vLLM accepts a remote `video_url` and downloads raw bytes vLLM’s OpenAI-compatible API supports a `video_url` content part: ```python class VideoURL(TypedDict, total=False): url: Required[str] class ChatCompletionContentPartVideoParam(TypedDict, total=False): video_url: Required[VideoURL] type: Required[Literal["video_url"]] ``` Source: `src/vllm/entrypoints/chat_utils.py`. When the URL is HTTP(S), vLLM downloads it as **raw bytes** and passes the bytes into the modality loader: ```python if url_spec.scheme.startswith("http"): data = connection.get_bytes(url, timeout=fetch_timeout, allow_redirects=...) return media_io.load_bytes(data) ``` Source: `src/vllm/multimodal/utils.py` (`MediaConnector.load_from_url`). --- ### 2) Decode: vLLM uses OpenCV (cv2) VideoCapture on an in-memory byte stream The default video backend is OpenCV, and it constructs `cv2.VideoCapture` over a `BytesIO` buffer containing the downloaded bytes: ```python backend = cls().get_cv2_video_api() cap = cv2.VideoCapture(BytesIO(data), backend, []) if not cap.isOpened(): raise ValueError("Could not open video stream") ``` Source: `src/vllm/multimodal/video.py` (`OpenCVVideoBackend.load_bytes`). The backend is selected from OpenCV’s stream-buffered backends registry: ```python import cv2.videoio_registry as vr for backend in vr.getStreamBufferedBackends(): if vr.hasBackend(backend) and ...: api_pref = backend break return api_pref ``` Source: `src/vllm/multimodal/video.py` (`OpenCVVideoBackend.get_cv2_video_api`). **Implication**: vLLM is delegating container parsing + co
- CVSS 3.1
- CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
- Severity from
- GitHub (reviewed advisory)
- Weakness
- CWE-122, CWE-209, CWE-532
- Also known as
- CVE-2026-22778, PYSEC-2026-565
- github.com/vllm-project/vllm/security/advisories/GHSA-4r2x-xpjr-7cvv
- nvd.nist.gov/vuln/detail/CVE-2026-22778
- github.com/vllm-project/vllm/pull/32319
- github.com/vllm-project/vllm/pull/31987
- security.access.redhat.com/data/csaf/v2/vex/2026/cve-2026-22778.json
- pypi.org/project/vllm
- github.com/vllm-project/vllm/releases/tag/v0.14.1
- github.com/vllm-project/vllm
- github.com/pypa/advisory-database/tree/main/vulns/vllm/PYSEC-2026-565.yaml
- github.com/advisories/GHSA-4r2x-xpjr-7cvv
- bugzilla.redhat.com/show_bug.cgi?id=2436113
- access.redhat.com/security/cve/CVE-2026-22778
- access.redhat.com/errata/RHSA-2026:3782
- access.redhat.com/errata/RHSA-2026:3713
- access.redhat.com/errata/RHSA-2026:3462
- access.redhat.com/errata/RHSA-2026:3461
- access.redhat.com/errata/RHSA-2026:30089
- access.redhat.com/errata/RHSA-2026:30088
- access.redhat.com/errata/RHSA-2026:30087
- access.redhat.com/errata/RHSA-2026:19712
More vLLM advisories
All vLLM| Date | Advisory | Severity | Fixed in |
|---|---|---|---|
| Jan 28 | vLLM vulnerable to Server-Side Request Forgery (SSRF) through MediaConnector CVE-2026-24779High7.1fixed in 0.14.1 | High7.1 | 0.14.1 |
| Jan 21 | vLLM affected by RCE via auto_map dynamic module loading during model initialization CVE-2026-22807High8.8fixed in 0.14.0 | High8.8 | 0.14.0 |
| Jan 13 | vLLM is vulnerable to DoS in Idefics3 vision models via image payload with ambiguous dimensions CVE-2026-22773Medium6.5fixed in 0.12.0 | Medium6.5 | 0.12.0 |
| Jan 8 | vLLM introduced enhanced protection for CVE-2025-62164 CVE-2026-56340High8.8fixed in 0.13.0 | High8.8 | 0.13.0 |
| Mar 9 | vLLM has SSRF Protection Bypass CVE-2026-25960Medium5.4fixed in 0.17.0 | Medium5.4 | 0.17.0 |
| Mar 27 | vLLM has Hardcoded Trust Override in Model Files Enables RCE Despite Explicit User Opt-Out CVE-2026-27893High8.8fixed in 0.18.0 | High8.8 | 0.18.0 |