
Notícia
Pacote malicioso do LiteLLM ficou quase 3 horas no ar e foi baixado mais de 49 mil vezes
Resumo: em 21 de outubro de 2026, atacantes publicaram uma versão maliciosa do LiteLLM (biblioteca Python de código aberto que funciona como proxy para dezenas de provedores de modelos de linguagem) no PyPI e nas imagens oficiais de container. A versão 1.107.0 ficou disponível por cerca de três horas e foi baixada mais de 49 mil vezes. A carga maliciosa roda a cada início do interpretador Python — mesmo que o LiteLLM nunca seja importado — e rouba credenciais de nuvem, de ferramentas de IA e de navegadores. O caminho do ataque começou com tokens de acesso do GitHub CLI roubados de dentro de logs de um gateway de IA: o pipeline de release da própria LiteLLM foi apontado para um repositório sósia que difere do original por um único hífen.
Introdução
O LiteLLM é uma peça de infraestrutura que passou a sustentar boa parte das empresas que usam IA generativa. Ele funciona como uma camada única de acesso: em vez de cada aplicação guardar as chaves de OpenAI, Anthropic, Google e outras dezenas de provedores, tudo passa pelo LiteLLM, que centraliza chamadas, custos, limites e credenciais. São cerca de 23 milhões de downloads semanais só no PyPI.
Em 21 de outubro de 2026, esse ponto de centralização virou a superfície de um ataque de cadeia de suprimentos — aquele tipo de ataque que não invade o seu sistema: ele entrega o código malicioso dentro de algo em que você confia.
O que aconteceu, em resumo: a versão 1.107.0 foi publicada normalmente nos canais oficiais do projeto — PyPI, Docker Hub e GHCR (GitHub Container Registry, o registro de imagens do GitHub) — mas construída a partir de um repositório controlado pelo atacante. Os artefatos carregavam uma proveniência de build aparentemente legítima que registrava fielmente o fork malicioso como origem. Quem instalou no intervalo certo executou o malware.
A própria LiteLLM conduziu a investigação e publicou um relatório detalhado poucas horas depois, com a linha do tempo completa e a análise de como o ataque furou um pipeline que já tinha sido endurecido depois de um incidente anterior em março. É esse relato, somado à análise técnica publicada pelo Datadog Security Labs (time de pesquisa da Datadog), que sustenta os detalhes abaixo.
Duas horas no ar, mais de 49 mil downloads
A janela de exposição foi curta, mas o alcance não. Como o LiteLLM é uma dependência de infraestrutura — e não uma biblioteca que alguém instala uma vez —, o intervalo de poucas horas é justamente o momento em que os builds automatizados de milhares de projetos rodam.
| Plataforma | Artefatos afetados | Janela de exposição |
|---|---|---|
| PyPI | litellm 1.107.0 (sete wheels) | 11:39:51 a 13:23 UTC |
| Docker Hub | tags v1.107.0, latest, main-latest e main-stable | 11:46:56 a 14:20 UTC |
| GHCR | mesmas quatro tags | 11:46:56 até 13:51 UTC |
O número de mais de 49 mil downloads da versão comprometida é uma estimativa baseada nas estatísticas públicas de download do PyPI. A LiteLLM também confirmou um detalhe relevante para o mundo corporativo: clientes Enterprise que usam o registry privado não foram afetados, porque aquela distribuição é separada.
A tag de código-fonte oficial da versão 1.107.0, no GitHub, não continha os arquivos maliciosos. Isso é importante para entender o tipo de ataque: o código-fonte público estava limpo — o que foi envenenado foi o processo de compilação.
Como o ataque funcionou
O relatório da LiteLLM descreve o ataque como uma sequência de barreiras que precisaram cair uma a uma. O pipeline de release da empresa é deliberadamente rígido: a publicação final só pode ser feita por uma conta presa a um notebook específico, fisicamente dentro do escritório, e nenhuma imagem Docker é reconstruída na hora da publicação.
Cadeia do comprometimento do release
A linha do tempo divulgada pela empresa mostra que o ataque foi conduzido em ritmo de operação, com três credenciais diferentes usadas para funções distintas — e com uma etapa dedicada a apagar os próprios rastros.
"Berri-AI" e "BerriAI": um hífen de diferença
Um dos detalhes mais reveladores do caso é o nome escolhido para o repositório falso: Berri-AI/litellm. O repositório legítimo é BerriAI/litellm.
A diferença é um único hífen. O objetivo declarado pela análise é claro: escapar de uma revisão humana casual. Quem olhasse o log da execução veria um nome de organização plausível, na grafia correta do projeto, e provavelmente não notaria. E, como o pipeline publicava com assinatura e metadados de procedência, o artefato resultante parecia — para qualquer ferramenta automática — tão legítimo quanto os anteriores.
É uma variante sofisticada do typosquatting (registro de nomes propositalmente parecidos com os originais para enganar quem digita ou lê rápido), só que aplicada ao repositório de código-fonte em vez do nome do pacote. O alvo não é quem digita errado: é o revisor que lê rápido.
De onde vieram os tokens: um segredo dentro de um log
A parte mais desconfortável do relatório é a origem das credenciais.
Segundo a LiteLLM, os atacantes tinham acesso a três conjuntos de credenciais do GitHub CLI pertencentes a desenvolvedores da empresa. Uma delas podia executar workflows; outra, segundo a investigação, pertencia a um dos dois proprietários da organização no GitHub — o que explica como a proteção de branch pôde ser desativada.
E o caminho até essas credenciais passa por um detalhe que interessa a qualquer equipe que use agentes de programação:
"Após uma investigação minuciosa, observamos situações específicas em que o Claude Code embute o token OAuth do GitHub CLI de um usuário no corpo de uma resposta, e em situações em que os corpos das respostas são registrados, esses tokens podem aparecer nos logs do LiteLLM."
A LiteLLM identificou ainda uma conta de usuário inesperada, com nome inócuo, dentro da sua implantação interna do LiteLLM, exposta à internet. A hipótese é que o atacante tenha acessado essa implantação, extraído os tokens de dentro dos logs e usado essas credenciais para comprometer o pipeline de release. A empresa ainda não confirmou como o invasor entrou nessa implantação, mas suspeita de uma vulnerabilidade recém-corrigida.
Há uma ironia amarga aqui: a própria ferramenta que centraliza o acesso a modelos de IA virou o cofre involuntário dos segredos que derrubaram o seu release. Log de aplicação que registra corpo de requisição é, na prática, um arquivo de credenciais.
O que a carga maliciosa faz
A análise do Datadog Security Labs descreve três arquivos que o pacote malicioso deixava cair na pasta site-packages do ambiente Python: cook.pth, cook.py e sitecustomize.py.
O detalhe decisivo é o mecanismo: o Python executa arquivos do tipo .pth e o sitecustomize.py automaticamente toda vez que o interpretador inicia. Isso significa que qualquer processo Python naquele ambiente roda o malware — mesmo que o LiteLLM nunca seja importado. Um script simples, uma ferramenta de linha de comando, um job de build: todos passam pelo mesmo caminho de inicialização.
A partir daí, dois componentes entram em ação:
O roubador de credenciais. O arquivo cook.py coleta segredos e os envia criptografados (combinação de AES-256 com RSA-4096) para o domínio litellm[.]dev — um endereço sósia do site oficial, criado só para receber os dados. Os alvos estão listados abaixo.
O backdoor. O sitecustomize.py consulta a cada hora um arquivo hospedado em um repositório fixo no GitHub, buscando um domínio de onde baixar e executar código Python. O arquivo em questão só continha valores de teste e já foi removido, então nenhum segundo estágio foi observado em campo — o atacante tinha o canal pronto, mas não chegou a usá-lo.
| Alvo | O que é coletado |
|---|---|
| Nuvem | Credenciais AWS, GCP e Azure (inclusive do serviço de metadados da instância), mais segredos de Kubernetes, Docker, Vault e Terraform |
| Desenvolvedor | Chaves SSH, GPG e TLS, tokens de Git, npm e PyPI, arquivos de variáveis de ambiente e histórico de shell |
| Ferramentas de IA | Chaves de API de provedores de LLM e sessões de assistentes de código como Claude, Codex, Gemini, Cursor e Copilot |
| Navegadores | Senhas salvas e cookies |
| O próprio proxy | Se um banco de dados estiver configurado, as tabelas onde o LiteLLM guarda as credenciais dos provedores |
Vale registrar um detalhe contraintuitivo e importante para quem for limpar um ambiente afetado: apagar a pasta do litellm não remove nada disso. Os três arquivos ficam em site-packages e continuam sendo executados. Pior: rodar o python ou o pip do próprio ambiente dispara o malware outra vez — inclusive o pip.
O que fazer se a 1.107.0 passou pelo seu ambiente
A orientação da LiteLLM, complementada pelo Datadog, começa com um aviso que contraria o instinto: não comece rodando pip install. Qualquer inicialização do Python naquele ambiente executa o cook.pth e o sitecustomize.py novamente.
Remova os arquivos primeiro. Apague cook.pth, cook.py e sitecustomize.py de todos os diretórios site-packages afetados, junto com os arquivos compilados correspondentes nas pastas __pycache__. Depois, encerre o processo Python destacado que o malware deixa rodando — ele mantém um arquivo de trava em /tmp e garante que apenas uma instância do roubador opere por vez.
# 1. localizar os rastros do pacote malicioso no ambiente
pip show litellm
find / -name "cook.pth" -o -name "cook.py" -o -name "sitecustomize.py" 2>/dev/null
# 2. remover os arquivos e os compilados correspondentes
find / -path "*/site-packages/cook.*" -delete
find / -path "*/site-packages/__pycache__/cook*.pyc" -delete
find / -path "*/site-packages/sitecustomize.py" -delete
# 3. encerrar o processo que segura a trava do roubador
ls -la /tmp/remote_code_loader.lock
# 4. reinstalar fixado na última versão segura
pip install "litellm==1.106.2"Reconstruir imagens e ambientes virtuais do zero, em vez de tentar limpar o existente, é a opção mais segura.
Assuma que a exfiltração funcionou. A regra prática é dura e correta: se a versão 1.107.0 foi instalada em uma máquina com saída para a internet, trate os segredos como comprometidos. Se o arquivo marcador que o malware cria estiver presente, o vazamento está confirmado; se não estiver, isso não prova que o ambiente está limpo — containers e rotinas de limpeza de arquivos temporários apagam esse rastro.
Rotacione tudo o que aquela máquina alcançava. Isso inclui a credencial de instância ou de task na nuvem, todas as chaves de provedor guardadas no banco do proxy LiteLLM (mais as chaves master e virtuais), a senha da conexão com o banco de dados e qualquer segredo que estivesse no ambiente de qualquer processo da máquina. Para quem usa AWS, o passo de verificação é procurar, no CloudTrail (serviço que registra chamadas de API na conta), chamadas de identificação da credencial da instância na hora da instalação — e depois o uso dessas mesmas credenciais de fora da sua infraestrutura.
Verifique o que dá para verificar. Esta lista de indicadores reúne os artefatos públicos do incidente. Domínios e endereços IP aparecem desativados de propósito, para não virar link clicável:
| Indicador | O que é |
|---|---|
| litellm.dev | Domínio sósia usado para exfiltração |
| X-Token: XWiA8gZNa7NcX2XRoAEb | Cabeçalho HTTP no envio dos dados roubados |
| raw.githubusercontent.com/letters9813/pythonclient-test | Repositório usado como ponto de entrega do backdoor |
| /tmp/.pc_once_72129118c59f5636c0bb | Arquivo criado após execução bem-sucedida do roubador |
| /tmp/remote_code_loader.lock | Trava que garante uma única instância do roubador |
| cook.pth · cook.py · sitecustomize.py | Arquivos maliciosos deixados em site-packages |
| sha256:1bbcb1443bc962e45f5aad53fe3d2c30600e0379715fb6c664cdd3ac126c339e | Índice de imagem infectada no Docker Hub e no GHCR |
A segunda vez no mesmo ano
Uma informação que muda a leitura do caso: não foi o primeiro comprometimento do LiteLLM em 2026. Em março, as versões 1.82.7 e 1.82.8 foram comprometidas, em uma campanha que o Datadog Security Labs atribuiu à atividade do grupo TeamPCP (campanha de ataque à cadeia de suprimentos de pacotes Python). Até agora não há conexão estabelecida entre os dois incidentes.
O que o histórico revela é que a resposta ao primeiro incidente foi séria. Depois de março, a LiteLLM moveu os releases para um repositório privado, adotou Trusted Publishers do GitHub, tornou as tags de imagem Docker imutáveis e passou a assinar as imagens. Ainda assim, o ataque de outubro atravessou tudo isso — não quebrando a criptografia nem explorando um erro de código, mas usando credenciais legítimas para apontar um pipeline confiável para o lugar errado.
É a lição central do caso, e ela vale para qualquer equipe que publica software: um pipeline de release é tão confiável quanto o conjunto de pessoas e tokens que podem alterá-lo. Controles como assinatura e procedência de build provam de onde o artefato veio — e, neste caso, eles registraram a verdade: o artefato veio do repositório sósia. O que faltou foi impedir que alguém com uma credencial roubada pudesse mudar a origem.
Conclusão
O incidente do LiteLLM é um retrato preciso de onde a cadeia de suprimentos de software está frágil em 2026. Não foi um atacante quebrando um servidor: foi um atacante usando as ferramentas certas com as credenciais certas para que a vítima publicasse o malware por conta própria.
Três aprendizados sustentam o caso. O primeiro é sobre tokens de desenvolvedor: eles deixaram de ser credenciais de conveniência e passaram a ser o ativo mais valioso de um projeto. Uma única credencial com permissão de escrita em organização permite desativar proteções, trocar a origem de um build e apagar os registros depois. Tratar token de CLI com o mesmo rigor de uma chave de produção deixou de ser exagero.
O segundo é sobre logs. Registro de aplicação que guarda corpo de requisição é, com frequência, um arquivo de segredos disfarçado. No caso, um token de acesso real viajou dentro do corpo de uma resposta de um agente de IA e foi parar em um log de uma implantação exposta à internet. Revisar o que se registra — e por quanto tempo — é uma tarefa de segurança, não de operação.
O terceiro é sobre a diferença entre alcançável e autorizado. Assinatura de imagem, procedência de build e tags imutáveis são controles valiosos, mas todos operam depois da decisão de qual repositório construir. Garantir que apenas repositórios aprovados possam ser origem de um release não é refinamento: é o controle que teria bloqueado este ataque.
Perguntas frequentes
Eu uso LiteLLM. Meu ambiente está comprometido?
Depende de qual versão e de quando. O comprometimento atinge apenas a versão 1.107.0 publicada no PyPI entre 11:39 e 13:23 UTC de 21 de outubro de 2026, e as tags v1.107.0, latest, main-latest e main-stable das imagens no Docker Hub e no GHCR entre 11:46 e 14:20 UTC. Todas as versões anteriores são seguras. Clientes Enterprise que usam o registry privado não foram afetados.
Por que apagar a pasta do pacote não resolve?
Porque o malware não vive dentro da pasta do LiteLLM. Ele deixa três arquivos em site-packages — cook.pth, cook.py e sitecustomize.py — que o Python executa automaticamente a cada inicialização do interpretador, independentemente de o LiteLLM ser importado ou não. Por isso a limpeza precisa remover esses arquivos especificamente, e não apenas desinstalar o pacote.
O código-fonte oficial estava infectado?
Não. A tag de código-fonte oficial da versão 1.107.0 no GitHub não continha os arquivos maliciosos. Os artefatos comprometidos foram compilados a partir de um repositório controlado pelo atacante, Berri-AI/litellm, que difere do repositório real, BerriAI/litellm, por um único hífen. O que foi comprometido foi o processo de build, não o código publicado.
Como os atacantes conseguiram as credenciais?
Segundo a investigação da LiteLLM, eles obtiveram tokens OAuth do GitHub CLI pertencentes a três desenvolvedores. A hipótese é que tenham acessado uma implantação interna do próprio LiteLLM, com nome de usuário inócuo, que estava exposta à internet, e retirado os tokens de dentro dos logs. A empresa notou que o Claude Code, em certas situações, embute o token do GitHub CLI do usuário no corpo de uma resposta — e quando esse corpo é registrado, o token vai para o log. Ainda não foi confirmado como o atacante entrou nessa implantação; a suspeita recai sobre uma vulnerabilidade recém-corrigida.
O que a carga maliciosa roubava?
Credenciais de nuvem (AWS, GCP e Azure, inclusive do serviço de metadados de instância), segredos de Kubernetes, Docker, Vault e Terraform; chaves e tokens de desenvolvedor (SSH, GPG, TLS, Git, npm, PyPI), arquivos de variáveis de ambiente e histórico de shell; chaves de API de provedores de modelos de linguagem e sessões de assistentes de código como Claude, Codex, Gemini, Cursor e Copilot; senhas e cookies salvos nos navegadores; e, quando havia banco de dados configurado, as credenciais de provedores guardadas pelas tabelas do próprio proxy LiteLLM.
Houve roubo de dados confirmado?
A LiteLLM orienta assumir que sim caso a versão 1.107.0 tenha sido instalada em uma máquina com saída para a internet. Se o arquivo marcador que o malware cria estiver presente, o vazamento está confirmado; se não estiver, isso não prova que o ambiente está limpo, porque containers e limpezas de arquivos temporários removem esse rastro. A recomendação é rotacionar todas as credenciais que a máquina alcançava.
Isso tem relação com a falha crítica do PHP (PHP2Shell)?
Não. São incidentes distintos que coincidiram no tempo. Curiosamente, existe um ponto de contato: no mesmo dia, a plataforma de deploy Railway avisou que detectou atividade anômala em sistemas que guardam variáveis de ambiente de clientes e disse acreditar que o caso faz parte de uma série de ataques contra empresas de plataforma com o objetivo de comprometer provedores de inferência de IA — o que aponta para esta mesma onda do LiteLLM. As falhas e os alvos, porém, são diferentes.
Já aconteceu antes com o LiteLLM?
Sim. Em março de 2026, as versões 1.82.7 e 1.82.8 foram comprometidas em uma campanha atribuída ao TeamPCP. Depois disso, o projeto endureceu o pipeline de release com repositório privado, Trusted Publishers do GitHub, tags de imagem imutáveis e assinatura de imagens. O ataque de outubro atravessou essas proteções usando credenciais legítimas para apontar o build para outro repositório. Até agora não há conexão estabelecida entre os dois incidentes.
Fontes e leituras adicionais
- LiteLLM — Contained: Oct 21, 2026 LiteLLM release v1.107.0 Compromised — 21/10/2026
- Datadog Security Labs — LiteLLM supply chain compromise: What you need to know — 22/10/2026
- SecurityWeek — LiteLLM Compromised in Fresh Supply Chain Attack — 22/10/2026
- The Hacker News — LiteLLM Suspects GitHub Token Leak in AI Gateway Logs Behind Supply Chain Attack — 22/10/2026
- BleepingComputer — Railway warns devs to rotate secrets after potential breach — 22/10/2026
- Datadog Security Labs — LiteLLM compromised in PyPI supply chain campaign (março, TeamPCP) — mar/2026