vLLM CVE-2026-114053: when one request chooses which model code your server runs
vLLM CVE-2026-114053 let a request pick which revision of a model's processor code to import. Who is exposed, the fix in 0.31.0, and how to lock it down.
- Published
- Reading time
- 6 min read

Key takeaways
- CVE-2026-114053 lets a client set mm_processor_kwargs.code_revision in a multimodal request so vLLM imports processor code from a revision the operator never reviewed, running arbitrary Python in the API process.
- The flaw affects vLLM 0.7.3 up to but not including 0.31.0, and only deployments that enable trust_remote_code for a model whose processor uses dynamic auto_map code.
- VulnCheck rates CVE-2026-114053 CVSS 4.0 9.2 and CVSS 3.1 8.1; the CVE record was published on October 21, 2026.
- vLLM's --api-key protects only the /v1, /v2, /inference, and /cohere path prefixes, so /tokenize, the main path to this bug, stays unauthenticated unless a proxy blocks it.
- vLLM 0.31.0 rejects per-request mm_processor_kwargs and media_io_kwargs by default; operators must opt back in with --trust-request-mm-kwargs.
On this page
CVE-2026-114053 is a remote code execution flaw in vLLM, the open-source LLM inference server. When trust_remote_code is enabled, vLLM 0.7.3 through 0.30.x passes a client-supplied mm_processor_kwargs.code_revision value to Transformers, so a request can choose which revision of a model's processor code gets imported and executed. Upgrade to vLLM 0.31.0, and if you run any model with trust_remote_code, treat this as urgent.
The bug is worth understanding beyond the patch. It shows that pinning a model's revision does not pin all of its code, and that a "harmless" utility endpoint on an inference server can reach the most dangerous code path it has. This article reflects the advisory and CVE record as of October 29, 2026.
What is CVE-2026-114053?
The vLLM project's GitHub advisory GHSA-h3rc-6mm3-gc2m, published on October 6, 2026, is titled "Request-controlled mm_processor_kwargs.code_revision allows RCE". It affects the vllm PyPI package from 0.7.3 up to, but not including, 0.31.0. VulnCheck, acting as the CNA, published CVE-2026-114053 on October 21, 2026 with a CVSS 4.0 score of 9.2 and a CVSS 3.1 score of 8.1. It is classed as CWE-94 (code injection) and CWE-829 (inclusion of functionality from an untrusted control sphere).
None of the sources reviewed for this article report exploitation in the wild. That can change, so check the CVE record and CISA's KEV catalog before you deprioritize it.
How does the attack work?
Some multimodal models ship their own Python processor class, declared through auto_map.AutoProcessor in the model repository. Transformers imports that code only when the caller passes trust_remote_code=True. Transformers also accepts a separate code_revision argument, which picks the revision the dynamic code is loaded from, independently of the revision used for weights and configuration.
According to the advisory, the request path looked like this:
- A client sends a multimodal request with
mm_processor_kwargsin the body. - vLLM merges those request values into the processor construction arguments, and request values override startup values.
- The kwargs filter removes only keys it recognizes as processor-call arguments, so
code_revisionsurvives. - vLLM pins
revisionandtrust_remote_codefrom the operator's configuration, but never reservescode_revision. AutoProcessor.from_pretrainedimports the processor module from the request-selected revision. Configuration and data stay on the operator's pinned revision; only the code moves.
Importing a Python module runs its top-level code, so the attacker's processor executes inside the vLLM API process with its credentials, network access, and GPU host.
Where does the attacker's revision come from?
The attacker needs a revision in the served model's repository that they control. The advisory names Hugging Face community pull request refs as one example. Hub pull requests do not use forks: contributors push commits to a ref such as refs/pr/42 stored directly on the source repository. Those refs are not fetched by default when you clone, but they can be fetched on demand, which is exactly what a request-selected revision does.
So a model you reviewed and pinned can still carry unreviewed code in its PR refs, written by anyone allowed to open a pull request.
Who is exposed?
The advisory lists five preconditions, all of which must hold:
- The served model's processor uses dynamic
auto_map.AutoProcessorcode. - The operator started vLLM with
trust_remote_codeenabled. The default, disabled, is not affected. - The server can fetch the request-selected revision, or already has it cached.
- The attacker can create or control a revision in the model repository.
- A multimodal request reaches the processor code path.
The second condition is the quick filter. If none of your vLLM deployments pass --trust-remote-code, this CVE does not apply to them, though you should still upgrade.
/v1/chat/completions also accepts mm_processor_kwargs, so any authenticated user of the chat API could reach the same code path. In multi-tenant deployments, "authenticated" often means every customer.
How do I check and fix my deployments?
Start with an inventory of where vLLM runs and how it was started.
# Installed version in each environment or image
pip show vllm | grep -i '^version'
# Find deployments that enable remote code
grep -rnE -- '--trust-remote-code|trust_remote_code[[:space:]]*=[[:space:]]*True' \
deploy/ k8s/ helm/ docker/ 2>/dev/null
Then work through these steps in order:
- Upgrade to vLLM 0.31.0 or later. The 0.31.0 release notes state that per-request
mm_processor_kwargsandmedia_io_kwargsare now rejected by default. The server returns an error instead of forwarding them. - Disable
trust_remote_codewhere you can. If your Transformers and vLLM versions support the model's architecture natively, it does not need remote code. - Pin code explicitly where you cannot. vLLM documents separate
--revision,--code-revision, and--tokenizer-revisionflags in its engine arguments. Set each to a reviewed commit hash rather than a branch name. - Put a reverse proxy in front of the API server that allowlists only the endpoints your clients need. vLLM's security guide recommends this, and it is the only reliable way to close
/tokenize,/metrics, and other unauthenticated paths. - Rebuild images. A pinned
vllmin a requirements file or base image stays vulnerable until the image is rebuilt and redeployed.
A minimal nginx allowlist looks like this:
location = /v1/chat/completions { proxy_pass http://vllm:8000; }
location = /v1/completions { proxy_pass http://vllm:8000; }
location = /v1/models { proxy_pass http://vllm:8000; }
location / { return 404; }
Should I look for signs of exploitation?
If you ran an affected version with trust_remote_code enabled and /tokenize reachable, assume the API process could have been compromised. Useful checks:
- Search proxy or gateway logs that capture request bodies for
code_revision. Legitimate clients have little reason to send it. - Inspect the host's Hugging Face cache for downloaded code from revisions you did not pin.
- Review outbound connections from inference hosts and rotate any credentials the process could read, such as Hub tokens and cloud keys.
What is the broader lesson for AI infrastructure?
This is the same mistake as letting a request choose a SQL table name: a value that should come only from operator configuration was accepted from the client. The advisory's own recommended fix says as much. Separate processor-construction arguments from request-time arguments with an allowlist, reject loader and source controls in requests with a 4xx error, and treat the operator's code_revision as the only permitted one.
Three rules carry over to any inference stack:
- Anything that selects code is configuration, never input. Revisions, repository IDs, adapter paths, and plugin names should be fixed at startup or checked against an allowlist.
- A revision pin is only as strong as every loader that honours it. Pin weights, code, and tokenizer separately, and test that a request cannot move any of them.
- Inference servers are not edge services. Their built-in auth was designed for trusted networks. Put an authenticating, allowlisting proxy in front of every one.
If you load third-party models, our guide to loading model weights safely covers pickle, weights_only, and the review process for trust_remote_code. For another recent example of how much damage a compromised component in the LLM serving path can do, see the LiteLLM 1.107.0 compromise.



