-Infinity
0

Vendor Risk Score

See how vllm compares to other vendors in security performance

View Risk Score →
Severity
6.9
AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N

vLLM from 0.14.0rc1 before 0.31.0 contains an information disclosure vulnerability in sanitizemessage() whose lowercase-only regex fails to scrub uppercase PIL image addresses. Unauthenticated attackers can send a crafted PNG to endpoints such as /tokenize, triggering HF-processor errors that leak live server heap addresses useful for ASLR bypass.

First published (updated )
Severity
8.7
AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H

vLLM from 0.10.1 before 0.31.0 forwards a request-controlled mmprocessorkwargs.maxpatches value to the Hugging Face processor for Cohere2 Vision models without a server-side upper bound, causing quadratic CPU work during multimodal preprocessing. Remote clients can send small image chat-completion requests with large, varying maxpatches values to bypass the LRU cache, exhaust preprocessing workers, and deny service to other clients.

First published (updated )
Severity
6.9
AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L

vLLM from 0.24.0 before 0.31.0 contains a resource exhaustion vulnerability in the MiniMax M3 VL video processor, which accepts request-level minpixels without range or minpixels <= maxpixels validation. Its video-wide pixel budget is enforced only when maxlongsidepixel is set, and that value defaults to None. API clients can supply a large minpixels via mmprocessorkwargs to enlarge every decoded frame, causing excessive CPU and host-memory consumption that may disrupt workers or the service.

First published (updated )
Severity
8.2
AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:H

vLLM from 0.28.0 before 0.30.0 contains a reachable assertion vulnerability in GPUModelRunner.initxdropepositions that allows remote attackers to crash the engine by submitting embeddings-only requests. Attackers can send a /v1/completions request containing only promptembeds to XD-RoPE models with --enable-prompt-embeds, terminating the EngineCore and API server for all clients.

First published (updated )
Severity
7.1
AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H

vLLM from 0.19.0 before 0.31.0 contains a resource exhaustion vulnerability that allows inference clients to bypass the server frame limit by setting mediaiokwargs.video.numframes in chat completion requests. Attackers can supply numframes=-1 or a large value with many base64 JPEG frames, forcing VideoMediaIO to decode all frames and np.stack them, causing memory exhaustion.

First published (updated )
Severity
6.5
AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H

Summary

vLLM's /v1/responses endpoint accepts request-level chattemplatekwargs, but does not apply the --trust-request-chat-template gate that protects Chat Completions, render, tokenize, and pooling paths.

When the server is run with the documented default trustrequestchattemplate=False and no explicit --chat-template, a Responses request can pass:

json {"chattemplatekwargs": {"chattemplate": "<attacker Jinja template>"}}

That key is preserved by ChatParams.getapplychattemplatekwargs() and then bound as the chattemplate parameter to the shared HF renderer. Prior vLLM advisories establish that request-controlled Jinja chat templates can cause CPU/memory exhaustion. This report covers the current-head Responses sibling path missed by the earlier fixes.

Technical Details

The shared OpenAI frontend has a validation helper that rejects request-supplied chat templates unless the trust flag is enabled. It explicitly checks both top-level chattemplate and chattemplatekwargs["chattemplate"].

Responses is a separate serving path:

- vllm/entrypoints/openai/responses/protocol.py exposes chattemplatekwargs. - ResponsesRequest.buildchatparams() merges request kwargs. - OpenAIServingResponses.effectivechattemplatekwargs() uses those kwargs. - ChatParams.getapplychattemplatekwargs() preserves a request chattemplate key when the server chat template is None. - vllm/renderers/hf.py unpacks the result into safeapplychattemplate.

There is no equivalent trust gate in vllm/entrypoints/openai/responses/serving.py.

Impact

An authenticated caller who can submit /v1/responses requests can supply a request-controlled Jinja chat template despite the trust flag being disabled. The expected fixed behavior is the same as Chat Completions: reject chattemplatekwargs["chattemplate"] unless the server was started with --trust-request-chat-template.

Suggested Fix

- Add trustrequestchattemplate to OpenAIServingResponses. - Pass args.trustrequestchattemplate when constructing the Responses serving object. - Reject request.chattemplatekwargs["chattemplate"] before rendering when trust is false. - Keep ordinary kwargs such as enablethinking working. - Add regression tests for default-deny and opt-in-allow behavior on /v1/responses.

Affected Package/Versions

Source sweep found the affected shape in:

- v0.16.0 - v0.18.0 - v0.20.0 - v0.21.0 - v0.22.0 - v0.22.1 - v0.23.0 - current checkout 470229c37efaf69c86e8bc97482b0b1ff7551c65 - current origin/main b3f0a0a0df76dda92ec4b2c9335f77e84adad911

Suggested affected range:

text = 0.16.0, <= 0.23.0

Appendix: Duplicate Research

This is related to, but distinct from:

- GHSA-6fvq-23cw-5628 / CVE-2025-61620 - GHSA-69j4-grxj-j64p / CVE-2025-62426

Those advisories establish the security impact of request-controlled Jinja templates and chattemplatekwargs, but they cover older Chat Completions/tokenize implementations. This report covers a current /v1/responses sibling path that still lacks the trust gate.

Local prior submissions this report..029 do not cover this root cause.

This advisory was fixed in MR50300.

1 / 2
Source: GitHub
First published (updated )
Severity
4.7
CSRF
AV:N/AC:H/PR:N/UI:R/S:C/C:L/I:N/A:N

Summary

The OpenAI-compatible server registers Starlette CORSMiddleware with allowedorigins defaulting to [""], and performs no authentication unless --api-key (or VLLMAPIKEY) is configured. A web page on any origin can send requests to a vLLM server that the victim's browser can reach (for example localhost or an internal/VPN address) and read the responses. The default allowcredentials=False blocks cookie-bearing cross-origin requests; because vLLM authenticates with a bearer header rather than cookies, the wildcard still permits untokenized access to an unauthenticated server and read access when the caller already holds a token.

Details

Affected components

- vllm/entrypoints/launchers/cliargs.py - allowedorigins default value. - vllm/entrypoints/serve/middleware/register.py - CORSMiddleware registration. - vllm/entrypoints/serve/middleware/authenticate.py - auth middleware and its guarded path prefixes.

Root cause

vllm/entrypoints/launchers/cliargs.py:

python allowcredentials: bool = False """Allow credentials.""" allowedorigins: list[str] = field(defaultfactory=lambda: [""]) """Allowed origins."""

vllm/entrypoints/serve/middleware/register.py:

python app.addmiddleware( CORSMiddleware, alloworigins=args.allowedorigins, allowcredentials=args.allowcredentials, allowmethods=args.allowedmethods, allowheaders=args.allowedheaders, )

The auth middleware is added only when a token is configured and guards only the /v1, /v2, /inference, and /cohere prefixes. /v1/loadloraadapter and /v1/unloadloraadapter are inside /v1 and therefore do require a key when one is set; they are open only when no key is configured and dynamic LoRA updating is enabled.

Impact

- A malicious page can enumerate models (GET /v1/models), issue POST /v1/chat/completions, consume GPU time, and read model output through the victim's browser. - When the server is reachable only from the victim's network, the browser acts as a proxy a remote website could not otherwise use. - With allowcredentials=False, cookie-based CSRF does not apply; the exposure is cross-origin request execution and response disclosure.

This advisory was fixed in MR61009.

1 / 2
Source: GitHub
First published (updated )
Severity
6.5
Out-of-bounds Read, Input Validation
AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H

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 kvtransferparams["prompttokenids"] reuse path) can trigger it.

Root cause vllm/v1/engine/inputprocessor.py accepts a token id when id <= max(tokenizer.maxtokenid, modelconfig.getvocabsize() - 1). vllm/tokenizers/hf.py computes maxtokenid = max(max(vocab.values()), tokenizer.vocabsize). For Llama-2 tokenizers max(vocab.values()) = 31999 but tokenizer.vocabsize = 32000, so maxtokenid = 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 padvocabsize(32000, 64) = 32000 rows (no padding), valid indices 0..31999. At VocabParallelEmbedding.forward with tpsize == 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 getmaskedinputandmask, 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.vocabsize one past the max real id (Llama-2 family, vocab 32000, is the clear case). Qwen2.5 is NOT affected (padded headroom).

Suggested fix maxtokenid in vllm/tokenizers/hf.py now uses tokenizer.vocabsize - 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.

1 / 2
Source: GitHub
First published (updated )
Severity
9.8
Input Validation
AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H

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.loadbase64() 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 parseimage() and fetchimage() 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.loadbytes() and MediaConnector.fetchimageasync(). 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.

1 / 2
Source: GitHub
First published (updated )
Severity
6.5
Input Validation
AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H

Summary

Any vLLM deployment serving a model of the DeepSeek-OCR family — deepseek-ai/DeepSeek-OCR, deepseek-ai/DeepSeek-OCR-2, or baidu/Unlimited-OCR (whose UnlimitedOCRForCausalLM subclasses DeepseekOCRForCausalLM) — can be killed by a single unauthenticated chat request carrying an ordinary, schema-valid PNG image, under completely default server configuration.

The image model's input validation contains a guard inherited from the upstream DeepSeek-OCR reference implementation:

python vllm/modelexecutor/models/deepseekocr.py:478-479 (parseandvalidateimageinput) if torch.sum(pixelvalues).item() == 0: return None

In the original research code this was an empty-batch shortcut; in vLLM's serving architecture pixelvalues is the actual client image tensor, and the condition is exactly satisfiable by a legitimate image: the in-tree DeepseekOCRProcessor normalizes pixels with ToTensor + Normalize(0.5, 0.5) (vllm/transformersutils/processors/deepseekocr.py:120-140), mapping pixel value 0 → exactly −1.0 and 255 → exactly +1.0 in float32. A 1024×1024 image that is half pure black and half pure white (a perfectly ordinary 1-bit-style scanned-document PNG for an OCR model) therefore yields torch.sum(pixelvalues) == 0.0 exactly (equal counts of ±1.0; pairwise reduction stays integer-exact, well inside float32's 2²⁴ exactness bound). ImageOps.pad(image, (1024, 1024)) is the identity map for an already-1024×1024 image (processors/deepseekocr.py:350-355), so no padding pixels disturb the balance.

Returning None makes embedmultimodal return None (deepseekocr.py:606-611), which immediately trips the engine-side sanity check in the worker:

python vllm/v1/worker/utils.py:512 (sanitycheckmmencoderoutputs) assert isinstance(mmembeddings, (list, tuple, torch.Tensor)), ( "Expected multimodal embeddings to be a list/tuple of 2D tensors, ...")

The AssertionError is raised inside the encoder runner of the EngineCore worker process with no per-request containment, escapes to the busy loop's top-level handler (vllm/v1/engine/core.py:1368, "EngineCore encountered a fatal error."), triggers EngineDeadError at the API server (vllm/v1/engine/asyncllm.py:843), and the whole process tree shuts down permanently. /health refuses connections until a manual restart.

Verified end-to-end on the official vllm/vllm-openai:v0.30.0 image (id d076d77d8dad) with real deepseek-ai/DeepSeek-OCR weights: after confirming /health 200, a text chat 200, and two control images (all-white and all-black 1024×1024) 200, the single half-black/half-white request returned HTTP 500 (EngineCore encountered an issue), the engine log shows AssertionError: Expected multimodal embeddings to be a list/tuple of 2D tensors ... got <class 'NoneType'> at v1/worker/utils.py:512, the API server shut itself down, and the container exited (Exited (0), OOMKilled=false). Every subsequent request, including GET /health, fails at the socket. The vulnerable check is unchanged on main (verified 2026-09-30 against the raw file on the default branch).

Environment notes (disclosed for completeness; unrelated to the sink): (1) the v0.30.0 image's Triton version refuses to compile deepencoder.py's fused rel-pos attention kernel (LOG2E non-constexpr global) during the startup profile run; per the compiler's own suggestion we set TRITONALLOWNONCONSTEXPRGLOBALS=1 — an environment workaround only, no source file was modified. (2) DeepSeek-OCR ships no chattemplate, so verification passed a one-line --chat-template that concatenates message content text; this does not touch the image data path. (3) The zero-sum check aggregates over the whole per-step modality batch, so the trigger image must be alone in its encoder batch — trivially true on an idle instance (our verification: first attempt, single request), and simply retried otherwise.

Details

1. The processor maps an ordinary binary image to exactly ±1.0 pixels. DeepseekOCRProcessor.tokenizewithimages (vllm/transformersutils/processors/deepseekocr.py:338-389) builds the global view as ImageOps.pad(image, (basesize, basesize), color=mean255) with basesize = 1024 (:21). For a 1024×1024 input the pad is a no-op (same-size ImageOps.contain resampling is the identity: the bicubic kernel passes through sample points exactly). ImageTransform (:120-140) then applies T.ToTensor() (uint8 0 → 0.0, 255 → 1.0, exact in float32) and T.Normalize((0.5,)3, (0.5,)3) (0.0 → −1.0, 1.0 → +1.0, exact). A left-half-black/right-half-white 1024×1024 RGB image therefore produces 1,572,864 elements of −1.0 and 1,572,864 of +1.0; torch.sum (pairwise/tree reduction, partial sums bounded by 1.58M ≪ 2²⁴) evaluates to exactly 0.0, and .item() == 0 is True. All of this runs in the API process and passes every validation layer: the image is 1 MP, far under the default VLLMMAXIMAGEPIXELS cap of 178,956,970 (vllm/envs.py:86).

2. The zero guard turns a valid image into a None encoder output. parseandvalidateimageinput (deepseekocr.py:468-497) returns None on the exact-zero sum; embedmultimodal (:606-611) propagates that None to its caller. The same pattern exists in deepseekocr2.py:339 (if pixelvalues is None or torch.sum(pixelvalues).item() == 0: return None), and UnlimitedOCRForCausalLM (unlimitedocr.py:244) inherits the method unmodified. (A sibling check in encodelocalfeatures at deepseekocr.py:522-523 guards crop tensors, which pass through a lossy resize and are not needed for this report.)

3. The worker asserts on the None and the engine dies. With the default configuration (cudagraphmmencoder=False, config/compilation.py), the V2 model runner executes the encoder eagerly: executemodel (v1/worker/gpu/modelrunner.py:1849) → modelstates/default.py:108 prepareinputsembeds → encoderrunner.executemmencoder (v1/worker/gpu/mm/encoderrunner.py:168) → model.embedmultimodal(mmkwargsbatch) → None → sanitycheckmmencoderoutputs(batchoutputs, expectednumitems=1) (encoderrunner.py:170) → AssertionError at v1/worker/utils.py:512. There is no per-request try/except anywhere on this path; the exception reaches the busy loop's top-level except Exception at core.py:1368 (via stepwithbatchqueue at core.py:660 and collectiverpc), which logs "EngineCore encountered a fatal error.", sends engine-dead, and re-raises (fault tolerance off by default; enginecoresentinel re-raises). The API server's outputhandler receives EngineDeadError (asyncllm.py:843) and shuts down. In the verified run the container exited (code 0, OOMKilled=false) and the port stayed closed — no self-recovery.

4. Why the guard exists and why it is wrong here. The torch.sum(...) == 0 → return None shortcut comes from the upstream DeepSeek-OCR reference implementation, where it skipped empty batches during batch inference. In vLLM, embedmultimodal is only invoked when the scheduler has real multimodal items to encode, so the guard never protects anything — it is purely a landmine that converts one specific, perfectly legal pixel distribution into a contract violation (embedmultimodal must return embeddings, not None) that the engine treats as a fatal invariant breach.

Version history. The check was introduced together with the model itself in #27247 ("[Model] Upstream Deepseek-OCR model", commit 675aa2ec, 2025-10-22; first stable release v0.11.1) and is unchanged since. DeepSeek-OCR-2 support (#33165, 2026-02-02) carries the same check at deepseekocr2.py:339. On main (checked 2026-09-30) the guard in parseandvalidateimageinput is still present verbatim.

Impact

Any unauthenticated client that can reach the OpenAI-compatible API of a deployment serving DeepSeek-OCR, DeepSeek-OCR-2, or Unlimited-OCR can deterministically crash the entire serving instance with one request: the EngineCore process dies, every in-flight and future request fails, and the API server exits; absent a supervisor the deployment stays down until restarted. The trigger is a schema-valid chat request with a small, completely legal PNG — for an OCR service, a half-black/half-white bitmap is indistinguishable from ordinary scanned-document traffic. The attack costs one request (~0.1 s observed end-to-end) and can be repeated after every restart.

No special server flags, no malformed input, no resource exhaustion, and no race are involved; the only requirement is that the trigger image is alone in its per-step encoder batch (true on an idle instance and retryable otherwise). Default-configured deployments of these models are affected with no mitigation short of patching.

Suggested remediation (any one of these breaks the kill chain):

1. Remove the torch.sum(pixelvalues) == 0 → return None shortcut from parseandvalidateimageinput (and the encodelocalfeatures sibling) in deepseekocr.py / deepseekocr2.py: in vLLM an empty encoder batch never reaches embedmultimodal, so the guard protects nothing and only converts valid inputs into a contract violation. If an all-zeros fast-path is ever needed, return a correctly-shaped zero embedding, not None. 2. If the check is kept as input validation, enforce it where it belongs: reject the offending item with a per-request error (HTTP 400) in the API-process input pipeline, not by violating the embedmultimodal return contract inside the worker. 3. Defense in depth: sanitycheckmmencoderoutputs failures should fail the offending request rather than the EngineCore busy loop — a model returning None for one item should not be engine-fatal.

This advisory was fixed in MR59417.

1 / 2
Source: GitHub
First published (updated )
Severity
6.5
AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H

Summary

The Phi-4 multimodal audio encoder (phi4mmaudio.py / phi4mmutils.py) runs its conformer attention in eager mode by default: the official HF config of microsoft/Phi-4-multimodal-instruct does not set useptscaleddotproductattention, so the default False applies (phi4mmaudio.py:166, :876; phi4mmutils.py:1669). The eager path fully materializes the attention probability matrix of shape [nchunks, 16, 500, 500] per layer — and then stores it on the module: self.attn = attn (phi4mmutils.py:1802, a torch.jit.Attribute declared at :1693), keeping a live reference for every one of the 24 encoder layers.

The only gates on audio length are the server-side limits VLLMMAXAUDIOCLIPFILESIZEMB=25 and VLLMMAXAUDIODECODEDURATIONS=600 (envs.py:83-84) — i.e. a 10-minute clip is a legal input by default. A 600 s clip becomes ~60,000 mel frames, which the encoder unfolds into 500-frame chunks (phi4mmaudio.py:996, maxseqlen = 500), giving nchunks ≈ 120. Each layer therefore materializes a 120×16×500×500 matrix (~1–2 GiB depending on dtype), and the module attribute keeps all completed layers' matrices alive, so GPU memory climbs monotonically within a single request until an allocation fails.

Verified end-to-end on the official vllm/vllm-openai:v0.31.0 image: one 19.2 MB silent 600 s WAV → worker torch.OutOfMemoryError: CUDA out of memory. Tried to allocate 2.29 GiB ... 501.75 MiB free ... 22.09 GiB allocated by PyTorch inside getaudiofeatures (phi4mmaudio.py:1279 → :1332 → phi4mmutils.py:1386) → EngineCore encountered a fatal error → API EngineDeadError → whole server down; /health refuses connections. Total time from request to dead service: ~6 seconds.

A secondary effect: because self.attn persists on the module after the request ends, the matrices of the last audio request stay resident indefinitely (observed +50 MiB pinned after a single 5 s control request); they are only overwritten by the next audio request, so the resident footprint equals the largest audio processed since startup.

Details

1. Root cause. MultiHeadedAttention.forwardattention in eager mode computes attn = maskedsoftmax(scores, mask) and unconditionally executes self.attn = attn (phi4mmutils.py:1795-1802). The attribute is a leftover inference/debug hook (used by torch.jit.Attribute(None, Tensor | None) at :1693); in serving it serves no purpose but pins the full [batch·chunks, heads, T, T] tensor per layer past both the layer's forward and the request's lifetime. The SDP attention branch (useptscaleddotproductattention=True) never materializes this matrix — but the HF config does not enable it and the code default is False.

2. Why one request suffices. The conformer chunks long audio to maxseqlen = 500 frames (phi4mmaudio.py:996). Duration is bounded only by VLLMMAXAUDIODECODEDURATIONS=600, so nchunks reaches ~120 for a maximal clip. With 16 heads and fp32 scores, one layer's attention tensor is ~1.8 GiB (the observed failing allocation was 2.29 GiB, consistent with the scores+bias materialization). The encoder has numblocks=24, attentionheads=16, attentiondim=1024, timereduction=8 (HF config). Weights plus a handful of retained per-layer matrices exhaust the ~2.3 GiB headroom that --gpu-memory-utilization 0.9 leaves on a 24 GB card — mid-forward, on the first request.

4. Deployment reality. --trust-remote-code is the documented, standard way to serve this model (the HF model card instructs it), so the finding applies to default deployments. The crash is deterministic, not load-dependent: scheduler stats at death show a single running request and near-zero KV cache usage.

Impact

Any unauthenticated client that can reach the chat/completions API of a default deployment serving Phi-4-multimodal-instruct (or any model reusing this audio tower) can kill the entire engine with one request carrying a perfectly legal 10-minute audio clip (silent noise suffices — no crafted content needed). Full denial of service, requiring a process restart. On GPUs with more headroom (e.g. 80 GB at default utilization) a single request may survive, but the eager path still materializes GiB-scale per-layer matrices and retains the last request's tensors indefinitely, so a few sequential max-length requests — or normal traffic following one — achieve the same result.

Relation to prior art: the only public Phi-4-mm advisory we found, GHSA-vc6m-hm49-g9qg, concerns a CPU-side quadratic-cost path — different subsystem, different mechanism. GitHub search for "phi4mm audio OOM/memory" (31 results, 2026-10-08) shows no report of this attention-retention issue; main (2026-10-08) is unchanged.

Suggested remediation (any one breaks the chain; 1+2 recommended):

1. Remove self.attn = attn from the serving path (or gate it behind an explicit debug/outputattentions flag) so attention matrices are freed when the layer returns. 2. Default useptscaleddotproductattention to True (flash/SDPA kernels never materialize the [B, H, T, T] matrix); keep eager only as an opt-in. 3. Additionally bound the encoder input (frames or duration) for this model so the eager path cannot reach GiB-scale single-layer allocations even if enabled.

This advisory was fixed in MR60614.

1 / 2
Source: GitHub
First published (updated )
Severity
8.8
AV:N/AC:H/PR:L/UI:N/S:U/C:H/I:H/A:H

Affected

- Ecosystem / package: pip / vllm - Affected versions: vLLM < 0.32.0.

Summary

When --mm-processor-cache-type shm is enabled, vLLM's multimodal SHM cache represents a cached item with an address and monotonicid pair and treats that pair as authority to dereference shared memory in the worker. A public scale-out request can supply its own multimodal features.kwargsdata, so an authenticated caller can forge an inner SHM carrier that points at attacker-controlled bytes already staged in the ring buffer. The worker then reaches pickle.loads() while deserializing the forged object.

This is reachable through ordinary public HTTP routes and does not require VLLMALLOWINSECURESERIALIZATION=1. The live chain used /v1/chat/completions/render to obtain a valid feature envelope, /v1/chat/completions to stage attacker-chosen bytes into SHM, and /inference/v1/generate to submit the forged inner carrier.

Affected code

Links pinned to the confirmed commit 752a3a504485 (v0.25.1):

- vllm/distributed/devicecommunicators/shmobjectstorage.py#L375-L400 — SHM object deserialization reaches pickle.loads(serializeddata) for byte objects. - vllm/multimodal/cache.py#L567-L581 — sender emits an SHM carrier containing only address and monotonicid. - vllm/multimodal/cache.py#L711-L737 — worker dereferences the untrusted pair and reads the SHM object. - vllm/entrypoints/scaleout/tokenintokenout/serving.py#L146-L173 — public features.kwargsdata is decoded into engine input without authenticating SHM handles before handoff.

The public scale-out route decodes attacker-controlled features.kwargsdata into MultiModalKwargsItems and hands them straight to the engine — no authentication of the SHM handle:

python vllm/entrypoints/scaleout/tokenintokenout/serving.py Lines 155-165 # Deserialize tensor data when present; None → cache hit. mmkwargs: dict[str, list[MultiModalKwargsItem | None]] = {} if features.kwargsdata is not None: for modality, items in features.kwargsdata.items(): mmkwargs[modality] = [ decodemmkwargsitem(item) if item is not None else None for item in items ] else: for modality, hashes in features.mmhashes.items(): mmkwargs[modality] = [None] len(hashes)

In the worker, a decoded item that carries an address is treated as authority to dereference shared memory: the (address, monotonicid) pair alone drives the read, with no binding to the cache key or to who issued the handle:

python vllm/multimodal/cache.py Lines 711-723 @override def getandupdateitem( self, mmitem: MultiModalKwargsItem | None, mmhash: str, ) -> MultiModalKwargsItem: assert mmitem is not None, f"Expected an address item for {mmhash=}" if "address" in mmitem: address = cast(int, mmitem["address"].data) monotonicid = cast(int, mmitem["monotonicid"].data) return self.shmcache.get(address, monotonicid)

return mmitem

The dereference lands in the SHM deserializer, which pickle.loads() any chunk tagged as bytes — so attacker bytes staged in the ring buffer are unpickled in the worker process:

python vllm/distributed/devicecommunicators/shmobjectstorage.py Lines 375-400 def deserialize(self, dataview: memoryview) -> Any: # pickle.loads do not read past the end of a pickled object # within a large buffer, so we can skip storing the metadata size typename, nbytes, lenarr = pickle.loads(dataview) serializeddata = dataview[-nbytes:]

if typename == torch.Tensor.name: obj = [] startidx = 0 for length in lenarr: itembytes = serializeddata[startidx : startidx + length] obj.append(itembytes) startidx += length obj = self.tensordecoder.decode(obj) elif typename == self.mmkwargsitemcls.name: obj = [] startidx = 0 for length in lenarr: itembytes = serializeddata[startidx : startidx + length] obj.append(itembytes) startidx += length obj = self.mmdecoder.decode(obj) elif typename == bytes.name: obj = pickle.loads(serializeddata) else: raise ValueError(f"Unsupported object type '{typename}' in metadata")

return obj

Impact

An ordinary authenticated inference caller can execute arbitrary Python in the worker process on a deployment that uses SHM multimodal caching. The live proof used a benign marker gadget and also caused the EngineCore health endpoint to fall from 200 to 503 after the forged request. The exploit is reachable with VLLMALLOWINSECURESERIALIZATION=0; it abuses the built-in SHM object deserializer, not the separate optional msgpack ext-hook flag.

Suggested Fix

Authenticate every SHM carrier with a server-issued capability bound to the cache key, address, and monotonic id; rotate the capability secret when the cache is cleared; and reject malformed or forged SHM carriers at the public scale-out boundary before engine handoff — so a forged pair never reaches the worker deref / pickle.loads().

The sender emits an HMAC capability (keyed by a 32-byte secret stored in the ring buffer and rotated on clear()) over (cachekey, address, monotonicid) alongside the pair. The public scale-out path validates it before engine handoff:

python vllm/entrypoints/scaleout/tokenintokenout/serving.py cache = self.onlinerenderer.renderer.mmprocessorcache for mmhash, item in zip(hashes, items): decodeditem = decodemmkwargsitem(item) if item is not None else None if decodeditem is not None and cache is not None: # Rejects a forged (address, monotonicid) that lacks a valid # server-issued capability for this cache key. cache.validateinputitem(decodeditem, mmhash) decodeditems.append(decodeditem)

The worker get() re-checks the capability on the reader side before it ever dereferences the caller-supplied address:

python vllm/distributed/devicecommunicators/shmobjectstorage.py def get(self, address, monotonicid, capability=None, key=None): if not self.iswriter: # Reject forged handles before dereferencing the supplied address. self.validatecapability(key, address, monotonicid, capability) with self.ringbuffer.accessbuf(address) as (dataview, bufmetadata): self.validatemonotonicid(address, monotonicid, bufmetadata) obj = self.serde.deserialize(dataview[self.flagbytes :]) ...

where validatecapability recomputes the HMAC with hmac.comparedigest and raises Missing server-issued SHM capability for cache key. / Invalid server-issued SHM capability for cache key. on any mismatch. The fix applies cleanly to v0.25.1 and ships regression tests asserting the generate path rejects an invalid handle and that the receiver requires a matching sender handle (and a capability issued after the current clear()) for the cache key.

Credit

Reported by: Patch the Planet (Trail of Bits + OpenAI collaboration)

This vulnerability was discovered using GPT-5.5-Cyber as part of the Patch the Planet security initiative.

---

Proposed fix: a proposed change for this issue is up for review in this advisory's temporary private fork: https://github.com/vllm-project/vllm-ghsa-6757-hggm-hp2w/pull/1

This advisory was fixed in MR59357.

1 / 2
Source: GitHub
First published (updated )
Severity
6.5
AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H

Summary vLLM renders chat templates by passing the resolved Jinja2 source to tokenizer.applychattemplate(), which compiles and .render()s it in an ImmutableSandboxedEnvironment. The sandbox prevents code-execution escapes but imposes no wall-clock timeout, no output-size cap, and no nested-loop or binop limit. The render runs in a ThreadPoolExecutor whose maxworkers defaults to 1, and CPython worker threads cannot be interrupted. An authenticated API client (or a malicious model repo loaded with trustremotecode=False) can therefore submit a single short template and permanently wedge all chat-style endpoints (/v1/chat/completions, /v1/responses, /tokenize, /pooling-chat, /invocations-chat) for every tenant until the process is restarted. A string-multiplication variant instead OOM-kills the API-server process. Because of a separately-reported (GHSA-jmjw-q4x3-hmc2) gate omission on /v1/responses, the remote authenticated attacker vector works in default vllm serve configuration with no operator opt-in.

Impact A single authenticated request of <100 bytes permanently denies all chat-style inference (/v1/chat/completions, /v1/responses, /tokenize, /pooling-chat, /invocations-chat) to every tenant of the API-server replica until the operator restarts the process. The string-multiplication variant OOM-kills the process. In a multi-tenant deployment this is a cross-tenant denial-of-service from any one tenant. From the malicious-model angle, a model repo whose tokenizerconfig.json carries the hostile template wedges every replica that loads it on the first legitimate chat request, with trustremotecode=False.

Preconditions: any non-harmony model (modeltype != gptoss); renderernumworkers at its default of 1; for the default-config authenticated API attacker vector, --chat-template must be unset (the default because most HF models ship their own). Blast radius: API-server process, per replica. Engine/worker processes unaffected by the CPU variant (event loop survives); affected by the memory variant (process OOM). Persistence: until process restart. Survives client disconnect.

This advisory was fixed in MR50300.

1 / 2
Source: GitHub
First published (updated )
Severity
8.3
AV:N/AC:L/PR:L/UI:N/S:C/C:N/I:N/A:H

vLLM from 0.8.5 before 0.31.0 has a denial of service flaw. LogprobsTensors.emptycpu() in vllm/v1/outputs.py allocates an uninitialized int32 tensor, and the V1 model runner leaves prompt positions reported as computed by a KV connector unwritten. A client sharing the engine can send promptlogprobs (or echo with logprobs) against a connector-cached prefix, making tokenizer decode raise OverflowError, which crashes EngineCore and drops all co-tenant requests.

First published (updated )
Severity
7.1
Out-of-bounds Read, Input Validation
AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H

vLLM from 0.20.1 before 0.29.0 contains an improper input validation vulnerability that allows remote attackers to crash the engine by supplying out-of-vocabulary stoptokenids. Attackers can send OpenAI chat, completion, generate, or batch requests with invalid IDs to terminate the engine or write outside the V2 runner's logits buffer.

First published (updated )
Severity
8.7
AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H

vLLM from 0.18.0 before 0.31.0 contains a resource exhaustion vulnerability that allows API clients to bypass the video/jpeg frame-count cap by overriding numframes through mediaiokwargs. Attackers can set numframes to -1 with a large inline video so VideoMediaIO.loadbase64 decodes every frame, exhausting memory and crashing the API frontend.

First published (updated )
Severity
8.7
AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N

vLLM from 0.10.2 before 0.25.0 contains an uncontrolled resource consumption vulnerability that allows unauthenticated attackers to exhaust memory because the Nemotron-VL processors globally set Image.MAXIMAGEPIXELS to None. Attackers can submit a pathological decompression-bomb image to /v1/chat/completions to OOM-kill the worker and deny service to co-tenants.

First published (updated )
Severity
8.2
Input Validation
AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:H

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 metadata to the disaggregated /inference/v1/generate endpoint. Attackers can replay a valid multimodal item with repeated or overlapping mmplaceholders ranges or mismatched kwargsdata and mmhashes lists, producing a negative text span in Qwen2.5-VL position construction that terminates the engine.

First published (updated )
Severity
8.8
SSRF
AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:L

vLLM from 0.9.2 before 0.24.0 contains a server-side request forgery vulnerability that allows API callers to force outbound connections by embedding a decode address in the X-Request-Id header. Attackers can make a P2pNcclConnector prefill worker ZMQ-connect to an attacker host, leaking the NCCL uniqueid and KV-cache tensors or blocking the worker.

First published (updated )
Severity
7.1
AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H

vLLM from 0.19.0 before 0.24.0 contains a decompression bomb vulnerability because the AudioMediaIO multimodal path calls loadaudio without the maxdurations decoded-duration limit. Authenticated attackers can send small compressed audio via inputaudio or audiourl in /v1/chat/completions requests that expands to huge decoded PCM, exhausting server memory.

First published (updated )
Severity
8.2
Input Validation
AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:H

vLLM from 0.22.0 before 0.24.0 contains an improper input validation vulnerability in the Rust gRPC Generate and GenerateStream service that forwards unchecked prompt token IDs to EngineCore. Attackers can submit requests with out-of-vocabulary prompt.tokenids values to trigger a fatal embedding lookup failure that terminates EngineCore and leaves the server unhealthy.

First published (updated )
Severity
8.2
Input Validation
AV:N/AC:H/AT:P/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N

vLLM from 0.22.0 before 0.24.0 contains an improper input validation vulnerability in the Rust gRPC Generate and GenerateStream service that forwards unchecked prompt token IDs to EngineCore. Attackers can submit requests with out-of-vocabulary prompt.tokenids values to trigger a fatal embedding lookup failure that terminates EngineCore and leaves the server unhealthy.

First published (updated )
Severity
7.1
AV:N/AC:L/AT:N/PR:L/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N

vLLM from 0.19.0 before 0.24.0 contains a decompression bomb vulnerability because the AudioMediaIO multimodal path calls loadaudio without the maxdurations decoded-duration limit. Authenticated attackers can send small compressed audio via inputaudio or audiourl in /v1/chat/completions requests that expands to huge decoded PCM, exhausting server memory.

First published (updated )
Severity
8.2
Input Validation
AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:H

vLLM from 0.22.0 before 0.24.0 contains a denial of service vulnerability that allows remote attackers to terminate EngineCore by bypassing logprobtokenids limits in the Rust gRPC frontend. Attackers can send Generate or GenerateStream requests with outputlogprobs enabled and more than 128 outputcandidates.tokenids, triggering a fatal sampler exception that crashes the engine.

First published (updated )
Severity
8.2
Input Validation
AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:H

vLLM from 0.22.0 before 0.24.0 contains an improper input validation vulnerability in the Rust gRPC converter that allows remote attackers to bypass maxlogprobs limits via CandidateTokens.topn. Attackers can send Generate or GenerateStream requests with oversized or integer-wrapping topn values to trigger torch.topk failures that terminate EngineCore.

First published (updated )
Severity
8.2
Input Validation
AV:N/AC:H/AT:P/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N

vLLM from 0.22.0 before 0.24.0 contains an improper input validation vulnerability in the Rust gRPC converter that allows remote attackers to bypass maxlogprobs limits via CandidateTokens.topn. Attackers can send Generate or GenerateStream requests with oversized or integer-wrapping topn values to trigger torch.topk failures that terminate EngineCore.

First published (updated )
Severity
8.7
AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H

Summary

API clients can supply arbitrary mmprocessorkwargs per request. vLLM forwards these values through the multimodal rendering and processing pipeline to Hugging Face and custom image/video processor constructors and calls. Resource-sensitive values such as image size, patch size, patch count, crop count, or frame count can therefore be controlled by a remote client.

For processors that upscale inputs, a single request can force an allocation large enough to terminate the API server or worker with an out-of-memory condition.

Affected Components

The per-request field was introduced in commit 041e29471671a3d43afedb6a749421d56ef4d3e7 and first shipped in v0.7.3. The generic forwarding path remains present in current main.

The Isaac path is a concrete high-amplification example:

- ChatCompletionRequest.mmprocessorkwargs - OnlineRenderer request extras - MMProcessorInputs.hfprocessormmkwargs - BaseMultiModalProcessor.info.gethfprocessor(hfprocessormmkwargs) - IsaacProcessingInfo.getimageprocessor(kwargs) - IsaacImageProcessor(kwargs) - processvisionforpatches()

Equivalent constructor forwarding exists in InternVL-derived processors, H2OVL, Step3VL, NemotronVL, and other multimodal processors. The issue is at the shared remote-input boundary and is not limited to a fixed model list.

Impact

- Availability: one request can exhaust CPU or GPU memory and terminate a shared service process. - Scope: all users of the affected service instance lose availability. - Authentication: vLLM's API key is optional, so deployments without an external authentication layer are remotely reachable without privileges.

Remediation

Reject non-empty per-request mmprocessorkwargs at every API-server request schema by default. Operators serving only trusted clients can explicitly opt in to the existing override behavior. Server-level --mm-processor-kwargs and offline LLM overrides remain available.

This shared boundary covers current and future multimodal processors instead of maintaining a model-specific list or a denylist that can miss custom processor arguments.

A patch for this was merged here: https://github.com/vllm-project/vllm/pull/58830

1 / 2
Source: GitHub
First published (updated )
Severity
7.1
AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H

vLLM before 0.31.0 contains a cache aliasing vulnerability that allows authenticated attackers to collide shared cache keys by supplying caller-controlled values such as EXIF ImageID or cachesalt. Attackers can set a UUID EXIF ImageID to receive another request's cached processed media, or match cachesalt to a LoRA name to reuse first-block KV state.

First published (updated )
Severity
8.7
AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H

vLLM after 0.24.0 and before 0.31.0 contains a memory exhaustion vulnerability in MOSS-Audio model serving that caches a processor for every distinct request-controlled mmprocessorkwargs value in an unbounded dictionary. Unauthenticated attackers can send distinct or oversized melconfig values to the /tokenize endpoint, which bypasses --api-key, to exhaust host memory and crash the API process.

First published (updated )
Severity
9.2
Code Injection
AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H

Summary

An untrusted multimodal request can set mmprocessorkwargs.coderevision. When vLLM serves a model whose Hugging Face processor uses dynamic automap code and the operator enabled --trust-remote-code, this request value reaches AutoProcessor.frompretrained and selects the Python revision imported by Transformers.

This lets a client replace the operator-reviewed processor module with code from another revision of the same model repository. The operator-selected model/data revision remains pinned; only the executed processor code changes.

Importing a Python module is arbitrary code execution in the vLLM API/renderer process. The PoC below demonstrates this with an import-time filesystem write. It is fully offline and does not require a GPU, model weights, or changes to a real Hub repository.

Affected snapshot

- Repository: vllm-project/vllm - Verified commit: 570735520942b6428ae98f1eb442c6d88adae55e - Verified with Transformers 5.15.0 and 5.16.1 - Affected release range has not been bisected

Affected configuration

The vulnerable path exists when all of the following are true:

1. The served model's processor uses dynamic automap.AutoProcessor code. 2. The operator enabled trustremotecode. 3. The server can fetch the request-selected revision, or it is already cached. 4. The attacker can create or otherwise control a revision in the served model repository. An example is a Hugging Face community pull-request ref when that repository permits them. 5. A multimodal request reaches the processor path.

The default trustremotecode=False configuration is not affected.

Attack surface

mmprocessorkwargs is accepted directly by public request models:

- TokenizeChatRequest.mmprocessorkwargs - ChatCompletionRequest.mmprocessorkwargs

/tokenize is particularly relevant because vLLM's authentication middleware guards only /v1, /v2, /inference, and /cohere prefixes:

- AuthenticationMiddleware

Consequently, /tokenize remains unauthenticated even when --api-key is configured, unless an external proxy protects it. The vLLM Security Guide documents /tokenize as an unprotected endpoint.

Root cause

The request value follows this path:

1. OnlineRenderer.preprocesschat places request mmprocessorkwargs in prompt extras. 2. Multimodal rendering forwards those kwargs into processor construction through MMProcessorInputs and processmultimodalasync. 3. MultiModalConfig.mergemmprocessorkwargs overlays inference values on startup values, so the request wins. 4. cachedgetprocessorwithoutdynamickwargs filters only recognized processor-call keys. coderevision is retained as a processor-construction kwarg. 5. cachedprocessorfromconfig pins revision and trustremotecode, but forwards the remaining kwargs without reserving coderevision. 6. getprocessor calls AutoProcessor.frompretrained(..., revision=revision, trustremotecode=trustremotecode, kwargs). 7. Transformers AutoProcessor.frompretrained uses coderevision to retrieve and import the dynamic module through getclassfromdynamicmodule, then removes it before loading processor data. This is why code comes from the attacker revision while configuration/data remain operator-pinned.

Request-time processor arguments are not separated from processor-construction arguments, and coderevision is not reserved.

Suggested remediation

1. Separate processor-construction arguments from untrusted processor-call arguments. An allowlist of supported request-time preprocessing controls is safest. 2. Reject coderevision and other loader/source controls in request mmprocessorkwargs, and pass modelconfig.coderevision explicitly as the only permitted processor-code revision. 3. Add a regression test proving a request cannot change the loaded module revision while operator pins remain effective. 4. Protect /tokenize with the configured authentication policy as defense in depth.

Expected safe behavior is either a 4xx response for reserved request keys or silently ignoring them before processor construction. Rejection is preferable because it makes attempted misuse visible.

A patch for this was merged here: https://github.com/vllm-project/vllm/pull/58830

1 / 2
Source: GitHub
First published (updated )

Contact

SecAlerts Pty Ltd.
132 Wickham Terrace
Fortitude Valley,
QLD 4006, Australia
info@secalerts.co
By using SecAlerts services, you agree to our services end-user license agreement. This website is safeguarded by reCAPTCHA and governed by the Google Privacy Policy and Terms of Service. All names, logos, and brands of products are owned by their respective owners, and any usage of these names, logos, and brands for identification purposes only does not imply endorsement. If you possess any content that requires removal, please get in touch with us.
© 2026 SecAlerts Pty Ltd.
ABN: 70 645 966 203, ACN: 645 966 203