Skip to content

GHSA-h3rc-j82p-2c3h CVE-2026-115915 PYSEC-2026-4346

vLLM: Untrusted EPS inputs can trigger denial of service or Ghostscript RCE

High PyPI
Severity
8.1 / 10
High · CVSS 3.1
Exploit chance (EPSS)
0.66%
Chance of exploitation in the next 30 days. Higher than 51.57% of scored vulnerabilities.
Known exploited
No
Not in CISA's catalog
Weakness
CWE-20 Improper Input Validation
CWE-183 Permissive List of Allowed Inputs
Fix
0.32.0
Upgrade vllm to this version or later

Description

Summary

In vLLM 0.30.0, ImageMediaIO passes attacker-controlled image bytes to Pillow's format autodetection without restricting the accepted formats; the request's MIME label does not constrain decoder selection. An EPS payload labeled image/png reached the host's Ghostscript executable. On a host with Ghostscript affected by CVE-2024-29510, this exposes the known Ghostscript sandbox escape through vLLM's image-loading path and can execute commands with the vLLM process's privileges. A bounded marker-command payload executed through the PyPI wheel's actual ImageMediaIO.load_base64() implementation using Debian Ghostscript 10.03.0. The loader-level execution is reproduced; the HTTP request path is source-traced but was not exercised end to end. This report concerns vLLM's untrusted-format dispatch and does not claim a new Ghostscript vulnerability. Exploitation requires an image-capable request path, a caller able to reach it under the deployment's authentication policy, and a vulnerable host Ghostscript build.

Details

ImageMediaIO is the boundary where attacker-controlled bytes enter Pillow's format autodetection: the declared MIME type does not constrain decoder selection, and the loader calls Image.open(BytesIO(data)) without a Pillow format allowlist. Pillow recognizes EPS by its file signature, and vLLM's subsequent image.load() call enters Pillow's EPS processing path. The OpenAI chat multimodal parser reaches this path through parse_image() and fetch_image() and the media connector; the data URL path extracts the MIME label and forwards the bytes to the loader (source). This is the vLLM-specific issue: untrusted image bytes can select a Pillow-supported format parser. Each downstream impact depends on the relevant parser, component version, and host configuration.

Pillow recognizes EPS by its file signature and invokes Ghostscript with -dSAFER, -sDEVICE=pnmraw, and the untrusted EPS input (Pillow EPS plugin, load path). The command execution in this report uses the already-known Ghostscript CVE-2024-29510, which allows crafted PostScript to bypass -dSAFER; Ghostscript lists 10.03.1 as the upstream fixed version (Ghostscript CVE details). This is an N-day dependency chain: CVE-2024-29510 provides the command-execution primitive, while the vLLM-specific issue is that untrusted, remotely supplied image bytes can reach the affected interpreter. No new Ghostscript flaw is claimed here.

The vLLM Python requirements declare Pillow but not Ghostscript, so this execution chain depends on a Ghostscript executable supplied by the host or deployment image. I reproduced command execution with the PyPI vllm==0.30.0 wheel, Pillow 12.3.0, and Debian amd64 Ghostscript 10.03.0~dfsg-1. The Codean Labs CVE-2024-29510 testkit identified that Ghostscript build as vulnerable. The adapted EPS payload ran only touch on a temporary marker. The marker existed after the loader call, although Pillow then raised ValueError because the exploit changes Ghostscript's output device. The API route was traced in source but a model-backed HTTP request was not run. Only PyPI vllm==0.30.0 was checked; no wider affected release range or other Ghostscript vendor build is claimed.

The same input boundary also exposes a separate Pillow-only denial-of-service condition when the installed Pillow version is 12.0.0–12.2.0. CVE-2026-59203 is triggered by a negative %%BeginBinary byte count and causes Pillow's EPS parser to loop during Image.open(); it does not invoke Ghostscript or provide code execution (Pillow advisory). The published vllm==0.30.0 requirements leave Pillow unpinned, so an existing environment can retain an affected Pillow version; the source at commit bc21cba9673cfc2256a2726b4bc32f062237cd35 requires pillow>=12.3.0. In an isolated local check with Pillow 12.2.0, the official sample hung through ImageMediaIO.load_bytes() and MediaConnector.fetch_image_async(). Eight concurrent image loads occupied the connector's eight media-loading threads and left a benign image load queued. Pillow 12.3.0 rejected the sample promptly. This confirms a conditional media-processing DoS path, separate from the Ghostscript RCE chain; full HTTP-server availability was not measured.

Impact

When a vLLM image-processing endpoint accepts attacker-supplied content and the host has Ghostscript affected by CVE-2024-29510, a caller who can reach the endpoint can trigger command execution as the vLLM process user. API-key authentication and network access controls determine who can reach the request path. Deployments without Ghostscript or with a build fixed for CVE-2024-29510 are not affected by this execution chain. Separately, existing environments that run vLLM 0.30.0 with Pillow 12.0.0–12.2.0 are exposed to CVE-2026-59203 through the same image-format dispatch boundary; the demonstrated impact is exhaustion of media-loading workers, and this Pillow CVE does not cause RCE. The report asks vLLM to assess and address the unsafe dispatch of untrusted image bytes and the affected dependency combinations.

This advisory was fixed in MR60022.

Affected versions

PyPI

PackageVulnerableFixed in
vllm
< 0.32.0
0.32.0
vllm
< 0.32.0
0.32.0
vllm
>= 0.30.0, < 0.32.0
0.32.0

How to fix

Move to the fixed version or later with your package manager, update the lockfile, and run your tests. If the package only arrives through another dependency, upgrade that dependency first. If none of its releases pulls a fixed version yet, force the version with your package manager's override.

vllm PyPI → 0.32.0

pip
pip install --upgrade "vllm>=0.32.0"
poetry
poetry add "vllm>=0.32.0"
uv
uv add "vllm>=0.32.0"

Severity breakdown

CVSS 3.1 8.1

CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H

Attack vector
Network
Attack complexity
High
Privileges required
None
User interaction
None
Scope
Unchanged
Confidentiality
High
Integrity
High
Availability
High

Weakness

CWE-20: Improper Input Validation

The product receives input or data, but it does not validate or incorrectly validates that the input has the properties that are required to process the data safely and correctly.

How to prevent it
  • Architecture and Design: Consider using language-theoretic security (LangSec) techniques that characterize inputs using a formal language and build "recognizers" for that language. This effectively requires parsing to be a distinct layer that effectively enforces a boundary between raw input and internal data representations, instead of allowing parser code to be scattered throughout the program, where it could be subject to errors or inconsistencies that create weaknesses. [REF-1109] [REF-1110] [REF-1111]
  • Architecture and Design: Use an input validation framework such as Struts or the OWASP ESAPI Validation API. Note that using a framework does not automatically address all input validation problems; be mindful of weaknesses that could arise from misusing the framework itself (CWE-1173).
  • Architecture and Design, Implementation: Understand all the potential areas where untrusted inputs can enter the product, including but not limited to: parameters or arguments, cookies, anything read from the network, environment variables, reverse DNS lookups, query results, request headers, URL components, e-mail, files, filenames, databases, and any external systems that provide data to the application. Remember that such inputs may be obtained indirectly through API calls.
  • Implementation: Assume all input is malicious. Use an "accept known good" input validation strategy, i.e., use a list of acceptable inputs that strictly conform to specifications. Reject any input that does not strictly conform to specifications, or transform it into something that does. When performing input validation, consider all potentially relevant properties, including length, type of input, the full range of acceptable values, missing or extra inputs, syntax, consistency across related fields, and conformance to business rules. As an example of business rule logic, "boat" may be syntactically valid because it only contains alphanumeric characters, but it is not valid if the input is only expected to contain colors such as "red" or "blue." Do not rely exclusively on looking for malicious or malformed inputs. This is likely to miss at least one undesirable input, especially if the code's environment changes. This can give attackers enough room to bypass the intended validation. However, denylists can be useful for detecting potential attacks or determining which inputs are so malformed that they should be rejected outright.
  • Architecture and Design: For any security checks that are performed on the client side, ensure that these checks are duplicated on the server side, in order to avoid CWE-602. Attackers can bypass the client-side checks by modifying values after the checks have been performed, or by changing the client to remove the client-side checks entirely. Then, these modified values would be submitted to the server. Even though client-side checks provide minimal benefits with respect to server-side security, they are still useful. First, they can support intrusion detection. If the server receives input that should have been rejected by the client, then it may be an indication of an attack. Second, client-side error-checking can provide helpful feedback to the user about the expectations for valid input. Third, there may be a reduction in server-side processing time for accidental input errors, although this is typically a small savings.
  • Implementation: When your application combines data from multiple sources, perform the validation after the sources have been combined. The individual data elements may pass the validation step but violate the intended restrictions after they have been combined.
  • Implementation: Be especially careful to validate all input when invoking code that crosses language boundaries, such as from an interpreted language to native code. This could create an unexpected interaction between the language boundaries. Ensure that you are not violating any of the expectations of the language with which you are interfacing. For example, even though Java may not be susceptible to buffer overflows, providing a large argument in a call to native code might trigger an overflow.
  • Implementation: Directly convert your input type into the expected data type, such as using a conversion function that translates a string into a number. After converting to the expected data type, ensure that the input's values fall within the expected range of allowable values and that multi-field consistencies are maintained.
  • Implementation: Inputs should be decoded and canonicalized to the application's current internal representation before being validated (CWE-180, CWE-181). Make sure that your application does not inadvertently decode the same input twice (CWE-174). Such errors could be used to bypass allowlist schemes by introducing dangerous inputs after they have been checked. Use libraries such as the OWASP ESAPI Canonicalization control. Consider performing repeated canonicalization until your input does not change any more. This will avoid double-decoding and similar scenarios, but it might inadvertently modify inputs that are allowed to contain properly-encoded dangerous content.
  • Implementation: When exchanging data between components, ensure that both components are using the same character encoding. Ensure that the proper encoding is applied at each interface. Explicitly set the encoding you are using whenever the protocol allows you to do so.

CWE-183: Permissive List of Allowed Inputs

The product implements a protection mechanism that relies on a list of inputs (or properties of inputs) that are explicitly allowed by policy because the inputs are assumed to be safe, but the list is too permissive - that is, it allows an input that is unsafe, leading to resultant weaknesses.

References

Timeline

  1. Published
  2. Last updated by the source
  3. Latest EPSS score
AdvisorySeverityWhy it's related
GHSA-8397-8qf6-f2gm
vLLM: Phi-4 multimodal audio encoder materializes and retains full attention matrices: a single max-length audio OOM-crashes the vLLM engine
Medium Also affects vllm
GHSA-x567-49g5-p4cf
vLLM: Responses API bypasses trust_request_chat_template for chat_template_kwargs
Medium Also affects vllm
GHSA-vvpg-rrww-wpmh
vLLM: Permissive default CORS origins allow cross-origin requests to the vLLM HTTP server
Medium Also affects vllm
GHSA-q97c-p368-75c4
vLLM: Out-of-vocabulary prompt token id passes input validation and triggers a CUDA device-side assert (engine crash / DoS)
Medium Also affects vllm
GHSA-gq5q-89c7-vhvx
vLLM DeepSeek-OCR image processing vulnerable to denial of service
Medium Also affects vllm
GHSA-6757-hggm-hp2w
vLLM: Public multimodal SHM handle forgery reaches worker-side `pickle.loads()` with insecure serialization disabled
High Also affects vllm
GHSA-542m-9234-8gvf
vLLM: DoS via unbounded chat_template Jinja2 rendering exhausts the renderer thread pool
Medium Also affects vllm
PYSEC-2026-4353
vLLM from 0.20.0 before 0.30.0 contains a denial of service vulnerability that allows remote attackers to crash the engine by sending inconsistent multimodal…
High Also affects vllm

Credits: LittlehamsterXu, jperezdealgaba

Is this in your code?

MergeHarbor checks every repository's dependencies against this database, ranks what matters by exploitability and reachability, routes it to the owning team and opens the fix pull request.

Check your repos with MergeHarbor