TL;DR

LMCache, the open-source KV-cache layer that speeds up LLM servers such as vLLM, has an unauthenticated remote code execution bug in its multiprocess (distributed) mode: the cache server opens an unauthenticated ZeroMQ socket, and one message type is handed to Python's pickle during argument decoding, before any handler runs. A single crafted message from any host that can reach the port runs code as the LMCache process — root in the project's official container images. JFrog disclosed it on 2026-10-07 as CVE-2026-105192, CVSS 9.8, with no fixed version available at the time. Fixed in 0.5.6, on PyPI since 2026-10-15 (vendor advisory 2026-10-13); the wire format changed, so every worker and server upgrades together. The default bind is localhost and is not exposed; the risk is multi-node and Kubernetes deployments that set a routable --host, which LMCache's own example Kubernetes manifest does.

What happened

LMCache's multiprocess/distributed mode opens a ZeroMQ ROUTER socket (default port 5555) so worker processes can register and share cache blocks, with no CURVE, ZAP, password or per-message authentication. Messages are msgpack; extension code 1 is passed to a deserializer that calls pickle.loads on attacker-supplied bytes while the server is still decoding a REGISTER_KV_CACHE request's arguments and before the handler runs. JFrog's Yuval Moravchick reported it, and JFrog disclosed it on 2026-10-07 as CVE-2026-105192 (JFSA-2026-001694382), CVSS 9.8 (the score applies to the routable configuration), CWE-502 and CWE-306. The vendor had not published an advisory and no fixed version exists; JFrog notes the official container images run the process as root, so a single message means full host compromise. A separate JFrog note records that one GitHub account opened six more LMCache security reports on 2026-10-06 (unauthenticated cross-tenant cache reads and command-running network services), single-source proof-of-concept claims with no CVE, maintainer confirmation or fix — tracked here only as context. Public proof-of-concept code for CVE-2026-105192 has since appeared; this advisory links JFrog's analysis, not any exploit.

This is the same class as the two InternLM LMDeploy RCEs disclosed in September (CVE-2025-66455, CVE-2025-59953 — pickle over ZeroMQ) and the November 2025 ShadowMQ research that found the pattern across several AI inference frameworks: an unauthenticated network socket feeding pickle. The audience overlap for vibe coders is anyone self-hosting vLLM with LMCache for a RAG or agent backend.

Am I affected?

pip show lmcache 2>/dev/null | grep -i version      # 0.3.9 through 0.5.5 (and 0.5.6rc*) are affected; 0.5.6 (2026-10-15) is fixed
# Is the multiprocess server reachable off-box? Default bind is localhost (safe).
# You are exposed only if LMCache runs in multiprocess/distributed mode with a routable --host,
# e.g. a multi-node or Kubernetes deployment binding on all interfaces.
ss -ltnp 2>/dev/null | grep 5555

An LMCache embedded inside a single vLLM process does not open the port and is not remotely exploitable. JFrog gave operators no way to tell whether a server had already been hit; the maintainers' 2026-10-13 guidance (below) is to review connections from unexpected sources, unexpected child processes, shells and outbound connections, and to treat a port reachable from untrusted networks as a compromise.

If you are affected

Upgrade every server and worker to 0.5.6 or later in one step (see the 2026-10-17 update below: the wire format changed and mixed versions do not connect). Until then, keep the LMCache ZMQ transport off routable networks — bind it to localhost or a trusted cluster-internal network only, and do not set --host to a routable address. A firewall reduces exposure but does not remove it, since any host that can open a connection can run code; segment the serving tier and do not run the container as root; official non-root images start at 0.5.6. See agent-sandboxing.md and if-your-webapp-was-compromised.md. If the port was reachable from an untrusted network before the upgrade, treat the host as compromised and rotate what it held.

Update 2026-10-09: still no fix. The CVE record (CNA JFrog, updated 2026-10-07) gives the affected versions as 0.3.9 and later, with no fixed version. PyPI's latest stable is still 0.5.5 (2026-09-12). The newest pre-release, 0.5.6rc3 (2026-10-06), falls inside that range. This advisory keeps the tested range in its title and treats every later version as affected until a fix ships. Do not treat a release candidate as a fix.

Update — 2026-10-17: fixed in 0.5.6 (PyPI 2026-10-15); the vendor advisory and post-mortem (2026-10-13) change the wire format, so every worker and server upgrades together; status → patched

The maintainers published GHSA-w5f2-9q9c-ff4h on 2026-10-13 (account nijaba; CVSS 3.1 9.8, CWE-306; affected >= 0.3.9, < 0.5.6, patched 0.5.6) and a post the same day: JFrog's public disclosure on 2026-10-07 was the first the project heard of it, the fix (PR #5644) merged to the dev branch on 2026-10-12, and 0.5.6 reached PyPI on 2026-10-15. The GitHub Advisory Database published the review on 2026-10-16, which is where this sweep saw it.

What the fix does, from the advisory: the device IPC descriptors that went through pickle are now versioned, typed MessagePack structures, validated first, with the wrapper type chosen from a fixed local allowlist and no pickle fallback. The wire format changed, so old and new processes cannot talk; the maintainers say to upgrade all workers and servers together, and that mixing versions is unsupported. The example Kubernetes deployment, which bound all interfaces, now binds localhost, and official images run as a non-root user from 0.5.6. Still planned, not shipped: RPC authentication between server, coordinator and frontend in 0.5.7, and removal of the remaining pickle use on the engine-driven path, which they describe as disabled by default and not network-reachable, before 0.5.8.

Compromise assessment, in the maintainers' words: if the port was reachable from untrusted networks, treat the host as potentially compromised, review connections from unexpected sources and unexpected child processes, shells or outbound connections, rotate reachable secrets and redeploy from clean images; a rejected request in the logs does not show the attack failed, because exploitation happens before message processing.

Status moves from active to patched on the vendor's explicit fixed version, which is on PyPI. Severity stays critical for the routable configuration. The 2026-10-09 note above ("do not treat a release candidate as a fix") stands for the 0.5.6 release candidates; the 0.5.6 release itself carries the fix.

pip show lmcache 2>/dev/null | grep -i '^version'   # 0.5.6 or later on every server and worker; a mixed cluster will not connect

Prevention

Treat every unauthenticated LLM-infrastructure port as internet-reachable until proven otherwise (supply-chain-attack-surface.md); never expose an inference or cache control plane without authentication and network isolation (ci-cd-hardening.md).

Sources