Protegendo Seus Projetos Python Contra Ataques à Supply Chain

Protegendo Seus Projetos Python Contra Ataques à Supply Chain

6 min de leitura

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: requets ao invés de requests)
  • 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:

1
uv lock --upgrade --exclude-newer "1 week"

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:

1
2
# Não instala pacotes publicados há menos de 1 semana
exclude-newer = "1 week"

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:

1
2
[tool.uv]
exclude-newer = "1 week"

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:

1
2
3
4
5
6
[tool.uv]
exclude-newer = "1 week"

# Exceção para requests - pode instalar versões desde 25/03/2026
[tool.uv.exclude-newer-package]
requests = "2026-03-25T16:00:00Z"

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:

1
2
3
4
5
6
7
8
# Linux/Mac
curl -LsSf https://astral.sh/uv/install.sh | sh

# Windows (PowerShell)
powershell -c "irm https://astral.sh/uv/install.ps1 | iex"

# Ou via pip
pip install uv

Crie seu projeto:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
uv init meu-projeto
cd meu-projeto

# Adicione a configuração de segurança
echo '[tool.uv]
exclude-newer = "1 week"' >> pyproject.toml

# Adicione dependências
uv add requests pandas

# Sincronize (respeitando a janela de 1 semana)
uv sync

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:

1
2
3
4
requests==2.31.0
pandas==2.2.1
numpy==1.26.4
pydantic==2.6.3

Agora, use o comando pip hash para gerar os hashes:

1
2
pip install --dry-run --report - requests==2.31.0 | \
  python -c "import json, sys; print(json.load(sys.stdin)['install'][0]['download_info']['url'])"

Ou, mais simples, use o pip-compile do pip-tools:

1
2
pip install pip-tools
pip-compile --generate-hashes requirements.in -o requirements.txt

Isso gerará um arquivo requirements.txt com hashes:

1
2
3
4
5
6
7
requests==2.31.0 \
    --hash=sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f \
    --hash=sha256:942c5a758f98d788eaceeaa8c0fb4a82c5e0c5f626c3f5f9d5e5a16b1a1e8c88
pandas==2.2.1 \
    --hash=sha256:234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef \
    --hash=sha256:abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890
# ... e assim por diante

2. Instale com verificação de hash

Agora, quando você instalar suas dependências:

1
pip install --require-hashes -r requirements.txt

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:

1
2
pip install pip-audit
pip-audit

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:

1
2
3
4
5
6
7
8
# .github/dependabot.yml
version: 2
updates:
  - package-ecosystem: "pip"
    directory: "/"
    schedule:
      interval: "weekly"
    open-pull-requests-limit: 10

3. Poetry com Lock File

Se você usa Poetry, o poetry.lock já inclui hashes por padrão:

1
poetry install --sync

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:

1
2
3
4
python -m venv venv
source venv/bin/activate  # Linux/Mac
# ou
venv\Scripts\activate  # Windows

5. Private PyPI Index

Para projetos críticos, considere usar um private PyPI index (como o Artifactory ou DevPI):

1
pip install --index-url https://your-private-pypi.com/simple/ requests

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:

  1. Migre para uv e configure exclude-newer - proteção instantânea
  2. Adicione hash verification - use pip-tools ou Poetry
  3. Configure pip-audit no CI/CD
  4. Habilite Dependabot ou Renovate
  5. 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: