system: OPERATIONAL
← back to all hacks
INFRASTRUCTURE MEDIUM NEW

An incomplete patch: memory-address leaks return in vLLM's newer API routes

The fix for vLLM's critical image-parsing flaw sanitized the OpenAI router — but routes added weeks later re-echo raw exception text, leaking heap addresses and reopening an ASLR-bypass primitive.

2026-07-17 // 6 min affects: vllm, vllm-<=0.22.0, anthropic-api-router, speech-to-text-realtime, multimodal-endpoints

What is this?

On June 11, 2026, the vLLM project published a security advisory (GHSA-hgg8-fqqc-vfmw) reported by researcher Kai Aizen (SnailSploit). It documents an incomplete fix: the patch that closed an earlier critical image-parsing flaw in vLLM’s OpenAI-compatible router did not extend to routes added shortly afterward, so those newer endpoints still leak internal memory addresses to remote callers.

The earlier flaw was severe — a critical (CVSS 9.8) vulnerability that chained a memory-address leak with an image-library heap overflow to reach remote code execution. Its fix introduced a sanitizer that strips object-representation addresses out of error messages before they reach clients. This follow-up finding is scored medium (CVSS 3.1 base 5.3), with low confidentiality impact and no integrity or availability impact. The weakness class is CWE-532, insertion of sensitive information into an error message — the same class as the parent issue. The affected code is present in vLLM versions up to and including 0.22.0.

How it works

When vLLM parses a malformed image, the imaging library raises an error whose text contains the in-memory representation of the buffer object — something like cannot identify image file <_io.BytesIO object at 0x7a95e299e750>. That trailing hex value is a live heap address. If it reaches the client verbatim, an attacker learns where objects sit in the process’s address space, collapsing ASLR entropy from roughly four billion possibilities to a handful — exactly the reconnaissance step the earlier critical chain relied on.

The parent fix added a sanitize_message helper and wired it into the OpenAI router’s exception handlers, rewriting <_io.BytesIO object at 0x...> down to <_io.BytesIO object>. The problem is that several response paths added at or after the same time never call it. The advisory lists five such sites: the Anthropic-compatible messages endpoint, its token-counting endpoint, the server-sent-events streaming converter, and two error paths in the realtime speech-to-text WebSocket. Each returns str(exception) directly to the caller.

A natural question is why vLLM’s global, sanitizing exception handler doesn’t catch these. The answer is a subtle framework detail worth internalizing: a global exception handler only fires on unhandled exceptions that propagate out of a route. Each affected HTTP route instead catches the exception inside the route function and builds its own response, so the sanitizing handler is never invoked. The WebSocket paths bypass it for a different reason — WebSocket frames don’t traverse the HTTP exception-handler chain at all. The same malformed-image trigger that fed the parent issue reaches all of these newer routes unchanged.

The advisory is explicit that this is not stale legacy code but a series of scope misses: the sanitizer landed on January 9, 2026; the Anthropic router was added six days later without it, the token-counting endpoint about two months after that, and the speech-to-text paths in May — each replicating the unsanitized pattern.

Why it matters

On its own, an address leak changes nothing a user can see. Its value is as a building block. The parent chain needed exactly this primitive to defeat ASLR before triggering memory corruption. That second stage — a heap overflow in an older image codec — is fixed in current library versions, so on a fully updated stack this finding is an information-disclosure primitive rather than a path to code execution. But vLLM is frequently shipped inside custom Docker images, downstream rebuilds, and long-lived LTS distributions that pin older system libraries. On any deployment still carrying a vulnerable image codec, these newer endpoints quietly re-enable the full leak-then-corrupt chain the original patch was meant to close.

The broader lesson is about how fixes decay. A patch applied at specific call sites protects only those call sites. As new routes, transports, and endpoints are added, they reintroduce the very pattern the fix was meant to eliminate — unless the mitigation lives at a chokepoint every response must pass through.

Defenses

The definitive fix is to upgrade to a vLLM build that includes the remediation merged in the project’s fix pull request. Beyond upgrading, the advisory’s guidance generalizes well and aligns with OWASP’s Sensitive Information Disclosure guidance:

  1. Sanitize error output symmetrically. Every path that returns exception text to a client — HTTP routes, streaming converters, and WebSocket handlers alike — must scrub object reprs and raw addresses. A fix on one router is not a fix everywhere.
  2. Move the mitigation to a chokepoint. Route-local try/except blocks and WebSocket handlers bypass framework-level exception handlers. A response middleware that scrubs every outgoing error body prevents this whole class of regression, so a newly added route can’t silently reopen the leak.
  3. Broaden the scrubbing pattern. A regex that matches only the exact lowercase CPython address suffix is brittle; future runtimes, C extensions, or custom __repr__ methods can produce non-matching formats. Strip any standalone hex address rather than one specific shape.
  4. Never return raw internal errors to untrusted callers. Log the detailed exception server-side; return a generic, opaque error to the client. Address leaks, stack traces, and file paths are all reconnaissance.
  5. Treat incomplete-fix follow-ups as first-class. When a critical bug is patched, audit every sibling and newly added path for the same sink before closing the book on it.

Status

ItemReferenceDateNotes
Follow-up advisory publishedGHSA-hgg8-fqqc-vfmw2026-06-11Info disclosure (CWE-532); CVSS 5.3 medium; no CVE assigned
Parent vulnerabilityCVE-2026-22778 / GHSA-4r2x-xpjr-7cvv2026Critical (CVSS 9.8); leak chained to heap overflow for RCE
Sanitizer introducedvLLM PR #319872026-01-09Applied only to OpenAI router exception handlers
Affected versionsvLLM ≤ 0.22.0Anthropic router, count-tokens, SSE converter, speech-to-text WebSocket
FixvLLM PR #451192026Applies sanitization to the missed sites

The takeaway is an old maxim in a new setting: a patch is only as complete as the surface it covers. Sanitize error output at a single point every response flows through, keep raw internal state out of client-facing messages, and when you fix a critical bug, hunt down every route that shares its sink before declaring it closed.

Details here are drawn from the vLLM security advisory and the referenced pull requests. No proof-of-concept payload is reproduced; defenders should consult the linked advisory for exposure assessment.

Sources