vLLM: Out-of-vocabulary prompt token id passes input validation and triggers a CUDA device-side assert (engine crash / DoS)
Impact
For a model whose vocabulary size is an exact multiple of the embedding padding size (64) — e.g. any Llama-2-family model, vocab 32000 — a single request carrying a pre-tokenized prompt with token id equal to the vocab size (32000) passes vLLM's input-id validation but is one past the last embedding row. At tensor-parallel size 1 the embedding lookup does not mask indices, so the id reaches F.embedding out of range and raises a CUDA device-side assert, which poisons the engine's CUDA context and takes the engine down. Any client that can send pre-tokenized input (/v1/completions with…
Source excerpt · OSVAffected packages
Start with the recorded fix for your release branch. Check your installed version and test compatibility before upgrading. Fixing this advisory does not rule out other vulnerabilities in the release.
| Affected range | Recorded fix |
|---|---|
| Earlier releases before 0.32.0Ecosystem versions | 0.32.0 |
Version evidence: OSV · GHSA-q97c-p368-75c4OSV · PYSEC-2026-4347
View original version evidence (198 explicit versions)
Affected products
Vendor version evidence. Product records are separate from automatic dependency matching.
vllm-project · GitHub_M
vllm
1 range
vllm-project · GitHub_M
vllm
Compare with this publisher’s ranges. This does not inspect your installation.
affected
< 0.32.0
Other versions: unknown
Original source description
For a model whose vocabulary size is an exact multiple of the embedding padding size (64) — e.g. any Llama-2-family model, vocab 32000 — a single request carrying a pre-tokenized prompt with token id equal to the vocab size (32000) passes vLLM's input-id validation but is one past the last embedding row. At tensor-parallel size 1 the embedding lookup does not mask indices, so the id reaches F.embedding out of range and raises a CUDA device-side assert, which poisons the engine's CUDA context and takes the engine down. Any client that can send pre-tokenized input (/v1/completions with prompt as token ids, /tokenize-fed flows, or the kv_transfer_params["prompt_token_ids"] reuse path) can trigger it.
Root cause
vllm/v1/engine/input_processor.py accepts a token id when id <= max(tokenizer.max_token_id, model_config.get_vocab_size() - 1).
vllm/tokenizers/hf.py computes max_token_id = max(max(vocab.values()), tokenizer.vocab_size). For Llama-2 tokenizers max(vocab.values()) = 31999 but tokenizer.vocab_size = 32000, so max_token_id = 32000 — one greater than the largest valid id.
The engine bound therefore becomes max(32000, 31999) = 32000, and id 32000 is accepted.
The model's embedding has pad_vocab_size(32000, 64) = 32000 rows (no padding), valid indices 0..31999. At VocabParallelEmbedding.forward with tp_size == 1 there is no masking, so index 32000 hits F.embedding out of range.
Affected
- tp=1 (single GPU per model — common per-copy layout). tp>1 masks via
get_masked_input_and_mask, so the id is clamped, not an OOB — likely wrong output rather than a crash. - Models whose vocab is a multiple of 64 with
tokenizer.vocab_sizeone past the max real id (Llama-2 family, vocab 32000, is the clear case). Qwen2.5 is NOT affected (padded headroom).
Suggested fix
max_token_id in vllm/tokenizers/hf.py now uses tokenizer.vocab_size - 1, so an id equal to the vocabulary size fails input validation instead of reaching the embedding. Fixed in MR59491, released in v0.32.0.
Reporter
Shijie Lyu (GitHub shijie-lyu lshjhf@gmail.com). Reported privately per SECURITY.
This advisory was fixed in MR59491.
Inside the record
Evidence available
Describes the evidence in this view, not whether the product is safe.
Original records
CVE-2026-115916View the latest unmodified CVE JSON from the official source. It may be newer than this imported page.
cve.new JSON →Underlying weaknesses
The source’s classification of what caused the vulnerability.
Contributing organizations · 1
Assigning organization
What changed
Follow changesLarge field values are marked as truncated previews. Original source snapshots remain retained.