Un fichier de configuration n'est pas censé exécuter quoi que ce soit

Un développeur d'un industriel européen récupère un modèle sur un hub public, appelle from_pretrained et part déjeuner. La bibliothèque télécharge les poids, lit le fichier JSON qui les décrit, puis initialise. Rien dans cette séquence ne ressemble à un consentement à exécuter le code d'un inconnu, et le développeur a déjà positionné trust_remote_code sur False pour que ce ne soit pas le cas.

Les chercheurs de Pluto Security ont démontré le contraire. La faille est suivie sous la référence CVE-2026-4372, affiche un score CVSS de base de 7,8 et relève de la classe CWE-502, désérialisation de données non fiables. Elle transforme un simple téléchargement de modèle en exécution de code Python arbitraire sur la machine qui télécharge, et l'action requise de l'utilisateur n'est rien d'autre que la manière documentée de charger un modèle.

Comment un champ de métadonnées a contourné le flag

Le flag protège les fichiers de code. L'attaque est arrivée par les métadonnées. Le constructeur de configuration contenait une boucle qui reprenait chaque clé et chaque valeur du JSON non fiable pour les écrire directement sur l'objet de configuration, sans liste blanche ni validation. Parmi les champs qu'un attaquant pouvait ainsi définir figurait _attn_implementation_internal, un attribut interne privé que personne n'imaginait accessible depuis un fichier téléchargé.

Lorsque ce champ contenait une chaîne de la forme propriétaire et dépôt, le chargeur de kernels la traitait comme un package à récupérer sur le hub et l'importait sans aucun contrôle de sécurité. Tout code Python placé dans le fichier d'initialisation de ce dépôt s'exécutait alors. Le mécanisme de consentement sur lequel les développeurs comptent n'a jamais été sollicité, parce qu'il ne couvrait que le code de modélisation personnalisé, et il ne s'agissait pas de code de modélisation personnalisé. Il s'agissait d'un fichier de paramètres.

Le correctif est arrivé en premier. L'avertissement a mis 81 jours de plus

Ce sont les dates qui racontent l'histoire. Le code vulnérable est entré dans la bibliothèque le 29 août 2025 et a été embarqué dans chaque release pendant environ six mois. La faille a été signalée via un bug bounty le 23 février 2026, un mainteneur a ouvert le correctif le 2 mars, et la version 5.3.0 l'a refermée le 4 mars. C'est une réaction rapide et tout à son honneur, dix jours entre le signalement et la release corrigée.

Puis le registre public s'est tu. La CVE-2026-4372 n'a été publiée que le 24 mai 2026, soit 81 jours après que le correctif se trouvait déjà dans une release publique. Dans cet intervalle, le correctif était décrit dans les notes de release comme un problème de sécurité lié à kernels, sans numéro de CVE, sans gravité et sans indiquer qu'il fermait une exécution de code à distance. Tout opérateur dont l'application des correctifs est déclenchée par les flux CVE et les avis des éditeurs, c'est-à-dire la plupart des opérateurs régulés en Europe, n'avait aucun signal pour prioriser une mise à niveau pourtant déjà disponible.

Puis le hub lui-même a été compromis par le même type de porte

Le 16 juillet 2026, Hugging Face a révélé une intrusion dans une partie de sa propre infrastructure de production. Un jeu de données malveillant a détourné deux chemins d'exécution de code dans le traitement des jeux de données, un chargeur de jeu de données à code distant et une injection de template dans une configuration de jeu de données, pour s'exécuter sur un worker de traitement. De là, l'intrus a obtenu l'accès au node, récolté des identifiants cloud et cluster, puis s'est déplacé latéralement vers plusieurs clusters internes au cours d'un week-end. L'analyse forensique a passé en revue plus de 17 000 actions enregistrées.

Hugging Face indique n'avoir trouvé aucune preuve d'altération de modèles, de jeux de données ou de Spaces publics, et avoir vérifié l'intégrité de sa chaîne d'approvisionnement logicielle. Il faut lire cet incident comme la démonstration du chemin d'escalade, et non comme une raison de se défier du hub. Un fichier qui décrit des données a atteint un worker, et ce worker détenait des identifiants. Voilà la forme du risque, et c'est exactement la même forme que la faille de configuration décrite plus haut.

Ce qu'il faut trancher avant votre prochain téléchargement de modèle

Trois vérifications, dans cet ordre. Établissez quelle version de transformers tourne dans vos images d'entraînement, vos notebooks et vos agents de build, et mettez à niveau tout ce qui se situe en dessous de la 5.3.0. Déterminez ensuite si le package kernels est installé à côté, puisque c'est lui qui rendait le chemin exploitable. Regardez enfin quels identifiants se trouvent sur les machines qui analysent les artefacts de modèles et de jeux de données, car ces machines sont généralement traitées comme de la simple tuyauterie technique et dotées en conséquence de droits très larges.

L'obligation de notification, elle, suit son propre calendrier. En vertu de l'article 23 de la directive NIS2, une entité entrant dans son champ doit adresser à son autorité nationale une alerte précoce dans les 24 heures suivant la prise de connaissance d'un incident important, une notification plus complète dans les 72 heures et un rapport final dans un délai d'un mois. En France, les orientations équivalentes émanent de l'ANSSI. Aucune de ces échéances ne se suspend pendant que vous déterminez quelle version de la bibliothèque vous faisiez tourner.