Un seul message, exécuté en root
L’équipe de recherche en sécurité de JFrog a révélé la CVE-2026-105192 le 7 octobre, en la notant 9,8 et critique. Elle a été trouvée par Yuval Moravchick, de cette même équipe. À la date de l’avis, aucune version corrigée n’existe.
LMCache est la couche de cache clé-valeur que les déploiements vLLM utilisent pour garder les caches d’attention vivants entre les requêtes et entre les machines. En mode multiprocessus, elle ouvre une socket ROUTER ZeroMQ sans chiffrement CURVE, sans authentification ZAP, sans mot de passe et sans aucune authentification des messages. Les messages arrivent en msgpack. Le code d’extension 1 est enregistré pour un type nommé DeviceIPCWrapper, dont la méthode Deserialize appelle le pickle.loads de Python.
Cet appel a lieu pendant que le serveur décode les arguments d’une requête REGISTER_KV_CACHE, avant l’exécution de la moindre logique de traitement. Un unique message non authentifié exécute donc du code sous l’utilisateur du processus LMCache. Les images de conteneur officielles font tourner ce processus en root.
L’exposition tient à un seul paramètre
Le 9,8 n’est pas toute l’histoire, et JFrog le dit. Le transport se lie à localhost sauf si l’exploitant fixe une adresse routable avec --host, et le score critique vaut pour cette configuration routable. Selon les termes de l’avis, “une installation standard sur un seul hôte qui conserve la liaison par défaut n’est pas joignable depuis d’autres machines”.
LMCache utilisé uniquement à l’intérieur d’un processus vLLM n’ouvre pas le port du tout. La forme exposée est le déploiement multinœud — celui vers lequel on se tourne quand une seule machine ne suffit plus, qui est aussi celui qui a le plus de chances de servir du trafic de production.

Pas de correctif, les mesures vous reviennent
Les versions 0.3.9 et ultérieures sont touchées. JFrog demande au projet de remplacer le sérialiseur derrière le code d’extension msgpack 1 par un format sûr, de cesser d’appeler pickle.loads sur des données venant de pairs non authentifiés, d’authentifier le transport avec CURVE ou un HMAC par message, et de refuser une liaison routable si aucune authentification n’est configurée.
En attendant une version corrigée, le conseil aux exploitants est sec : ne pas fixer --host sur une adresse routable, garder le port 5555 sur localhost ou sur un réseau de cluster de confiance, et le protéger par pare-feu. JFrog ajoute la réserve qui compte : quiconque parvient à se connecter peut toujours exécuter du code sous l’utilisateur LMCache.
La même classe de bogue, deux fois en une semaine
Désérialiser avec pickle des données venues du réseau est une erreur Python documentée depuis vingt ans, et elle apparaît désormais dans la plomberie du service de modèles. Au Pwn2Own d’Irlande, la même semaine, LiteLLM est tombé dès le premier jour sur une validation d’entrée défaillante enchaînée à une injection de code, pour 40 000 dollars, et une seconde équipe l’a emporté avec quatre bogues de plus.
La part proprement IA de l’affaire n’est pas la vulnérabilité. C’est qu’une couche de cache placée entre un serveur de modèles et ses GPU a été construite avec un plan de contrôle non authentifié, parce qu’on a supposé que le déploiement vivrait sur un réseau de confiance.

Ce qu’il faut vérifier ce soir
Deux questions règlent l’essentiel : le port 5555 est-il joignable depuis autre chose que l’hôte, et le conteneur tourne-t-il en root ? Si la réponse est oui aux deux, l’avis décrit un chemin allant d’un seul paquet à un shell sur une machine où reposent vos poids de modèle.
Ce qu’il faut surveiller, c’est la version corrigée. D’ici là, il s’agit d’un trou connu, noté et publiquement documenté, avec un délai de correctif, dans un composant que la plupart des équipes faisant tourner vLLM à grande échelle ont moins choisi qu’hérité.