VulnWatch VulnWatch
← Back to dashboard
Unknown osv · GHSA-hgg8-fqqc-vfmw

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

Published Jun 17, 2026

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 () 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):

# File Line Code
1 vllm/entrypoints/anthropic/api_router.py 78 message=str(e), (inside POST /v1/messages exception handler)
2 vllm/entrypoints/anthropic/api_router.py 124 message=str(e), (inside POST /v1/messages/count_tokens)
3 vllm/entrypoints/anthropic/serving.py 808 error=AnthropicError(type="internal_error", message=str(e)), (SSE streaming converter)
4 vllm/entrypoints/speech_to_text/realtime/connection.py 75 await self.send_error(str(e), "processing_error") (WebSocket event loop)
5 vllm/entrypoints/speech_to_text/realtime/connection.py 265 await 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),       #

Affected AI Products

vllm
Get the weekly digest. Every Monday: top AI security stories of the week. Free.