Se você acompanha as notícias sobre segurança em Python, provavelmente já ouviu falar dos ataques recentes que comprometeram diversas bibliotecas populares no PyPI. Pacotes legítimos foram sequestrados, versões maliciosas foram publicadas, e desenvolvedores ao redor do mundo instalaram código comprometido sem nem perceber.
O mais assustador? Isso pode acontecer com qualquer um de nós, a qualquer momento.
O Que Está Acontecendo?
Nos últimos meses, vimos um aumento alarmante em ataques do tipo “supply chain” no ecossistema Python:
- Typosquatting: Pacotes maliciosos com nomes similares a bibliotecas populares (ex:
requetsao invés derequests) - Account Takeover: Contas de mantenedores sendo comprometidas e versões maliciosas sendo publicadas
- Dependency Confusion: Pacotes internos sendo substituídos por versões públicas maliciosas
- Malicious Updates: Atualizações legítimas que introduzem código malicioso
O impacto desses ataques pode ser devastador: roubo de credenciais, exfiltração de dados, backdoors em produção, e muito mais.
A Primeira Linha de Defesa: Não Instale Pacotes “Bleeding Edge”
Aqui está uma verdade inconveniente: a maioria dos ataques à supply chain são descobertos nas primeiras horas ou dias após a publicação. Se você instalar um pacote assim que ele é lançado, está se colocando em risco desnecessário.
A solução? Espere alguns dias antes de instalar novas versões.
UV: O Gerenciador Moderno com Segurança Embutida
Se você ainda não conhece o uv, ele é o gerenciador de pacotes Python mais rápido e moderno disponível hoje. E tem uma funcionalidade matadora para segurança: --exclude-newer.
Como Funciona?
O uv permite que você exclua pacotes publicados há menos de X tempo. Por exemplo, você pode configurar para só instalar pacotes que existem há pelo menos uma semana:
|
|
Isso significa que qualquer pacote malicioso publicado recentemente será automaticamente ignorado.
Configuração User/System-Wide
Você pode definir isso globalmente no arquivo de configuração do uv. No Linux/Mac, adicione ao ~/.config/uv/uv.toml:
|
|
No Windows: %APPDATA%\uv\uv.toml
Configuração por Projeto
Ainda melhor, adicione ao pyproject.toml do seu projeto para que todos no time usem a mesma política:
|
|
E Quando Preciso de uma Atualização Urgente?
Ótima pergunta! Imagine que uma CVE crítica é descoberta no requests e uma correção é lançada hoje. Você não pode esperar uma semana.
Para esses casos, você pode definir exceções para pacotes específicos:
|
|
Isso permite que você instale versões específicas quando necessário, mantendo a proteção geral.
Por Que Isso Funciona?
Pense nisso: quando um atacante compromete um pacote, ele quer resultados imediatos. Ele não vai esperar uma semana para colher os frutos. Com exclude-newer:
- ✅ Você dá tempo para a comunidade identificar pacotes maliciosos
- ✅ Scanners de segurança têm tempo para processar novos lançamentos
- ✅ Mantenedores têm tempo para yankar versões problemáticas
- ✅ Você reduz drasticamente sua superfície de ataque
É como deixar o vinho envelhecer - só que para dependências.
Começando com UV
Se ainda não tem o uv instalado:
|
|
Crie seu projeto:
|
|
Pronto! Seu projeto agora está automaticamente protegido contra pacotes bleeding edge.
Verificação de Integridade: Hashing
Além de evitar pacotes muito novos, outra técnica eficaz é o uso de hash verification nas suas dependências.
Como Funciona?
Quando você instala um pacote Python, o pip baixa um arquivo .whl ou .tar.gz de um repositório. Cada arquivo tem um hash único (SHA256) que funciona como uma “impressão digital” daquele pacote específico.
A ideia é simples: se você especificar o hash exato do pacote que deseja instalar, o pip irá verificar se o arquivo baixado corresponde a esse hash. Se alguém tentar substituir o pacote por uma versão maliciosa, o hash não vai bater, e a instalação falhará.
Na Prática
Vamos ver como implementar isso no seu projeto.
1. Gere o arquivo de hashes
Primeiro, crie um arquivo requirements.txt com suas dependências e versões pinadas:
|
|
Agora, use o comando pip hash para gerar os hashes:
|
|
Ou, mais simples, use o pip-compile do pip-tools:
|
|
Isso gerará um arquivo requirements.txt com hashes:
|
|
2. Instale com verificação de hash
Agora, quando você instalar suas dependências:
|
|
O pip só instalará se os hashes conferirem. Se alguém tentar te enviar um pacote malicioso, a instalação falhará imediatamente.
Outras Camadas de Proteção
O hash verification é poderoso, mas não é a única defesa. Aqui estão outras técnicas que você deve usar:
1. Pip Audit
Use a ferramenta pip-audit para verificar vulnerabilidades conhecidas:
|
|
Isso escaneará todas as suas dependências contra o banco de dados de vulnerabilidades do PyPI.
2. Dependabot / Renovate
Configure ferramentas de atualização automática de dependências no seu repositório. Elas monitoram por vulnerabilidades e criam PRs automaticamente:
|
|
3. Poetry com Lock File
Se você usa Poetry, o poetry.lock já inclui hashes por padrão:
|
|
Isso garante que as versões exatas (com hashes verificados) sejam instaladas.
4. Ambientes Isolados
Sempre use ambientes virtuais. Se uma dependência maliciosa for instalada, ela estará isolada daquele projeto específico:
|
|
5. Private PyPI Index
Para projetos críticos, considere usar um private PyPI index (como o Artifactory ou DevPI):
|
|
Isso permite que você controle exatamente quais pacotes estão disponíveis.
6. Code Review de Dependências
Antes de adicionar uma nova dependência:
- ✅ Verifique a popularidade (downloads, stars no GitHub)
- ✅ Confira a frequência de atualizações
- ✅ Leia o código fonte (sim, realmente)
- ✅ Verifique se os mantenedores são confiáveis
- ✅ Procure por issues de segurança abertas
7. Minimize Dependências
A melhor dependência é aquela que você não tem.
Pergunte-se sempre: “Eu realmente preciso dessa biblioteca de 500MB para fazer algo que posso implementar em 50 linhas?”
Conclusão
Os ataques à supply chain são uma ameaça real e crescente no ecossistema Python. Não é paranoia, é precaução.
A boa notícia? As ferramentas para se proteger já existem e são gratuitas. A má notícia? A maioria dos desenvolvedores não as usa.
Não seja parte da estatística. Implemente essas práticas hoje mesmo:
- Migre para
uve configureexclude-newer- proteção instantânea - Adicione hash verification - use
pip-toolsou Poetry - Configure
pip-auditno CI/CD - Habilite Dependabot ou Renovate
- Eduque seu time
Segurança não é opcional. É responsabilidade.
💡 Dica Pro: Combine uv + hash verification + pip-audit. Essa tríade cria uma defesa em profundidade praticamente impenetrável contra ataques à supply chain.
Referências: