Le 29 octobre 2026, l’équipe de recherche de Pluto Security a publié un rapport baptisé Load/Mine, révélant une campagne de cryptominage et de backdoor distribuée à travers des dépôts de modèles sur la plateforme Hugging Face. Trente‑et‑une dépôts, répartis sur sept comptes Hugging Face et un miroir sur ModelScope, ont été identifiés, totalisant près de 30 000 téléchargements enregistrés. Le rapport précise que ces chiffres mesurent les téléchargements, pas les infections confirmées.

Comment le code malveillant s’exécute‑t‑il ?

La chaîne d’attaque exploite le comportement documenté de la fonction trust_remote_code=True du framework Transformers. Lors du chargement d’un dépôt, le fichier Python référencé dans le champ auto_map du config.json est importé avec les privilèges de l’utilisateur avant le chargement des poids. Le code du module s’exécute immédiatement via exec_module(). Cette étape, bien décrite dans la documentation, exige que l’utilisateur vérifie le contenu du fichier lorsqu’il active l’option. Le rapport cite également la vulnérabilité CVE‑2026‑22807, qui permettait à certaines versions de vLLM d’ignorer le paramètre de confiance et d’exécuter automatiquement le module.

Découverte et première vague

Pluto a développé un scanner qui analyse chaque fichier .py référencé par auto_map ainsi que les fichiers Python adjacents aux poids. Les patterns recherchés incluent les appels à subprocess, socket, ctypes, memfd_create et le décodage Base64. Le premier dépôt détecté était dsxk4mr8tq/qwen2-tiny-gpt2, contenant un fichier modeling_evil.py de 305 lignes. L’opérateur a créé six dépôts en moins de trois heures le 12 octobre 2026.

La connexion entre les comptes a été révélée par des fichiers de sauvegarde (.bak-src, .bak-sync) qui pointaient vers les comptes hhzz667 (Hugging Face) et wssb123e (ModelScope). Au total, la première vague comptait 12 dépôts sur trois comptes et deux plateformes, avec plus de 700 téléchargements avant leur suppression.

Anatomie du payload

En se basant sur le dépôt MENXIANGYU/qwen2‑tiny, le rapport décrit un chargeur qui écrit /tmp/.cch/svc.py, un watchdog relançant le mineur toutes les 120 secondes. Des hooks sont ajoutés à /root/.bashrc, /root/.profile et au .bashrc de l’utilisateur. Trois variantes incluent une reverse shell vers l’adresse 212.32.253.3, ports 443 ou 9443.

Le binaire du mineur, syscore.bin (40,6 Mo, compressé avec UPX), est lancé via memfd_create et fexecve sous le nom d’un worker kernel kworker/u20:1, évitant ainsi toute trace sur le disque. Une copie de secours persiste dans /tmp/.cch/sync. Après décompression, le binaire, rebaptisé peakminer, se connecte à des pools en utilisant le login krxXJ2PKQW.worker. Le malware écrit également des statuts dans le registre local Xinference sous des noms de type qwen2‑tiny‑<code base32> et supprime les enregistrements concurrents.

Deuxième vague et adaptations

Après la suppression des comptes de la première vague, une seconde vague a émergé huit jours plus tard, avec 19 dépôts répartis sur cinq comptes, dont MENXIANGYU qui compte 13 dépôts. Le dépôt phare MENXIANGYU/qwen2‑tiny est passé de 7 354 téléchargements le 20 octobre à 28 412 le 28 octobre, soit 97,7 % des téléchargements de la seconde vague.

Un des dépôts, MENXIANGYU/qa‑whl‑1021, publié seulement 8,5 heures après le mail de divulgation, proposait un script d’évasion de conteneur vers l’hôte, montait le répertoire /var/lib/gpustack et ouvrait un accès root. Une version ultérieure du dropper ne répondait aux requêtes provenant d’IP non autorisées avec le code 403 et le texte « static ip ».

Revenus et victimes observées

Le portefeuille de la première vague a reçu environ 2 276 PRL (≈ 5 000 $) en 716 transactions, avec 2 241 PRL redistribués. Sur la plateforme Kryptex, le même portefeuille affichait deux workers actifs, générant 1 008 PRL (≈ 2 237 $) en 30 jours. Les workers présentaient des noms de type notebook et ont fonctionné brièvement, suggérant un usage sur des clusters GPUProcesseur conçu pour effectuer de nombreux calculs en parallèle, notamment utilisé pour entraîner et exécuter des modèles d'IA. partagés. Un autre groupe, identifié comme la famille hl, a exploité une technique similaire pour miner du Monero, rapportant environ 26 $ de gains.

Lacunes des scanners de sécurité

Aucun des 12 dépôts de la première vague n’a été détecté par les scanners de Hugging Face. Le payload de la seconde vague a quant à lui été classé « safe » par tous les outils testés, y compris JFrog. La documentation de Hugging Face indique que chaque fichier < 2 Go est scanné à chaque commit, mais que les scans (ClamAV et import‑pickle) ne couvrent pas les exploits d’importation de code. Pluto estime qu’une vérification statique des fichiers .py référencés par auto_map aurait permis de bloquer l’ensemble de la campagne.

Recommandations pour les développeurs

  • Vérifier les modèles chargés avec trust_remote_code=True ; désactiver cette option quand le code source n’est pas audité.
  • Inspecter le répertoire /tmp/.cch/ et rechercher les processus svc.py ou les workers kworker/u20:1 avec des arguments de minage.
  • Contrôler les enregistrements Xinference (qwen2‑tiny‑* ou ezv‑*).
  • Bloquer les connexions sortantes vers les adresses et ports listés dans le rapport.
  • En cas de suspicion, isoler la machine, conserver les preuves, réinitialiser les credentials et repartir d’une image fiable.

Pluto Security avertit que ce type de campagne devrait se multiplier, car la chaîne d’importation de code à chaud dans les modèles LLMUn grand modèle de langage apprend des régularités dans des textes pour produire ou transformer du langage. Il ne constitue pas une base de faits garantie. offre un vecteur d’infection simple à mettre en œuvre et difficile à détecter avec les outils actuels.

Cette menace rappelle que la confiance accordée aux dépôts de modèles open source doit toujours être accompagnée d’une vérification minutieuse du code avant exécution.

Une lecture à partager ?
Partager
Partager cet article
WhatsApp ↗LinkedIn ↗Facebook ↗X ↗E-mail ↗

POUR CONTINUER

Garder le fil.

Toutes les actus ↗