Your RSA-2048 keys break in 2030. Find every one of them before attackers do.
🐍
🐍 PyPI
Not in CISA KEV
MEDIUM severity

CVE-2026-54236 — vllm

MEDIUMFix: vllm-project/vllm@9492362

CVE-2026-54236 is a medium-severity (CVSS 5.3) CWE-532 vulnerability in vllm. A fix is available for vllm — see the affected versions and patch details below.

vLLM: incomplete CVE-2026-22778 fix leaks PIL repr addresses via Anthropic router

Also known asGHSA-hgg8-fqqc-vfmwPYSEC-2026-3408
Published
Updated
Affected
1 pkg
Patched
1 / 1
Exploits
None indexed
Exploitation data as of Oct 24, 2026 · OSV.dev, NVD, FIRST.org (EPSS)

Exploitation Status

Proof-of-concept exploit code exists

  • CISA’s SSVC triage found public proof-of-concept exploit code for this CVE, though no confirmed active exploitation.
  • CISA assesses this as automatable — exploitation doesn’t require manual, per-target effort, which raises the odds of mass scanning and opportunistic attacks.

Exploitation and automatability from CISA’s SSVC triage for CVE-2026-54236.

EPSS Exploitation Probability

via FIRST.org ↗
0.9%probability of exploitation in next 30 days
Lower Risk0.00%
Lower risk than most CVEs60th percentile — riskier than 60% of all scored CVEsHighest risk
0.30%0.67%1.05%1.43%0.8%0.8%0.9%0.9%0.9%Jul 26Sep 26Oct 26

Probability of exploitation in the next 30 days, from FIRST.org EPSS.

How urgent is this, really

CVE-2026-54236 by exploitation likelihood (EPSS) against impact (CVSS). Outside the shaded patch-first corner.

Where this sits among everything scored

Of 395,249 CVEs with a current EPSS score, this one falls in the < 10% band (highlighted). Counts from FIRST.org, log-scaled.

Real-World Exposure

1 pkg affected
🐍vllm

Real-time download stats are indexed for npm and PyPI packages. This vulnerability affects PyPI packages — download data is not available via public APIs for these ecosystems.

Description

vLLM: incomplete CVE-2026-22778 fix leaks PIL repr addresses via the Anthropic API router

Researcher: Kai Aizen — SnailSploit (@SnailSploit), Adversarial & Offensive Security Research Severity: CVSS 3.1 5.3 (Medium) AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N Target: https://github.com/vllm-project/vllm


Summary

The fix for CVE-2026-22778 / GHSA-4r2x-xpjr-7cvv (PRs #31987 and #32319) introduced sanitize_message and applied it at four FastAPI exception-handling sites in the OpenAI router. The sanitizer strips object-repr memory addresses (<_io.BytesIO object at 0x7a95e299e750> → <_io.BytesIO object>) before error messages reach the client, defeating the ASLR-bypass primitive that CVE-2026-22778 chained with a libopenjp2 heap overflow for RCE.

The fix is incomplete: response paths added to vLLM at or after the same time as the fix continue to echo str(exc) directly to clients without sanitize_message. The original Stage 1 primitive — sending malformed image bytes so PIL raises UnidentifiedImageError whose message contains the BytesIO object repr — reaches all of them unmodified and leaks the heap address verbatim in the response body.

All five lines below are present in main HEAD (771e1e48b, 2026-05-26).

Affected sites

Current main HEAD (771e1e48b, 2026-05-26):

#FileLineCode
1vllm/entrypoints/anthropic/api_router.py78message=str(e), (inside POST /v1/messages exception handler)
2vllm/entrypoints/anthropic/api_router.py124message=str(e), (inside POST /v1/messages/count_tokens)
3vllm/entrypoints/anthropic/serving.py808error=AnthropicError(type="internal_error", message=str(e)), (SSE streaming converter)
4vllm/entrypoints/speech_to_text/realtime/connection.py75await self.send_error(str(e), "processing_error") (WebSocket event loop)
5vllm/entrypoints/speech_to_text/realtime/connection.py265await self.send_error(str(e), "processing_error") (WebSocket generation loop)

Why the global exception handler does not save these paths

api_server.py registers a catch-all app.exception_handler(Exception)(exception_handler) at line 262, and that handler calls create_error_response(exc) which DOES apply sanitize_message. However, FastAPI exception handlers fire only on unhandled exceptions that propagate out of a route function.

All affected HTTP paths catch Exception inside the route coroutine and construct the response themselves:

# vllm/entrypoints/anthropic/api_router.py:71-81 (POST /v1/messages)
try:
    generator = await handler.create_messages(request, raw_request)
except Exception as e:
    logger.exception("Error in create_messages: %s", e)
    return JSONResponse(
        status_code=HTTPStatus.INTERNAL_SERVER_ERROR.value,
        content=AnthropicErrorResponse(
            error=AnthropicError(
                type="internal_error",
                message=str(e),       # <-- unsanitized
            )
        ).model_dump(),
    )

Because the exception is caught and a JSONResponse is returned in-route, every registered FastAPI exception handler — including the sanitizing global one — is bypassed. The WebSocket path bypasses it for a different reason: WebSocket frames don't traverse FastAPI's HTTP exception handler chain at all.

Reachability — the same primitive as the parent CVE

The Anthropic Messages API accepts image content parts in the request body (type: "image" with base64 source.data or type: "image_url"). Image bytes are passed to the same multimodal loader used by the OpenAI router. Malformed bytes cause PIL.Image.open to raise:

UnidentifiedImageError: cannot identify image file <_io.BytesIO object at 0x7a95e299e750>

The exception propagates up through handler.create_messages into the except Exception as e: at api_router.py:75. str(e) returns the exception message verbatim, including the address. The address ends up in the error.message field of the JSON response body returned to the attacker. ASLR entropy on the affected process drops from ~4 billion to ~8 candidates, identically to CVE-2026-22778 Stage 1.

The same primitive is reachable on POST /v1/messages/count_tokens (route #2), inside the SSE streaming converter when an exception is raised mid-stream (route #3), and over the realtime speech-to-text WebSocket when audio decoder or generation paths raise an exception containing any object repr (routes #4, #5).

Chronology — these are scope misses, not legacy code

  • 2026-01-09: PR #31987 (aa125ecf0) introduces sanitize_message and applies it to OpenAI router HTTP exception handlers.
  • 2026-01-15 (six days later): PR #32369 (4c1c501a7) adds vllm/entrypoints/anthropic/api_router.py containing line 78's message=str(e). The fix was not applied to the new router.
  • 2026-03-02 (~two months later): PR #35588 (9a87b0578) adds the Anthropic count_tokens endpoint, replicating the same message=str(e) pattern at line 124.
  • 2026-05-12 (~four months later): PR #42370 (d37e25ffb) consolidates speech-to-text entrypoints and the realtime WebSocket uses send_error(str(e), ...) for both error paths.
  • 2026-05-26: current main HEAD, all five lines still present.

CVSS v3.1

AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N — Base 5.3 (MEDIUM)

The parent CVE-2026-22778 was 9.8 (CRITICAL) because it chained the Stage 1 leak with a Stage 2 libopenjp2 heap overflow. Stage 2 is patched in OpenCV ≥ 4.13.0 (PR #32668 bumped the requirement), so Stage 1 alone here is a partial ASLR-bypass info-disclosure primitive rather than a complete RCE. Deployments that ship vLLM alongside an older OpenCV/libopenjp2 (system OpenCV on long-LTS distros, custom Docker images, downstream rebuilds) re-enable the full chain via the affected endpoints.

CWE

CWE-532 (Insertion of Sensitive Information into Log File / Error Message). Same CWE assigned to the parent CVE-2026-22778.

Remediation

1. Apply sanitize_message symmetrically to the five sites

# vllm/entrypoints/anthropic/api_router.py — add at top:
from vllm.entrypoints.utils import sanitize_message

# Line 78 (POST /v1/messages) and Line 124 (count_tokens):
message=sanitize_message(str(e)),
# vllm/entrypoints/anthropic/serving.py — add at top:
from vllm.entrypoints.utils import sanitize_message

# Line 808:
error=AnthropicError(type="internal_error", message=sanitize_message(str(e))),
# vllm/entrypoints/speech_to_text/realtime/connection.py — add at top:
from vllm.entrypoints.utils import sanitize_message

# Lines 75 and 265:
await self.send_error(sanitize_message(str(e)), "processing_error")

2. Tighten the regex (defense in depth)

The current regex r" at 0x[0-9a-f]+>" is narrow — it only matches the exact CPython builtin object-repr suffix in lowercase hex with a trailing >. Future Python versions, C extensions, or custom __repr__ methods could produce non-matching formats that re-enable the leak:

# vllm/entrypoints/utils.py
def sanitize_message(message: str) -> str:
    # Strip any standalone hex address; downstream observers don't need them.
    return re.sub(r"\b0x[0-9a-fA-F]{6,}\b", "0x?", message)

3. Future-proofing: consider a response middleware

Both the route-local exception handling pattern (Anthropic router) and the WebSocket path bypass FastAPI's exception handler chain. A response-level middleware that always invokes sanitize_message on outgoing error bodies would prevent this class of regression entirely.

Affected versions

  • All vLLM versions containing vllm/entrypoints/anthropic/api_router.py (introduced 2026-01-15 in PR #32369).
  • All vLLM versions containing vllm/entrypoints/speech_to_text/realtime/connection.py (introduced 2026-05-12 in PR #42370).
  • Confirmed present in main HEAD 771e1e48b (2026-05-26).

References

Steps to reproduce

  1. Clone the target: git clone --depth 1 https://github.com/vllm-project/vllm
  2. Run the proof of concept (PoC.py) against the cloned source.
  3. Observe the result shown under Verified result below.

Credit

Kai Aizen — SnailSploit (@SnailSploit). Adversarial & Offensive Security Research.

Fix

A fix for this vulnerability was added here: https://github.com/vllm-project/vllm/pull/45119

Affected Packages

1 total 1 fixed
EcosystemPackageVulnerable rangeFix
🐍PyPIvllmall versions0.24.0pip install --upgrade 'vllm==0.24.0'

Affected Products

1 product · 1 configurations
Application
vllmvllm
< 0.23.1
range

Detection & mitigation playbook

Open-source dependency
  1. Detect

    Scan your dependency tree (package-lock.json, pnpm-lock.yaml, requirements.txt, go.sum, etc.) for vllm, including transitive dependencies — a direct dependency you never call can still pull in a vulnerable version.

  2. Fix

    Update vllm to 0.24.0 or later, then make sure no transitive (indirect) dependency still pins the vulnerable range — O3 confirms CVE-2026-54236 is resolved across your whole dependency graph.

  3. Workarounds

    Stop feeding it untrusted input: reject or quarantine files and payloads from unverified sources until you can upgrade, restrict accepted formats to the ones you actually need, and run the parsing or decoding step in a least-privileged sandbox or short-lived worker so a crash or corrupted read cannot reach the rest of the process.

How to detect CVE-2026-54236

A community-maintained Nuclei template exists for this CVE. You can scan for it directly:

nuclei -id cve-2026-54236 -u https://target
Template
vLLM <= 0.23.0 - Anthropic Router Heap Address Information Leak
Severity
medium
Impact
Remote attackers can leak heap addresses, significantly reducing ASLR effectiveness and enabling further exploitation like remote code execution.
Remediation
Update to vllm version to latest.

Template by ProjectDiscovery nuclei-templates (kenlacroix), MIT licensed. View the full template. Scan only systems you are authorised to test.

Fixing This On Your OS

If you run this on a Linux distribution, patch through your package manager against the distro's own security advisory below — it tracks the exact backported fix for your release, which can ship on a different timeline (and sometimes a different severity) than the upstream project.

Red HatModerate

This Moderate impact information disclosure flaw in vLLM does not affect Red Hat products. The vulnerable code responsible for incomplete error message sanitization, which could leak heap memory addresses via specially crafted image bytes sent to the Anthropic Messages API, is not present in Red Hat's supported…

Workaround published by Red Hat
Mitigation for this issue is either not available or the currently available options do not meet the Red Hat Product Security criteria comprising ease of use and deployment, applicability to widespread installation base, or stability.
Source: Red Hat security advisory for CVE-2026-54236 (CC BY 4.0)

Frequently Asked Questions

# vLLM: incomplete CVE-2026-22778 fix leaks PIL repr addresses via the Anthropic API router **Researcher:** Kai Aizen — SnailSploit (@SnailSploit), Adversarial & Offensive Security Research **Severity:** CVSS 3.1 5.3 (Medium) `AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N` **Target:** https://github.com/vllm-project/vllm --- ## Summary The fix for CVE-2026-22778 / GHSA-4r2x-xpjr-7cvv (PRs #31987 and #32319) introduced `sanitize_message` and applied it at four FastAPI exception-handling sites in the OpenAI router. The sanitizer strips object-repr memory addresses (`<_io.BytesIO object at 0x7a95e299e
O3 Security · Impact-Aware SCA

Is CVE-2026-54236 in your dependencies?

Find it across PyPI, including transitive dependencies.

CVE-2026-54236: vllm RCE — Fixed in 0.24.0