CVE-2025-66455 Overview
CVE-2025-66455 is a critical insecure deserialization vulnerability in LMDeploy, a toolkit for compressing, deploying, and serving large language models. The flaw affects versions 0.9.2 through 0.15.x when the PyTorch DistServe (PD-disaggregation) control plane is enabled. The control plane calls recv_pyobj() on a ZeroMQ PULL socket, which uses Python pickle deserialization internally. An attacker who reaches the DistServe API server can force the process to connect to an attacker-controlled ZeroMQ endpoint and execute arbitrary code. API-key authentication is not enabled by default, exposing unauthenticated deployments to full remote code execution [CWE-502].
Critical Impact
Unauthenticated remote code execution with the privileges of the LMDeploy serving process on DistServe-enabled deployments.
Affected Products
- LMDeploy versions 0.9.2 through 0.15.x (PyTorch backend with PD-disaggregation/DistServe enabled)
- Deployments exposing the /distserve/p2p_connect HTTP endpoint
- LMDeploy DistServe control planes without API-key authentication configured
Discovery Timeline
- 2026-09-18 - CVE-2025-66455 published to NVD
- 2026-09-23 - Last updated in NVD database
- LMDeploy 0.16.0 - Vendor releases fixed version replacing pickle with JSON for P2P ZMQ requests
Technical Details for CVE-2025-66455
Vulnerability Analysis
The vulnerability resides in the PyTorch DistServe control plane responsible for peer-to-peer connections between disaggregated serving nodes. The receiver invokes PyZMQ's recv_pyobj(), which reconstructs Python objects via pickle.loads(). Pickle deserialization executes arbitrary constructors and __reduce__ methods, permitting native code execution when the payload is attacker-controlled.
The DistServe HTTP API exposes a POST /distserve/p2p_connect endpoint that accepts a peer address from the client. The server then opens a ZeroMQ connection to that address and reads incoming messages with recv_pyobj(). This design allows any reachable client to redirect the connection target to an attacker-operated ZeroMQ endpoint.
Because API-key authentication is opt-in, most deployments accept unauthenticated requests. The result is unauthenticated remote code execution on any DistServe node reachable over the network. Ordinary LMDeploy deployments that do not use PD-disaggregation are not exposed to this data flow.
Root Cause
The root cause is the use of recv_pyobj() on data sourced from an untrusted network peer. Pickle deserialization is not safe for untrusted input, and the peer address itself is supplied through an unauthenticated HTTP endpoint. Together, these design choices make code execution reachable without authentication.
Attack Vector
An attacker with network reachability to the DistServe HTTP API server sends a POST /distserve/p2p_connect request specifying an attacker-controlled ZeroMQ endpoint. The LMDeploy process opens a PULL socket to that endpoint. The attacker then delivers a crafted pickle payload that executes commands under the LMDeploy process account.
# Security patch: lmdeploy/pytorch/disagg/conn/engine_conn.py
# fix(disagg): use JSON instead of pickle for P2P ZMQ requests (#4804) (#4812)
import zmq
import zmq.asyncio
from pydantic import ValidationError
from lmdeploy.logger import get_logger
from lmdeploy.pytorch.disagg.conn.protocol import (
# ...protocol imports...
)
# The fix replaces recv_pyobj()/send_pyobj() with JSON-based
# serialization validated by pydantic models, eliminating
# pickle deserialization on the P2P control channel.
Source: GitHub commit f05b4ad
Detection Methods for CVE-2025-66455
Indicators of Compromise
- Unexpected POST /distserve/p2p_connect requests from clients outside the trusted cluster network
- Outbound ZeroMQ (tcp://) connections from LMDeploy serving nodes to non-cluster IP addresses
- Child processes spawned by the LMDeploy Python interpreter (shells, curl, wget, package managers)
- New listeners, cron jobs, or SSH keys added on hosts running the LMDeploy PyTorch backend
Detection Strategies
- Inspect HTTP access logs on DistServe API servers for /distserve/* calls sourced from untrusted networks
- Monitor process telemetry for python or LMDeploy worker processes executing shell commands or spawning interpreters
- Alert on egress ZeroMQ connections initiated by inference nodes to addresses outside the cluster CIDR
- Detect deserialization exploitation patterns by looking for pickle opcode signatures on control-plane traffic captures
Monitoring Recommendations
- Ingest LMDeploy application logs, host process telemetry, and network flow data into a centralized analytics platform
- Baseline normal /distserve endpoint callers and alert on new source IPs
- Track LMDeploy version inventory across GPU nodes to identify unpatched installations
- Correlate DistServe HTTP requests with subsequent outbound ZMQ connections and process activity for post-exploitation evidence
How to Mitigate CVE-2025-66455
Immediate Actions Required
- Upgrade LMDeploy to version 0.16.0 or later, which replaces pickle with JSON on the P2P ZMQ channel
- Block network access to /distserve/* endpoints from untrusted clients at the reverse proxy or ingress controller
- Enable API-key authentication on all LMDeploy DistServe deployments
- Audit LMDeploy hosts for signs of exploitation prior to patching
Patch Information
The fix is available in LMDeploy release v0.16.0. The patch in commit f05b4ad8 migrates the P2P ZeroMQ request format from pickle to JSON validated by pydantic models. Details are documented in GitHub Security Advisory GHSA-2vh9-42vm-xmv2.
Workarounds
- Restrict DistServe HTTP and ZeroMQ control planes to trusted cluster networks using firewalls or network policies
- Configure API-key authentication so unauthenticated callers cannot invoke /distserve/p2p_connect
- Block arbitrary outbound ZeroMQ connections from serving nodes with egress firewall rules
- Disable PD-disaggregation/DistServe entirely if it is not required for the deployment
# Example egress restriction and upgrade for LMDeploy DistServe nodes
pip install --upgrade "lmdeploy>=0.16.0"
# Restrict inbound access to the DistServe API to the cluster subnet only
iptables -A INPUT -p tcp --dport 23333 -s 10.0.0.0/24 -j ACCEPT
iptables -A INPUT -p tcp --dport 23333 -j DROP
# Block outbound ZMQ connections outside the trusted cluster range
iptables -A OUTPUT -p tcp --dport 5555:5600 ! -d 10.0.0.0/24 -j DROP
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.
