
OpenMed < 1.5.2 RCE non authentifié via le chargement du modèle de filtre de confidentialité PII et trust_remote_code=True
Gravité : Critique, CVSS 4.0 9.3, CVSS 3.1 9.8 (attribuée par VulnCheck, la CNA)
Vecteur (v4.0) : CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N
Vecteur (v3.1) : CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
Affecté : OpenMed < 1.5.2
Corrigé dans : 1.5.2
CWE : CWE-94 (Contrôle inapproprié de la génération de code, injection de code)
Découvert et signalé par : Sai Teja Erukude
Publié : 2 juin 2026
OpenMed antérieur à 1.5.2 contient une vulnérabilité d'exécution de code à distance non authentifiée dans le chemin de chargement du modèle de filtre de confidentialité PII.
Les points de terminaison de l'API REST POST /pii/extract et POST /pii/deidentify acceptent une valeur model_name issue du corps de la requête. Dans les versions vulnérables, le répartiteur du filtre de confidentialité utilisait une correspondance de sous-chaîne large sur cette valeur contrôlée par l'attaquant. Un nom de modèle tel que attacker/foo-privacy-filter-bar pouvait donc être routé vers le backend du filtre de confidentialité.
Sur les déploiements non-MLX/Torch, ce backend chargeait les artefacts de modèle Hugging Face via Transformers avec trust_remote_code=True. Si le dépôt de modèle contrôlé par l'attaquant contenait du code Transformers personnalisé référencé via auto_map dans config.json ou tokenizer_config.json, Transformers importait et exécutait ce code Python lors du chargement du modèle ou du tokenizer.
Le code importé s'exécutait avec les privilèges du processus du service OpenMed.
Un attaquant distant non authentifié capable d'atteindre l'API REST d'OpenMed peut exécuter du code Python arbitraire sur le serveur en fournissant un identifiant de modèle de style Hugging Face malveillant dans model_name.
Selon le déploiement du service, cela peut permettre :
Le problème est atteignable via les deux points de terminaison PII, car tous deux acceptent model_name et utilisent le même chemin d'extraction PII/chargement de modèle :
POST /pii/extract
Content-Type: application/json
{
"text": "John Doe called 555-1212",
"model_name": "attacker/foo-privacy-filter-bar",
"confidence_threshold": 0.0
}
POST /pii/deidentify
Content-Type: application/json
{
"text": "John Doe called 555-1212",
"model_name": "attacker/foo-privacy-filter-bar",
"confidence_threshold": 0.0
}
Le flux de contrôle vulnérable présente deux défaillances de frontière de confiance :
model_name fourni par l'utilisateur lors de la sélection du backend de filtre de confidentialité.trust_remote_code=True.Le répartiteur traitait tout identifiant de modèle contenant privacy-filter comme appartenant à la famille des filtres de confidentialité. Cela permettait à des identifiants contrôlés par l'attaquant, par exemple attacker/foo-privacy-filter-bar, d'atteindre un chemin de code destiné aux modèles Privacy Filter de première partie dignes de confiance.
Une fois routé vers ce chemin, Transformers pouvait charger du code personnalisé contrôlé par l'attaquant via auto_map. Cette importation se produit lors du chargement du modèle/tokenizer, avant qu'une quelconque inférence utile n'ait à réussir. Une charge utile de preuve peut donc être aussi réduite que :
from pathlib import Path
Path("marker.txt").write_text(
"custom Transformers code executed via trust_remote_code\n",
encoding="utf-8",
)
poc_exploit.py construit un répertoire de modèle local inoffensif au format Hugging Face dont le nom contient privacy-filter. Les modules Transformers personnalisés générés écrivent un fichier marqueur lors de leur importation. Le script envoie ensuite une requête à une instance de test de l'API OpenMed avec ce répertoire comme model_name.
Le comportement attendu sur les versions vulnérables d'OpenMed est le suivant :
model_name contrôlé par l'attaquant.trust_remote_code=True.À exécuter uniquement contre une instance de test locale :
pip install -r requirements.txt
python poc_exploit.py --target http://127.0.0.1:8000 --endpoint /pii/extract
Si le service OpenMed s'exécute dans un environnement qui ne peut pas accéder au répertoire local généré, publiez un modèle de test équivalent dans un dépôt Hugging Face contrôlé et transmettez cet identifiant explicitement :
python poc_exploit.py \
--target http://127.0.0.1:8000 \
--model-name your-org/foo-privacy-filter-bar \
--marker marker.txt
Mettez à niveau vers OpenMed 1.5.2 ou une version ultérieure.
OpenMed 1.5.2 sépare le routage de la confiance :
privacy-filter ne sont plus routés via le chemin de confiance privacy-filter.PrivacyFilterTorchPipeline définit trust_remote_code sur False par défaut.OPENMED_TRUSTED_REMOTE_CODE_MODELS.Si une mise à niveau immédiate n'est pas possible :
model_name contrôlées par l'utilisateur à Transformers avec trust_remote_code=True.| Date | Événement |
|---|---|
| 18 mai 2026 | Vulnérabilité soumise à VulnCheck |
| 20 mai 2026 | VulnCheck a initié la démarche de divulgation coordonnée |
| 22 mai 2026 | CVE-2026-47117 attribuée provisoirement |
| 1er juin 2026 | Correctif OpenMed 1.5.2 examiné et confirmé |
| 2 juin 2026 | CVE-2026-47117 publiée |
Découverte et signalée par Sai Teja Erukude.
La divulgation a été coordonnée via VulnCheck.