All vulnerabilities
GHSA-4xqp-c3mv-qff7

An oversized min_tokens in one request hangs the vLLM engine while /health stays green

vllm
CVSS
6.5Medium
ExploitationNo known exploitationNot in CISA KEV, which does not prove it is unexploitedCISA KEV
Exploit odds (EPSS)No scoreNo FIRST EPSS score in this snapshot yet
Fixed inNone listedNo source names a fixed version yet
Published6 Oct 2026Updated 6 Oct 2026GitHub

What fixes it

No source in this snapshot names a fixed version.

Description

Summary

Any client that can reach /inference/v1/generate, mounted by default in v0.29.0 and unauthenticated unless --api-key is set, can stop vllm serve from serving with one request. The body sets sampling_params.max_tokens to null and min_tokens to 2147483648. The EngineCore, the single scheduler process, re-validates it in its input thread, which dies; the process stays up, /health answers 200, every later request hangs.

Root cause

The min_tokens <= max_tokens check runs in [_verify_args](https://github.com/vllm-project/vllm/blob/c1b69aa0d49b88016b5b2156ae61649c2c2df282/vllm/sampling_params.py#L616-L620) only when max_tokens is set. On /inference/v1/generate the API process builds SamplingParams directly from the JSON with max_tokens=None, so the check is skipped; the processor then [fills in max_tokens](https://github.com/vllm-project/vllm/blob/c1b69aa0d49b88016b5b2156ae61649c2c2df282/vllm/v1/engine/input_processor.py#L358-L362) (2045 here) without validating again and forwards the request.

In the EngineCore, [process_input_sockets](https://github.com/vllm-project/vllm/blob/c1b69aa0d49b88016b5b2156ae61649c2c2df282/vllm/v1/engine/core.py#L1757) decodes the message, which rebuilds SamplingParams and runs _verify_args a second time. Now both values are present and VLLMValidationError is raised on the decode line, one line above the try that protects request handling:

1757                        req: EngineCoreRequest = add_request_decoder.decode(data_frames)  # <-
1758                        try:
1759                            request = self.preprocess_add_request(req)
...
1765                        except Exception:
1766                            self._handle_request_preproc_error(req)
1767                            continue

The exception is not caught, so the thread exits. It was the only reader of the input socket: no request reaches the scheduler any more, but nothing reports it, because the scheduler loop just waits on an empty queue, the thread is checked only at start-up, and [check_health](https://github.com/vllm-project/vllm/blob/c1b69aa0d49b88016b5b2156ae61649c2c2df282/vllm/v1/engine/async_llm.py#L1025-L1028) only looks for a recorded error. /health keeps answering 200 while every generation request hangs.

The OpenAI routes resolve max_tokens before building SamplingParams, so there the check runs in the API process and returns HTTP 400.

Impact

  • Who can trigger it — Any network client, no credentials, that can reach /inference/v1/generate: mounted by default on a vllm serve of v0.29.0, and on main when VLLM_ENABLE_SCALE_OUT_ENDPOINTS=1 or --tokens-only is set.
  • What they get — One 92-byte request stops the server from serving any route for every client; later requests hang until the client gives up. The process stays alive and /health keeps answering 200, so nothing restarts it. Recovery is a manual restart.

--- The initial discovery was made by AI scanning tools in Microsoft Security FORGE Labs, and later all technical claims has been reviewed and validated by human experts.

A public fix is available here: https://github.com/vllm-project/vllm/pull/57731

Text from GitHub Advisory Database

Affected versions 1

  • vllm, pip< 0.31.0GitHub