vLLM is one of the most widely deployed open-source LLM inference servers, the serving layer that sits between a model and the network. On November 20, 2025 its maintainers published CVE-2025-62164, a high-severity deserialization vulnerability in the Completions API that could corrupt server memory and, under the right conditions, lead to remote code execution. The instructive part is not that a deserialization bug existed, but that it existed in code that had already reached for PyTorch's safe loading mode and still was not safe.

The facts

  • Identifier: CVE-2025-62164 (advisory GHSA-mrw7-hf4f-83pf).
  • Severity: CVSS 8.8, High. Vector CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H.
  • Affected: vLLM from 0.10.2 up to, but not including, 0.11.1.
  • Fixed in: 0.11.1.
  • Weakness classes: CWE-502 (deserialization of untrusted data), CWE-787 (out-of-bounds write), plus CWE-20 and CWE-123.

Read the vector carefully. PR:L means the attacker needs some privilege: the ability to send requests to the Completions endpoint. That is not the same as fully unauthenticated internet access. It also is not much comfort, because a large share of vLLM deployments expose the API on a trusted network with no authentication in front of it, on the assumption that the serving layer only ever sees well-formed inference traffic. This vulnerability is what happens when that assumption is wrong.

The mechanism

The Completions API accepts prompt embeddings: tensors a client can supply directly instead of text. In the affected versions, the function _load_and_validate_embed in vllm/entrypoints/renderer.py deserialized those user-supplied tensors with torch.load().

Crucially, the code already passed weights_only=True. That flag is PyTorch's headline mitigation against the classic torch.load pickle-execution problem, and its presence is exactly why this bug is worth writing about: the developers did the thing the ecosystem tells you to do, and it was still exploitable.

The reason is a change in PyTorch itself. From PyTorch 2.8.0, sparse tensor integrity checks are disabled by default. A maliciously crafted sparse tensor can therefore carry indices that bypass bounds checks, and when vLLM converts that tensor to a dense representation with to_dense(), the out-of-range indices drive an out-of-bounds memory write. The immediate result is memory corruption and denial of service; memory-corruption primitives of this shape are the raw material from which remote code execution is built, which is why the advisory rates confidentiality, integrity, and availability all High.

The deeper lesson is a dependency-boundary one. weights_only=True was a correct defense against the threat it was designed for. It said nothing about a separate safety property, sparse tensor invariants, that a downstream library quietly changed the default for. A mitigation is only as current as the assumptions underneath it.

Who is exposed

Any deployment running vLLM 0.10.2 through 0.11.0 that lets a caller reach the Completions endpoint with prompt-embedding input. In practice that includes internal inference platforms, multi-tenant model-serving setups where tenants share a vLLM instance, and any gateway that forwards embedding payloads to vLLM without validating them. If your serving layer trusts its callers because it is on a private network, this is precisely the class of bug that turns one compromised client, or one malicious tenant, into a memory-corruption primitive on the model host.

The fix

Upgrade to vLLM 0.11.1 or later. The patch (PR #27204) wraps the deserialization path in the torch.sparse.check_sparse_tensor_invariants context manager, restoring the integrity checks that PyTorch stopped applying by default and rejecting malformed sparse tensors before they reach to_dense().

If you cannot upgrade immediately, the compensating controls follow from the vector: put authentication in front of the Completions endpoint, do not expose it beyond the clients that genuinely need it, and treat prompt-embedding input as untrusted data rather than internal plumbing.

Why this sits in the inference-server class

The serving layer is the part of the AI stack most exposed to the network and least likely to be treated as an attack surface. It is framed as infrastructure, so it inherits the trust posture of infrastructure, while it actually parses attacker-influenced input on every request. CVE-2025-62164 is a clean example: a documented-safe deserialization call, defeated by a default change one dependency down, in the component everyone assumes is just plumbing.

Sources