Skip to main content

vLLM CVE-2026-41523

HIGH
Code Injection (CWE-94)
2026-06-16 https://github.com/vllm-project/vllm GHSA-q8gq-377p-jq3r
7.5
CVSS 3.1 · Vendor: https://github.com/vllm-project/vllm
Share

Severity by source

Vendor (https://github.com/vllm-project/vllm) PRIMARY
7.5 HIGH
AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:H
vuln.today AI
7.5 HIGH

Attacker is a remote unauthenticated model publisher (AV:N/PR:N) but victim must load the model and run vLLM under -O (UI:R, AC:H); successful exploit yields full process compromise (C:H/I:H/A:H).

3.1 AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:H
4.0 AV:N/AC:H/AT:P/PR:N/UI:A/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N
Red Hat
7.5 HIGH
qualitative

Primary rating from Vendor (https://github.com/vllm-project/vllm).

CVSS VectorVendor: https://github.com/vllm-project/vllm

CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:H
Attack Vector
Network
Attack Complexity
High
Privileges Required
None
User Interaction
Required
Scope
Unchanged
Confidentiality
High
Integrity
High
Availability
High

Lifecycle Timeline

3
Source Code Evidence Fetched
Jun 16, 2026 - 18:20 vuln.today
Analysis Generated
Jun 16, 2026 - 18:20 vuln.today
CVE Published
Jun 16, 2026 - 17:34 github-advisory
HIGH 7.5

Blast Radius

ecosystem impact
† from your stack dependencies † transitive graph · vuln.today resolves 4-path depth
  • 1 pypi packages depend on vllm (1 direct, 0 indirect)

Ecosystem-wide dependent count for version 0.22.0.

DescriptionCVE.org

Summary

An assert-based security check in vLLM's activation function loading allows any unauthenticated attacker to achieve arbitrary code execution on the server by publishing a malicious HuggingFace model, when vLLM runs in Python optimized mode (python -O or PYTHONOPTIMIZE=1).

Details

vLLM uses an assert statement at vllm/model_executor/layers/pooler/activations.py:48 as its sole security control to restrict which activation functions can be loaded from a HuggingFace model's config.json:

python
# vllm/model_executor/layers/pooler/activations.py:35-53
function_name: str | None = None
if (
    hasattr(config, "sentence_transformers")
    and "activation_fn" in config.sentence_transformers
):
    function_name = config.sentence_transformers["activation_fn"]
elif (
    hasattr(config, "sbert_ce_default_activation_function")
    and config.sbert_ce_default_activation_function is not None
):
    function_name = config.sbert_ce_default_activation_function

if function_name is not None:
    assert function_name.startswith("torch.nn.modules."), (
        "Loading of activation functions is restricted to "
        "torch.nn.modules for security reasons"
    )
    fn = resolve_obj_by_qualname(function_name)()

Python's assert statements are stripped at compile time when running in optimized mode (python -O or PYTHONOPTIMIZE=1). When the assert is absent, the attacker-controlled function_name from the model's config.json is passed directly to resolve_obj_by_qualname() - an unrestricted import gadget:

python
def resolve_obj_by_qualname(qualname: str) -> Any:
    module_name, obj_name = qualname.rsplit(".", 1)
    module = importlib.import_module(module_name)
    return getattr(module, obj_name)

This is the same vulnerability class as CVE-2017-1000433 (pysaml2 assert-based auth bypass), flagged by Bandit B101 and Ruff S101, and the reason Django proactively replaced all assert-based security checks (ticket #32508).

Attacker-controlled input sources:

  • config.sentence_transformers["activation_fn"] (line 40)
  • config.sbert_ce_default_activation_function (line 45)

Affected call sites - get_act_fn() is called via resolve_classifier_act_fn() from:

  • vllm/model_executor/layers/pooler/seqwise/poolers.py:122 - SequencePooler
  • vllm/model_executor/layers/pooler/tokwise/poolers.py:130 - TokenPooler

Broader systemic risk: resolve_obj_by_qualname is called from ~20 locations across the codebase with no validation of its own. Any future caller feeding user-controlled input to it without validation creates the same vulnerability class.

Suggested fix: Replace the assert with an explicit conditional raise:

python
if not function_name.startswith("torch.nn.modules."):
    raise ValueError(
        "Loading of activation functions is restricted to "
        "torch.nn.modules for security reasons"
    )

Impact

Arbitrary code execution. A malicious model author publishes a HuggingFace model with a crafted config.json. When a victim loads this model with vLLM running under python -O or PYTHONOPTIMIZE=1, arbitrary code executes during model initialization with the privileges of the vLLM process.

The attack requires:

  1. Victim loads a malicious model from HuggingFace (user interaction)
  2. vLLM runs under python -O or PYTHONOPTIMIZE=1 (documented in production use)
  3. Model uses a cross-encoder architecture (e.g. BERT or RoBERTa with sequence classification)

Coordinated disclosure note: This vulnerability was also reported via huntr.com on April 2, 2026 (https://huntr.com/bounties/dcb05b04-e625-41e7-adbc-bbae0cc2d64c). A GitHub Security Advisory was also filed because it is vLLM's stated preferred disclosure channel per SECURITY.md.

Fix

A fix for this was introduced in this commit: https://github.com/vllm-project/vllm/commit/b3c7ffcab82c2439726f8cb213800f6f38c023d3

AnalysisAI

Arbitrary code execution in vLLM versions prior to 0.22.0 allows remote unauthenticated attackers to run code on the inference server by publishing a malicious HuggingFace model, when vLLM is launched in Python optimized mode (python -O or PYTHONOPTIMIZE=1). The sole guardrail restricting which activation function classes can be loaded from a model's config.json is implemented with a Python assert, which is stripped at compile time under -O, leaving an unrestricted import gadget directly fed by attacker-controlled data. No public exploit identified at time of analysis, but the vendor advisory (GHSA-q8gq-377p-jq3r) and a coordinated huntr.com submission document the issue in detail.

Technical ContextAI

vLLM is a high-throughput inference and serving engine for large language models written in Python (pkg:pip/vllm). In vllm/model_executor/layers/pooler/activations.py, the get_act_fn() routine reads an activation_fn / sbert_ce_default_activation_function string from the loaded HuggingFace model config and uses 'assert function_name.startswith("torch.nn.modules.")' as its only allowlist before passing the value to resolve_obj_by_qualname(), which performs importlib.import_module() followed by getattr() with no further validation. Python documents that assert is removed when the interpreter runs with -O or PYTHONOPTIMIZE=1, so the allowlist disappears in exactly the production-tuned configurations vLLM operators are likely to use. The root cause is CWE-94 (Improper Control of Generation of Code) realized through an assert-based security check, the same class CISA and Bandit (B101) / Ruff (S101) flag and the reason Django removed assert-based checks in ticket #32508; CVE-2017-1000433 in pysaml2 is a direct prior analogue. The reachable call sites are SequencePooler (vllm/model_executor/layers/pooler/seqwise/poolers.py:122) and TokenPooler (tokwise/poolers.py:130), invoked when loading cross-encoder / sentence-transformer models (e.g. BERT or RoBERTa for sequence classification).

RemediationAI

Vendor-released patch: upgrade vLLM to 0.22.0 or later, which replaces the assert with an explicit 'if not function_name.startswith("torch.nn.modules."): raise ValueError(...)' in vllm/model_executor/layers/pooler/activations.py (commit b3c7ffcab82c2439726f8cb213800f6f38c023d3, advisory https://github.com/vllm-project/vllm/security/advisories/GHSA-q8gq-377p-jq3r). If you cannot upgrade immediately, the simplest compensating control is to stop running vLLM under python -O or with PYTHONOPTIMIZE=1 - this restores the assert and closes the vulnerable code path, at the cost of slightly larger memory footprint and losing the marginal CPU savings from stripped asserts and __debug__ branches. As a model-supply-chain control, restrict which HuggingFace repositories vLLM is allowed to load (pin to specific vetted revisions or mirror them to an internal registry) and forbid auto-pulling models from arbitrary external authors; this is high-value but introduces operational overhead in model curation. Defenders who maintain a fork can also locally backport the conditional-raise change shown in the upstream commit to older vLLM versions.

More in Python

View all
CVE-2025-24016 CRITICAL POC
9.9 Feb 10

Wazuh SIEM platform versions 4.4.0 through 4.9.0 contain an unsafe deserialization vulnerability in the DistributedAPI t

CVE-2025-27520 CRITICAL POC
9.8 Apr 04

BentoML version 1.4.2 and earlier contains an unauthenticated remote code execution vulnerability through insecure deser

CVE-2025-2945 CRITICAL POC
9.9 Apr 03

pgAdmin 4 contains critical remote code execution vulnerabilities in the Query Tool download and Cloud Deployment endpoi

CVE-2013-5093 MEDIUM POC
6.8 Sep 27

The renderLocalView function in render/views.py in graphite-web in Graphite 0.9.5 through 0.9.10 uses the pickle Python

CVE-2025-32375 CRITICAL POC
9.8 Apr 09

BentoML is a Python library for building online serving systems optimized for AI apps and model inference. Rated critica

CVE-2014-0224 HIGH POC
7.4 Jun 05

OpenSSL before 0.9.8za, 1.0.0 before 1.0.0m, and 1.0.1 before 1.0.1h does not properly restrict processing of ChangeCiph

CVE-2024-21644 HIGH POC
7.5 Jan 08

pyLoad download manager version prior to 0.5.0b3.dev77 exposes the Flask SECRET_KEY through an unauthenticated endpoint.

CVE-2017-9462 HIGH POC
8.8 Jun 06

In Mercurial before 4.1.3, "hg serve --stdio" allows remote authenticated users to launch the Python debugger, and conse

CVE-2026-39987 CRITICAL POC
9.3 Apr 08

Unauthenticated remote code execution in Marimo ≤0.20.4 allows attackers to execute arbitrary system commands via the `/

CVE-2024-21645 MEDIUM POC
5.3 Jan 08

pyLoad is the free and open-source Download Manager written in pure Python. Rated medium severity (CVSS 5.3), this vulne

CVE-2026-33017 CRITICAL POC
9.3 Mar 17

Langflow (a visual LLM pipeline builder) contains a critical unauthenticated code execution vulnerability (CVE-2026-3301

CVE-2026-55255 HIGH POC
8.4 Jun 19

Cross-user flow execution in Langflow (< 1.9.1) lets any authenticated API-key holder run another user's flow by passing

Vendor StatusVendor

Share

CVE-2026-41523 vulnerability details – vuln.today

This site uses cookies essential for authentication and security. No tracking or analytics cookies are used. Privacy Policy