vllm: V1 InputBatch.condense leaves a stale allowed_token_ids mask on recycled batch rows
What fixes it
No source in this snapshot names a fixed version.
Description
Severity
- Severity: Low
- CVSS v3.1:
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:L/A:N(3.7, Low) - CWE: CWE-440 (Expected Behavior Violation), CWE-668 (Exposure of Resource to Wrong Sphere)
Summary
vLLM V1 InputBatch.condense() can leave a stale allowed_token_ids_mask_cpu_tensor row after moving a constrained request. A later unrestricted request that reuses that batch slot inherits the previous request's token allowlist, so sampling for that other client is constrained by a mask it did not set (cross-request output-integrity issue). The victim request still returns HTTP 200 with no error indication.
Public report: https://github.com/vllm-project/vllm/issues/43894
Affected
- Ecosystem / package: pip /
vllm - Affected versions: vLLM ≤ 0.30.0 (V1 worker
InputBatchpath). Confirmed via public issue #43894. - Fixed versions: Fix merged in https://github.com/vllm-project/vllm/pull/43931 (not yet in a tagged release as of v0.30.0; expected in the next release).
Details
InputBatch.condense() copies allowed_token_ids_mask_cpu_tensor from a moved request's row into the freed index but never clears the source row. add_request() only writes that row when the new request sets sampling_params.allowed_token_ids. When another active request still has allowed_token_ids, _make_sampling_metadata() copies the active prefix of the CPU mask to GPU and Sampler.apply_logits_processors() applies the stale whitelist to the unrestricted request.
An attacker who can submit generate traffic (including unauthenticated /invocations, which is outside --api-key guards, or any valid API key on /v1) plants a chosen allowed_token_ids mask. If batching/condense recycles that row onto another client's unrestricted request while the constrained request is still active, the victim's tokens are limited to the attacker's allowlist (for example only a single token, only digit tokens, or only tokens that spell a short phrase). This is vocabulary steering / wrong allowlist application, not free-form substitution of arbitrary attacker text.
A related but distinct bug in InputBatch.swap_states() (row-view aliasing of the same mask tensor) was fixed in https://github.com/vllm-project/vllm/pull/48419.
Impact
Limited cross-request sampling integrity on a shared engine: one client's allowed_token_ids can constrain another client's outputs under concurrent batching. Confidentiality and availability are unaffected. Attack complexity is High because exploitation needs concurrent requests plus a condense slot-reuse race while the attacker's constrained request remains in the batch.
Patches
- https://github.com/vllm-project/vllm/pull/43931 — clear vacated
allowed_token_idsmask rows incondense() - https://github.com/vllm-project/vllm/pull/48419 — related
swap_statesmask aliasing fix
References
- https://github.com/vllm-project/vllm/issues/43894
- https://github.com/vllm-project/vllm/pull/43931
- https://github.com/vllm-project/vllm/pull/48419
- https://docs.vllm.ai/en/latest/usage/security.html (API key does not cover
/invocations)
Credit
Reported publicly by @glaziermag in issue #43894.
Text from GitHub Advisory Database
Affected versions 1
- vllm, pip< 0.31.0GitHub