Every CVESearch/Get API key

CVE-2026-22778

vLLM leaks a heap address when PIL throws an error

9.8 CriticalPublic exploitFix available

vLLM is an inference and serving engine for large language models (LLMs). From 0.8.3 to before 0.14.1, when an invalid image is sent to vLLM's multimodal endpoint, PIL throws an error. vLLM returns this error to the client, leaking a heap address. With this leak, we reduce ASLR from 4 billion guesses to ~8 guesses. This vulnerability can be chained a heap overflow with JPEG2000 decoder in OpenCV/FFmpeg to achieve remote code execution. This vulnerability is fixed in 0.14.1.

Attack profile

How easy it is to exploit

Attack vector
Network
Complexity
Low
Privileges needed
None
User interaction
None

What an attacker can affect

Confidentiality
High
Integrity
High
Availability
High

Exploit likelihood

18.3%Up 18.2 points since Feb 3, 2026
90%50%10%1%

What each source reports

CVE List Score used9.8

vLLM leaks a heap address when PIL throws an error

vLLM is an inference and serving engine for large language models (LLMs). From 0.8.3 to before 0.14.1, when an invalid image is sent to vLLM's multimodal endpoint, PIL throws an error. vLLM returns this error to the client, leaking a heap address. With this leak, we reduce ASLR from 4 billion guesses to ~8 guesses. This vulnerability can be chained a heap overflow with JPEG2000 decoder in OpenCV/FFmpeg to achieve remote code execution. This vulnerability is fixed in 0.14.1.

Record
CVE-2026-22778
CVSS 3.1
9.8 CriticalCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
Weakness
CWE-532, CWE-209
Updated
2026-11-02
EUVDEUVD-2026-52779.8

vLLM is an inference and serving engine for large language models (LLMs). From 0.8.3 to before 0.14.1, when an invalid image is sent to vLLM's multimodal endpoint, PIL throws an error. vLLM returns this error to the client, leaking a heap address. With this leak, we reduce ASLR from 4 billion guesses to ~8 guesses. This vulnerability can be chained a heap overflow with JPEG2000 decoder in OpenCV/FFmpeg to achieve remote code execution. This vulnerability is fixed in 0.14.1.

Record
EUVD-2026-5277
CVSS 3.1
9.8 CriticalCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
Updated
2026-11-02
GitHub AdvisoriesGHSA-4r2x-xpjr-7cvv9.8

vLLM has RCE In Video Processing

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:

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:

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:

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:

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…

Record
GHSA-4r2x-xpjr-7cvv
CVSS 3.1
9.8 CriticalCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
Weakness
CWE-122, CWE-209, CWE-532
Updated
2026-11-02
NVD9.8

vLLM is an inference and serving engine for large language models (LLMs). From 0.8.3 to before 0.14.1, when an invalid image is sent to vLLM's multimodal endpoint, PIL throws an error. vLLM returns this error to the client, leaking a heap address. With this leak, we reduce ASLR from 4 billion guesses to ~8 guesses. This vulnerability can be chained a heap overflow with JPEG2000 decoder in OpenCV/FFmpeg to achieve remote code execution. This vulnerability is fixed in 0.14.1.

Record
CVE-2026-22778
CVSS 3.1
9.8 CriticalCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
Weakness
CWE-532, CWE-209
Updated
2026-11-02
OSV9.8

vLLM leaks a heap address when PIL throws an error

vLLM is an inference and serving engine for large language models (LLMs). From 0.8.3 to before 0.14.1, when an invalid image is sent to vLLM's multimodal endpoint, PIL throws an error. vLLM returns this error to the client, leaking a heap address. With this leak, we reduce ASLR from 4 billion guesses to ~8 guesses. This vulnerability can be chained a heap overflow with JPEG2000 decoder in OpenCV/FFmpeg to achieve remote code execution. This vulnerability is fixed in 0.14.1.

Record
CVE-2026-22778
CVSS 3.1
9.8 CriticalCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
Weakness
CWE-532
Updated
2026-11-02
OSVGHSA-4r2x-xpjr-7cvv9.8

vLLM has RCE In Video Processing

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:

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:

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:

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:

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…

Record
GHSA-4r2x-xpjr-7cvv
CVSS 3.1
9.8 CriticalCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
Weakness
CWE-122, CWE-209, CWE-532
Updated
2026-11-02
OSVPYSEC-2026-5659.8

vLLM has RCE In Video Processing

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:

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:

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:

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:

 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…

Record
PYSEC-2026-565
CVSS 3.1
9.8 CriticalCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
Updated
2026-11-02

Affected products

Affected packages

Affected packages
PackageAffectedFixed
vllm
PyPI
0.8.3 up to 0.14.1
0.14.1
vllm
PyPI
0.8.3 up to 0.14.1, plus listed versions
0.10.00.10.10.10.1.10.10.20.11.0
Show 12 moreShow less
0.11.10.11.20.12.00.13.00.14.00.8.40.8.50.8.5.post10.9.00.9.0.10.9.10.9.2
0.14.1

Public exploits

Links only. Every CVE stores no exploit code.

History

History
RecordedChangedSources
first indexedCVE List, EUVD, GitHub Advisories, Metasploit, Nuclei, NVD, OSV, PoC in GitHub

Dates are when Every CVE recorded each change. Upstream dates may differ.

In short

CVE-2026-22778 is a critical vulnerability (CVSS 9.8) in Vllm, published February 2, 2026. Public exploit code exists. EPSS puts the chance of exploitation in the next 30 days at 18.3%, the 97th percentile. Fixed in vllm 0.14.1.

References

Show 15 moreShow less
This page doesn't list everything

Left out here: the rest of 3 source descriptions. The JSON record has them.

MoveEnter Open