DevGuideTK
← Trilha Backend

Dependências e pacotes

Versionamento semântico, arquivos de trava e o risco de segurança das dependências transitivas.

As decisões sobre dependências são cinco: quando acrescentar uma, como instalar de forma reproduzível, como atualizar, como tratar vulnerabilidades e como reduzir a superfície de ataque.

Antes de acrescentar uma dependência

Toda dependência nova é código que a equipe passa a manter sem ter escrito. Algumas perguntas antes de instalar:

PerguntaSinal de alerta
A biblioteca padrão já resolve?Uma dependência para UUID, cópia profunda de objetos ou formatação simples de datas
O pacote é mantido?Último lançamento há anos, problemas abertos sem resposta
Quem mantém?Uma única pessoa, sem histórico, para algo crítico
Quantas dependências ele traz?Dezenas de pacotes indiretos para uma função pequena
O nome é exatamente o esperado?Uma letra diferente do pacote popular; poucos downloads; publicado há dias
A licença é compatível?Licenças que impõem obrigações ao seu código (como a GPL em software distribuído)

Instalação reproduzível

EcossistemaComando para desenvolverComando para CI e imagem
Nodenpm installnpm ci
Python (pip)pip install -r requirements.txtpip install --require-hashes -r requirements.txt, com versões e hashes gerados por pip-compile ou uv
Python (Poetry, uv)poetry install, uv syncpoetry install --sync, uv sync --frozen
Gogo get, go mod tidygo mod download e o build; o go.sum é conferido sempre
Javamvn installmvn -B verify, com versões exatas e o plugin Enforcer
C#dotnet restoredotnet restore --locked-mode, com RestorePackagesWithLockFile ativado

A regra é a mesma em todos: o arquivo de trava vai para o repositório, e o CI e o Dockerfile usam o comando que falha se a trava não bater, em vez de resolver versões novas.

Atualizar: pouco e sempre

EstratégiaConsequência
Nunca atualizarVulnerabilidades acumulam; um dia uma atualização obrigatória atravessa várias versões maiores de uma vez
Atualizar tudo de vez em quandoUma mudança enorme, difícil de revisar e de reverter; quando algo quebra, ninguém sabe qual pacote foi
Atualizações pequenas e frequentes, automatizadasCada mudança é pequena, testada pelo CI e fácil de reverter

Ferramentas como Dependabot e Renovate abrem pull requests automáticos para cada atualização, com as notas da versão. Uma configuração comum:

Tipo de atualizaçãoTratamento
Correções (patch) e pacotes de desenvolvimentoIntegrar automaticamente se os testes passarem
Versões menoresAgrupadas por semana, com revisão rápida
Versões maioresUma por vez, lendo o guia de migração
Correções de segurançaPrioridade imediata

Atualizar automaticamente só é seguro com testes que realmente exercitam o sistema. Sem eles, a automação só acelera a entrada de defeitos.

Vulnerabilidades

EcossistemaFerramenta de verificação
Nodenpm audit
Pythonpip-audit
Gogovulncheck, que mostra só as vulnerabilidades em funções que o código realmente chama
JavaOWASP Dependency-Check, plugins do Maven e do Gradle
C#dotnet list package --vulnerable
TodosDependabot, Snyk, Trivy e a varredura do próprio GitHub ou GitLab

Nem toda vulnerabilidade apontada é explorável no seu sistema. Uma falha numa função que o código nunca chama, ou numa dependência só de desenvolvimento, pesa menos que uma falha alcançável a partir de uma rota pública. O govulncheck faz essa análise para Go; nas outras linguagens, a priorização costuma ser manual:

  1. A vulnerabilidade está numa dependência que vai para produção?
  2. O código usa a parte afetada?
  3. A entrada que dispara a falha pode vir de um usuário externo?
  4. Qual é a severidade e já existe exploração conhecida?

Reduzir a superfície de ataque

PráticaO que evita
Arquivo de trava com hashes, e instalação exata no CIVersões e conteúdos inesperados
Desligar scripts de instalação no CI (npm ci --ignore-scripts), liberando só os pacotes que precisamCódigo executado na instalação
Registro interno ou proxy (Artifactory, Nexus, Verdaccio)Dependência direta do registro público; confusão de dependência
Escopo dos pacotes internos (@empresa/pacote)Um pacote público ocupando o nome de um interno
Ações do CI fixadas por hash, e não por etiquetaUma ação de terceiros alterada depois de aprovada
Menos dependênciasMenos código de terceiros para confiar

Resumo da decisão

  1. Antes de instalar: a biblioteca padrão resolve? O pacote é mantido e o nome está certo?
  2. Arquivo de trava no repositório; instalação exata no CI e no Dockerfile.
  3. Atualizações pequenas e frequentes, automatizadas, com testes que as validem.
  4. Vulnerabilidades verificadas no CI e priorizadas pelo que é alcançável.
  5. Superfície de ataque: scripts de instalação desligados no CI, registro interno, pacotes internos com escopo.

O próximo nível mostra os comandos de cada ecossistema, uma configuração de atualização automática e como isolar uma dependência atrás de uma interface própria nas cinco linguagens.

Prompts para aprofundar

Ao abrir no ChatGPT ou no Claude, o prompt é enviado ao serviço escolhido pela URL e também fica copiado na sua área de transferência.

  • Política de dependências da equipe

    Quero definir a política de dependências da minha equipe.
    
    Pergunte qual ecossistema usamos, quantos serviços existem e como as dependências são atualizadas hoje.
    
    Ajude a definir:
    1. Os critérios para aceitar uma dependência nova.
    2. A instalação reproduzível no CI e nas imagens.
    3. A estratégia de atualização: frequência, automação, o que integrar automaticamente e o que revisar.
    4. A verificação de vulnerabilidades e o critério para bloquear um deploy.
    5. As medidas contra ataques à cadeia de suprimentos.
    
    Termine com um documento curto que eu possa colocar no repositório.
  • Priorizar vulnerabilidades

    A ferramenta de verificação do meu projeto aponta muitas vulnerabilidades e não sei por onde começar.
    
    Pergunte qual ecossistema e ferramenta eu uso e peça que eu cole o resultado da verificação.
    
    Explique:
    1. Como ler o relatório: pacote, versão, severidade, versão corrigida e caminho na árvore.
    2. Como priorizar: produção ou desenvolvimento, uso da parte afetada, exposição a entrada externa, severidade e exploração conhecida.
    3. Como corrigir quando a vulnerabilidade está numa dependência indireta.
    4. O que fazer quando não há versão corrigida.
    
    Depois analise o meu relatório e monte uma lista em ordem de prioridade.
  • Configurar atualização automática

    Quero configurar atualizações automáticas de dependências com Dependabot ou Renovate.
    
    Pergunte qual plataforma (GitHub, GitLab) e ecossistemas eu uso, e como estão os testes do projeto.
    
    Explique:
    1. A diferença entre Dependabot e Renovate.
    2. Como agrupar atualizações para não receber dezenas de pull requests.
    3. O que integrar automaticamente e com quais condições.
    4. Como esperar alguns dias antes de adotar versões recém-publicadas, e por que isso protege contra pacotes comprometidos.
    5. Como tratar as atualizações de segurança com prioridade.
    
    Termine com o arquivo de configuração pronto para o meu caso.