Exploit write-up
vllm remote code execution (CVE-2026-73558)
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.