Severity by source
AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
Network-reachable endpoint, default no auth (PR:N/UI:N), low-complexity pickle RCE granting full code execution as the serving process (C:H/I:H/A:H); scope unchanged as impact stays within the process privileges.
Primary rating from Vendor (https://github.com/InternLM/lmdeploy).
CVSS VectorVendor: https://github.com/InternLM/lmdeploy
Lifecycle Timeline
3DescriptionCVE.org
Summary
LMDeploy's PyTorch DistServe/PD-disaggregation control plane used recv_pyobj() to deserialize messages received through a ZeroMQ PULL socket. PyZMQ implements recv_pyobj() using Python pickle deserialization, which can execute arbitrary code while reconstructing an object.
The peer address used by the receiver was supplied through the POST /distserve/p2p_connect HTTP endpoint. An attacker who could reach an affected DistServe API server could cause the server to connect to an attacker-controlled ZeroMQ endpoint and deserialize a crafted pickle payload.
API-key authentication is not enabled unless the operator explicitly configures it. As a result, affected DistServe deployments without API keys allowed unauthenticated remote code execution with the privileges of the LMDeploy serving process.
This issue affects the PyTorch backend when PD-disaggregation/DistServe is enabled. Ordinary deployments that do not use the affected disaggregated-serving path do not expose this data flow.
Affected components
- HTTP entry point:
lmdeploy/serve/openai/endpoints/distserve.py, POST /distserve/p2p_connect
- Attacker-controlled peer address:
DistServeConnectionRequest.remote_engine_endpoint_info.zmq_address
- Vulnerable receiver:
lmdeploy/pytorch/disagg/conn/engine_conn.py, EngineP2PConnection.handle_zmq_recv()
- Unsafe operation:
recv_pyobj(), which performs pickle deserialization
Vulnerable data flow
- A caller submits a DistServe P2P connection request containing a
ZeroMQ address.
- The LMDeploy engine connects its ZeroMQ PULL socket to that address.
handle_zmq_recv()receives messages usingrecv_pyobj().- A malicious peer sends a crafted pickle object.
- Python code executes during deserialization, before LMDeploy can
perform any type or field validation.
A type check performed after recv_pyobj() cannot mitigate this issue because pickle payload execution occurs during deserialization.
Impact
Successful exploitation allows arbitrary code execution as the LMDeploy serving process. This can expose model weights, prompts, credentials, attached storage, cluster-network services, and host or GPU resources. An attacker may also modify or terminate the serving process.
Affected versions
Affected versions:
lmdeploy >= 0.9.2, < 0.16.0
The vulnerable P2P receiver was introduced in commit b0b705f7.
Remediation
The issue was fixed by replacing the pickle-based ZeroMQ protocol with JSON serialization:
send_pyobj()was replaced withsend_json().recv_pyobj()was replaced withrecv_json().- Received objects are validated using the
DistServeCacheFreeRequest Pydantic schema before use.
- Invalid or off-schema messages are rejected without terminating the
receive loop.
Fix commit:
https://github.com/InternLM/lmdeploy/commit/f05b4ad8bf2e2d84101a1d63b3c44fadd99223b2
The fix was released in LMDeploy 0.16.0.
Workarounds
Users who cannot upgrade immediately should:
- Prevent untrusted clients from reaching
/distserve/*endpoints. - Restrict the DistServe HTTP and ZeroMQ control planes to trusted
cluster networks.
- Configure API-key authentication.
- Block arbitrary outbound ZeroMQ connections from serving nodes.
These measures reduce exposure but do not make pickle deserialization safe. Upgrading to LMDeploy 0.16.0 or later is recommended.
Articles & Coverage 1
AnalysisAI
Unauthenticated remote code execution in LMDeploy 0.9.2 through 0.15.x lets any attacker who can reach a DistServe/PD-disaggregation deployment's POST /distserve/p2p_connect endpoint run arbitrary code with the privileges of the LMDeploy serving process. The endpoint accepts an attacker-supplied ZeroMQ peer address; the engine connects to it and deserializes the reply with PyZMQ's recv_pyobj(), which is backed by Python pickle and therefore executes code during object reconstruction, before any type or schema check can run. Rated CVSS 3.1 9.8 (AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H, CWE-502); exploitation is unauthenticated only in the default configuration where the operator has not enabled API-key authentication, and no public exploit code has been identified at time of analysis. A vendor patch is available in LMDeploy 0.16.0, which replaces the pickle-based ZeroMQ protocol with JSON plus Pydantic validation.
Technical ContextAI
The flaw is CWE-502 (Deserialization of Untrusted Data) rooted in the PD-disaggregation (prefill/decode separation, branded DistServe) control plane of LMDeploy's PyTorch backend. In that architecture, separate prefill and decode engine instances communicate over ZeroMQ PUSH/PULL sockets to coordinate cache-freeing between peers. The vulnerable receiver, EngineP2PConnection.handle_zmq_recv() in lmdeploy/pytorch/disagg/conn/engine_conn.py, used PyZMQ's recv_pyobj(), which internally calls pickle.loads() on peer-supplied bytes; pickle's object reconstruction invokes arbitrary callables via __reduce__, so code executes inside the deserialization step itself, defeating any isinstance() or field check written afterwards. The peer address was neither hard-coded nor authenticated: it was taken from DistServeConnectionRequest.remote_engine_endpoint_info.zmq_address submitted to the HTTP route in lmdeploy/serve/openai/endpoints/distserve.py, so an attacker simply points the server's PULL socket at their own ZeroMQ endpoint and sends a crafted pickle. The upstream fix (commit f05b4ad8bf2e2d84101a1d63b3c44fadd99223b2) swaps send_pyobj()/recv_pyobj() for send_json()/recv_json(), validates incoming objects against the DistServeCacheFreeRequest Pydantic schema with model_validate(), and catches ValueError/ValidationError so malformed messages are logged and skipped rather than terminating the receive loop. Affected package is the pip distribution pkg:pip/lmdeploy; the vulnerable receiver was introduced in commit b0b705f7.
RemediationAI
Upgrade to LMDeploy 0.16.0 or later, which is the vendor-released fix for this issue and replaces the pickle wire format with JSON plus DistServeCacheFreeRequest Pydantic schema validation (fix commit: https://github.com/InternLM/lmdeploy/commit/f05b4ad8bf2e2d84101a1d63b3c44fadd99223b2; release: https://github.com/InternLM/lmdeploy/releases/tag/v0.16.0; advisory: https://github.com/InternLM/lmdeploy/security/advisories/GHSA-2vh9-42vm-xmv2). If an immediate upgrade is not possible, apply compensating controls knowing they narrow rather than eliminate the pickle deserialization path: enable API-key authentication on the LMDeploy server so that /distserve/* requires credentials (this restores authentication but does nothing if a key holder is malicious and does not fix the unsafe deserialization itself); restrict the DistServe HTTP endpoint and the ZeroMQ control plane to a trusted cluster network via firewall or reverse-proxy rules so untrusted clients cannot reach /distserve/p2p_connect (this may break legitimate cross-node disaggregated serving if peer ranges are not scoped correctly); and block arbitrary outbound ZeroMQ/TCP connections from serving nodes with egress policy, which limits the attacker's ability to redirect the PULL socket to their own endpoint but can disrupt legitimate peer-to-peer communication between prefill and decode engines if the allowed peer set is not enumerated. Operators who do not need PD-disaggregation should disable DistServe entirely, which removes the affected endpoint and receiver from the running service. Vendor guidance notes that upgrading remains the recommended remedy because workarounds do not make pickle deserialization safe.
Wazuh SIEM platform versions 4.4.0 through 4.9.0 contain an unsafe deserialization vulnerability in the DistributedAPI t
BentoML version 1.4.2 and earlier contains an unauthenticated remote code execution vulnerability through insecure deser
pgAdmin 4 contains critical remote code execution vulnerabilities in the Query Tool download and Cloud Deployment endpoi
The renderLocalView function in render/views.py in graphite-web in Graphite 0.9.5 through 0.9.10 uses the pickle Python
BentoML is a Python library for building online serving systems optimized for AI apps and model inference. Rated critica
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
pyLoad download manager version prior to 0.5.0b3.dev77 exposes the Flask SECRET_KEY through an unauthenticated endpoint.
Langflow (a visual LLM pipeline builder) contains a critical unauthenticated code execution vulnerability (CVE-2026-3301
In Mercurial before 4.1.3, "hg serve --stdio" allows remote authenticated users to launch the Python debugger, and conse
Unauthenticated remote code execution affects Kestra OSS (the open-source event-driven orchestration platform) prior to
Unauthenticated remote code execution in Marimo ≤0.20.4 allows attackers to execute arbitrary system commands via the `/
pyLoad is the free and open-source Download Manager written in pure Python. Rated medium severity (CVSS 5.3), this vulne
Same weakness CWE-502 – Deserialization of Untrusted Data
View allShare
External POC / Exploit Code
Leaving vuln.today
EUVD-2025-210969
GHSA-2vh9-42vm-xmv2