Skip to content

vLLM: Incomplete CVE-2025-62164 remediation can be bypassed by concurrent prompt parts

Moderate severity GitHub Reviewed Published Jul 27, 2026 in vllm-project/vllm • Updated Sep 4, 2026

Package

pip vllm (pip)

Affected versions

>= 0.21.0, < 0.26.0

Patched versions

0.26.0

Description

Executive Summary

The follow-up protection for CVE-2025-62164 is incomplete at vLLM revision 26587f9519e22a5c4549ead7595ad9ca3229c4fd. It wraps serialized prompt-embedding reconstruction and dense conversion in torch.sparse.check_sparse_tensor_invariants(), but PyTorch 2.11.0 implements that context with save/enable/restore operations over process-global state. Two prompt-embedding parts in one /v1/chat/completions request are gathered concurrently on the event loop's default executor. When one context exits before the other loads its tensor, it can restore the global flag to False while the second part remains inside its guard.

In a deterministic run against hash-verified source from the affected revision, the actual target loader rejected an invalid sparse payload as a negative control. The frozen chat tracker then scheduled benign and malicious parts on distinct asyncio_0 and asyncio_1 threads. The benign context exited, the malicious loader observed the invariant flag disabled, and torch.load(weights_only=True) reconstructed indices [[10], [10]] for a declared shape of [3, 3]. The run intercepted the target's to_dense() call before it operated on the invalid tensor.

This primary trigger requires --enable-prompt-embeds, which is default-off, but it does not require renderer_num_workers > 1, a multimodal model, or --enable-mm-embeds. API authentication is optional in the stock server: middleware is installed only when CLI or environment API keys are supplied.

The lab proves bypass of the follow-up guard, invalid sparse reconstruction, and guarded-sink reachability. Crash and memory-corruption consequences are conditional on the behavior documented by the published CVE.

Background

CVE-2025-62164 / GHSA-mrw7-hf4f-83pf concerns client-controlled serialized prompt_embeds reaching torch.load(weights_only=True) and an invalid sparse tensor reaching to_dense(). The advisory attributes memory corruption, denial of service, and potential code execution to that historical unsafe operation.

The remediation chronology matters for duplicate handling:

This report therefore does not present the malformed sparse payload or to_dense() sink as new. It reports a distinct concurrency root cause and trigger: unsynchronized save/enable/restore of the process-global follow-up guard, reachable through the later multi-part chat scheduler.

The affected revision pins PyTorch 2.11.0 in pyproject.toml:10.

Vulnerability Details

The target's safe_load_prompt_embeds performs the guarded operation in vllm/renderers/embed_utils.py:16-39:

with torch.sparse.check_sparse_tensor_invariants():
    tensor = torch.load(
        BytesIO(pybase64.b64decode(embed, validate=True)),
        weights_only=True,
        map_location=torch.device("cpu"),
    )
    if not isinstance(tensor, torch.Tensor):
        raise VLLMValidationError(...)
    tensor = tensor.to_dense()

The context is not request-local. With the global flag initially disabled, we can describe the verified interleaving:

  1. Benign part A enters, saves False, and enables the flag.
  2. Malicious part B enters, saves True, and leaves the flag enabled.
  3. A completes its load and exits, restoring its saved False value.
  4. B remains lexically inside its context but observes the actual global flag as False.
  5. B's torch.load(..., weights_only=True) reconstructs the malformed sparse tensor.
  6. The target reaches tensor.to_dense() before later rank, hidden-size, and dtype checks.

weights_only=True constrains deserialization types; it does not compensate for a sparse invariant check that another request has disabled.

The complete stock actor-to-sink chain, traced in the affected source, is:

POST /v1/chat/completions (vllm/entrypoints/openai/chat_completion/api_router.py:41-61) -> OpenAIServingChat.create_chat_completion -> _create_chat_completion -> render_chat_request (vllm/entrypoints/openai/chat_completion/serving.py:206-280) -> OnlineRenderer.render_chat (vllm/renderers/online_renderer.py:95-190) -> preprocess_chat (vllm/renderers/online_renderer.py:335-380) -> BaseRenderer.render_chat_async (vllm/renderers/base.py:1070-1105) -> HfRenderer.render_messages_async (vllm/renderers/hf.py:1049-1085) -> parse_chat_messages_async (vllm/entrypoints/chat_utils.py:1911-1945) -> content-part parse_prompt_embeds and _load_prompt_embeds_async (vllm/entrypoints/chat_utils.py:1099-1120) -> AsyncMultiModalItemTracker.resolve_items (vllm/entrypoints/chat_utils.py:818-835) -> asyncio.gather of both prompt parts -> safe_load_prompt_embeds_async -> make_async -> loop.run_in_executor(executor=None, ...) (vllm/utils/async_utils.py:28-45) -> guarded torch.load -> to_dense().

The prompt async helper is created without an explicit executor, so it uses the event loop's default executor. This path is separate from the renderer's configurable pool. The deterministic scheduler run observed the two parts on distinct default-executor threads while leaving renderer_num_workers at its default of one.

prompt_embeds bypasses multimodal processing, and the tracker explicitly permits it when is_multimodal_model=False (vllm/entrypoints/chat_utils.py:793-837). Consequently, the primary trigger needs neither a multimodal model nor enable_mm_embeds.

The source also states that async wrappers must be thread-safe (vllm/utils/async_utils.py:28-38), while a target test acknowledges that the sparse flag is not thread-local and concurrent users can leak state (tests/renderers/test_sparse_tensor_validation.py:58-61).

Exploitability Analysis

The following evidence labels separate what was demonstrated from what remains conditional:

Label Claim
Verified by run PyTorch 2.11.0 rejects the identical invalid payload through the actual target loader without the race.
Verified by run The hash-verified frozen tracker schedules two prompt parts on distinct default-executor threads, races the flag to False, reconstructs the invalid sparse tensor, and reaches the target to_dense() call while the interception prevents execution.
Traced in source A client can supply multiple prompt_embeds content parts through the stock /v1/chat/completions route and the function chain above.
Traced in source enable_prompt_embeds defaults to False (vllm/config/model.py:255-260), so the operator must opt in. enable_mm_embeds and non-default renderer workers are not preconditions for this path.
Traced in source api_key defaults to None (vllm/entrypoints/openai/cli_args.py:264), and authentication middleware is installed only when a CLI or environment key is present (vllm/entrypoints/openai/api_server.py:306-310). With a configured key, the attacker must authenticate; without one, the stock route has no API-key middleware.
Unrun A live HTTP/GPU server, real-world race win rate, unsafe dense conversion, process crash, memory corruption, and reliable code execution.

The feature is documented for trusted users, which narrows intended exposure. It is not a memory-safety boundary: a user authorized to submit embedding inputs should not be able to disable a process-wide invariant for concurrent work.

The current run proves the same invalid sparse object can cross the guard and reach the historical sink. If executing that sink retains the behavior described in CVE-2025-62164 for the deployed PyTorch build, denial of service or memory corruption may follow. This is a conditional impact statement, not a reproduced outcome. Reliable RCE is not claimed.

The opt-in feature, scheduling requirement, and absence of a measured live win rate support Medium/P2 despite the serious historical sink class. No additional deployment assumptions are required for the one-request scheduler beyond stock default-executor concurrency being available.

Remediation

The immediate fix is one shared process-wide lock around every use of this process-global sparse guard. The lock must cover invariant enabling, deserialization, tensor type validation, and dense conversion:

with shared_sparse_load_lock:
    with torch.sparse.check_sparse_tensor_invariants():
        tensor = torch.load(..., weights_only=True, map_location="cpu")
        validate_tensor_type(tensor)
        tensor = tensor.to_dense()

Every prompt, image, and audio loader that manipulates the same global flag must use the same lock. A lock only around torch.load, separate per-loader locks, or a lock omitted from the chat helper would leave overlapping save/restore sequences possible.

The stronger design is to avoid mutable process-global validation state in concurrent request code. Prefer a PyTorch per-call invariant check if one is available, or reconstruct and validate serialized embeddings inside a deliberately serialized boundary before any sparse operation.

Regression coverage should:

  • Preserve the actual-target negative control using the identical malformed payload.
  • Force A-enter, B-enter, A-exit, B-load and assert B remains protected.
  • Execute the multi-part chat tracker with the event loop's default executor and renderer_num_workers=1.
  • Cover cross-loader overlap so later prompt, image, or audio changes cannot bypass a shared fix.
  • Assert the global flag is restored after success and exceptions.
  • Reject invalid tensors before any dense conversion.

Until a fix is deployed, leaving enable_prompt_embeds disabled removes this stock source path.

Summary

The affected vLLM revision uses a process-global PyTorch context as the follow-up protection for CVE-2025-62164. A later chat feature causes two prompt-embedding parts from one request to run concurrently on the default executor. One context can restore the flag to False while the other is still guarded, allowing the historical malformed sparse payload class to reach the historical to_dense() sink. The new issue is the concurrent guard bypass and shipped trigger, not the payload or sink. Runtime validation proves the bypass and safe sink reachability on PyTorch 2.11.0; historical crash and memory-corruption effects remain conditional, and RCE was not tested or claimed.

References

@jperezdealgaba jperezdealgaba published to vllm-project/vllm Jul 27, 2026
Published by the National Vulnerability Database Aug 13, 2026
Published to the GitHub Advisory Database Sep 4, 2026
Reviewed Sep 4, 2026
Last updated Sep 4, 2026

Severity

Moderate

CVSS overall score

This score calculates overall vulnerability severity from 0 to 10 and is based on the Common Vulnerability Scoring System (CVSS).
/ 10

CVSS v4 base metrics

Exploitability Metrics
Attack Vector Network
Attack Complexity Low
Attack Requirements Present
Privileges Required None
User interaction None
Vulnerable System Impact Metrics
Confidentiality None
Integrity None
Availability Low
Subsequent System Impact Metrics
Confidentiality None
Integrity None
Availability None

CVSS v4 base metrics

Exploitability Metrics
Attack Vector: This metric reflects the context by which vulnerability exploitation is possible. This metric value (and consequently the resulting severity) will be larger the more remote (logically, and physically) an attacker can be in order to exploit the vulnerable system. The assumption is that the number of potential attackers for a vulnerability that could be exploited from across a network is larger than the number of potential attackers that could exploit a vulnerability requiring physical access to a device, and therefore warrants a greater severity.
Attack Complexity: This metric captures measurable actions that must be taken by the attacker to actively evade or circumvent existing built-in security-enhancing conditions in order to obtain a working exploit. These are conditions whose primary purpose is to increase security and/or increase exploit engineering complexity. A vulnerability exploitable without a target-specific variable has a lower complexity than a vulnerability that would require non-trivial customization. This metric is meant to capture security mechanisms utilized by the vulnerable system.
Attack Requirements: This metric captures the prerequisite deployment and execution conditions or variables of the vulnerable system that enable the attack. These differ from security-enhancing techniques/technologies (ref Attack Complexity) as the primary purpose of these conditions is not to explicitly mitigate attacks, but rather, emerge naturally as a consequence of the deployment and execution of the vulnerable system.
Privileges Required: This metric describes the level of privileges an attacker must possess prior to successfully exploiting the vulnerability. The method by which the attacker obtains privileged credentials prior to the attack (e.g., free trial accounts), is outside the scope of this metric. Generally, self-service provisioned accounts do not constitute a privilege requirement if the attacker can grant themselves privileges as part of the attack.
User interaction: This metric captures the requirement for a human user, other than the attacker, to participate in the successful compromise of the vulnerable system. This metric determines whether the vulnerability can be exploited solely at the will of the attacker, or whether a separate user (or user-initiated process) must participate in some manner.
Vulnerable System Impact Metrics
Confidentiality: This metric measures the impact to the confidentiality of the information managed by the VULNERABLE SYSTEM due to a successfully exploited vulnerability. Confidentiality refers to limiting information access and disclosure to only authorized users, as well as preventing access by, or disclosure to, unauthorized ones.
Integrity: This metric measures the impact to integrity of a successfully exploited vulnerability. Integrity refers to the trustworthiness and veracity of information. Integrity of the VULNERABLE SYSTEM is impacted when an attacker makes unauthorized modification of system data. Integrity is also impacted when a system user can repudiate critical actions taken in the context of the system (e.g. due to insufficient logging).
Availability: This metric measures the impact to the availability of the VULNERABLE SYSTEM resulting from a successfully exploited vulnerability. While the Confidentiality and Integrity impact metrics apply to the loss of confidentiality or integrity of data (e.g., information, files) used by the system, this metric refers to the loss of availability of the impacted system itself, such as a networked service (e.g., web, database, email). Since availability refers to the accessibility of information resources, attacks that consume network bandwidth, processor cycles, or disk space all impact the availability of a system.
Subsequent System Impact Metrics
Confidentiality: This metric measures the impact to the confidentiality of the information managed by the SUBSEQUENT SYSTEM due to a successfully exploited vulnerability. Confidentiality refers to limiting information access and disclosure to only authorized users, as well as preventing access by, or disclosure to, unauthorized ones.
Integrity: This metric measures the impact to integrity of a successfully exploited vulnerability. Integrity refers to the trustworthiness and veracity of information. Integrity of the SUBSEQUENT SYSTEM is impacted when an attacker makes unauthorized modification of system data. Integrity is also impacted when a system user can repudiate critical actions taken in the context of the system (e.g. due to insufficient logging).
Availability: This metric measures the impact to the availability of the SUBSEQUENT SYSTEM resulting from a successfully exploited vulnerability. While the Confidentiality and Integrity impact metrics apply to the loss of confidentiality or integrity of data (e.g., information, files) used by the system, this metric refers to the loss of availability of the impacted system itself, such as a networked service (e.g., web, database, email). Since availability refers to the accessibility of information resources, attacks that consume network bandwidth, processor cycles, or disk space all impact the availability of a system.
CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:N/VA:L/SC:N/SI:N/SA:N

EPSS score

Exploit Prediction Scoring System (EPSS)

This score estimates the probability of this vulnerability being exploited within the next 30 days. Data provided by FIRST.
(16th percentile)

Weaknesses

Concurrent Execution using Shared Resource with Improper Synchronization ('Race Condition')

The product contains a concurrent code sequence that requires temporary, exclusive access to a shared resource, but a timing window exists in which the shared resource can be modified by another code sequence operating concurrently. Learn more on MITRE.

CVE ID

CVE-2026-73557

GHSA ID

GHSA-pr7f-p5mw-fc87

Source code

Credits

Loading Checking history
See something to contribute? Suggest improvements for this vulnerability.