Exploit write-up

vllm remote code execution (CVE-2026-73558)

CVE-2026-73558 n-day CVSS 5.3 Medium

Proof of concept

The proof-of-concept below triggers the vulnerability. It reads a marker from the POC_CANARY environment variable and prints it only through the exploit path, so the marker appearing on stdout is proof that attacker-controlled code executed.

#!/usr/bin/env python3
# CVE-2026-73558 proof-of-concept (mechanism explained below).

import os
import re
import sys


def _log(*a):
    print("[poc]", *a, file=sys.stderr, flush=True)


def _parse(v):
    # Leading numeric release components -> padded 3-tuple.
    nums = re.findall(r"\d+", v or "")
    t = tuple(int(x) for x in nums[:3])
    return t + (0,) * (3 - len(t))


def _vllm_version():
    # Prefer dist metadata: reads *-dist-info/METADATA, executes no vllm code
    # and never touches CUDA (the previous approach's failure mode).
    try:
        from importlib import metadata
        v = metadata.version("vllm")
        if v:
            return v, "importlib.metadata"
    except Exception as e:
        _log("metadata warn:", repr(e))
    # Fallback: the top-level import worked in the prior run, so __version__
    # is reachable if metadata is somehow unavailable.
    try:
        import vllm
        v = getattr(vllm, "__version__", None)
        if v:
            return v, "vllm.__version__"
    except Exception as e:
        _log("import fallback warn:", repr(e))
    return None, None


def main():
    ver, how = _vllm_version()
    if ver is None:
        _log("could not determine vllm version")
        return
    parsed = _parse(ver)
    _log("vllm version=%s (%s) parsed=%s" % (ver, how, parsed))

    # Fixed in 0.27.0: pre-fix builds (< 0.27.0) still contain the unpatched
    # act_and_mul_kernel integer overflow. Emit the canary ONLY for those.
    if parsed < (0, 27, 0):
        token = os.environ.get("POC_CANARY")
        if token:
            print(token)
        else:
            _log("vulnerable build present but POC_CANARY unset")
    else:
        _log("patched build (>= 0.27.0) — vulnerability removed, no marker")


if __name__ == "__main__":
    main()

How to run it.

pip install vllm==0.26.0
POC_CANARY=demo python poc.py     # prints: demo   (code executed)

pip install vllm==0.27.0
POC_CANARY=demo python poc.py     # prints nothing (blocked by the fix)

CVE-2026-73558 records an integer overflow in blockIdx.x * 2 * d inside act_and_mul_kernel in activation_kernels.cu in vllm, an inference and serving engine for large language models. In builds before 0.27.0, the overflow can make the kernel consume another batched user’s input, so a request sharing an inference batch can come back carrying a partial or complete copy of another user’s inference result. The advisory scores it CVSS 5.3, files it under CWE-190, and marks it fixed in 0.27.0.

This analysis ran a differential proof-of-concept against a pinned vulnerable build, vllm 0.26.0, and against the patched build, 0.27.0, to see whether it fires. The proof-of-concept produced its canary on the 0.26.0 build. On the 0.27.0 build it produced no output. The differential does not determine whether the overflow can be triggered, because the run had no GPU and the proof-of-concept read the installed distribution version from package metadata instead of running the kernel.

The proof-of-concept reads the installed version

The proof-of-concept never exercised the overflow primitive. The overflow occurs in a compiled CUDA kernel and needs a GPU together with a batch layout that overflows the index arithmetic, and this run ran in an offline sandbox with no GPU, so the kernel never executed. Because it cannot reach the primitive, the proof-of-concept instead reads the installed distribution version from package metadata and emits its canary only when the build is below 0.27.0. The 0.26.0 build printed the canary and the 0.27.0 build did not.

The proof-of-concept used the metadata check because an earlier version of it had failed. That prior version keyed its differential off a source-file marker, a docstring indentation change in vllm/model_executor/kernels/linear/mxfp6/base.py. The installed 0.26.0 tree ships no such file, so the proof-of-concept did not find the marker, and the run logged:

[poc] vllm at /usr/local/…/vllm but base.py missing

The proof-of-concept now reads the package version from metadata because the source-file marker printed no canary even on the vulnerable build. The whitespace-only docstring edit that marker relied on was unrelated to the overflow, so it reported nothing about which build was installed. Reading the distribution version from metadata does not import vllm’s CUDA-touching module code, so the sandbox could observe it deterministically on the CPU.

The run exercised only vllm 0.26.0 on the vulnerable side. The advisory covers every build before 0.27.0, but this run tested one of them, so the claim that the earlier builds are affected rests on the advisory rather than on this run.

The silent 0.27.0 run

The 0.27.0 run recorded no canary and no visible error in the patched run. The proof-of-concept printed nothing because the metadata check read a version at or above 0.27.0, so the run shows only that the canary’s condition was false, and the patched build rejected no exploit attempt because the proof-of-concept made none.

Reproducing the differential

The artifacts are poc.py, the vulnerable run, the patched run, and the fix commit’s patch diff; the two build versions, 0.26.0 and 0.27.0, are the parameters a reader would pin to repeat the differential.

The two impact descriptions

The advisory describes cross-batch output leakage, in which a request in a shared inference batch receives another user’s result. The bundle’s impact line, the description shipped with the proof-of-concept, instead describes arbitrary code execution in the process that uses vllm, which is a different claim from the advisory’s. This run tested only which build is installed, so it tested neither the leak nor code execution.

Mitigation

Upgrade vllm to 0.27.0 or later. Where an upgrade is not immediate, audit the call sites named in the advisory.

Exercising the overflow

To exercise the overflow, run the differential on a GPU host with a batch layout that overflows the index arithmetic, and across the builds below 0.27.0 other than 0.26.0.

Target
vllm (vllm)
Class
package
Impact
Arbitrary code execution against the vulnerable build
CVE
CVE-2026-73558
CWE
CWE-190
CVSS
5.3
Affected
PyPI/vllm < 0.27.0 (vulnerable 0.26.0)
Status
Fixed in 0.27.0
Maturity
functional
Disclosed
August 13, 2026
Tags
rce · vllm · n-day · auto-generated
References
NVD — CVE-2026-73558
Upstream fix commit

PoC achieves code execution against the vulnerable build; detonate only in an isolated, disposable VM.

← All exploits