Software supply chain capa

Software supply chain: o código que ninguém do seu time escreveu

TL;DR

A fração do código de terceiros em produção supera com folga o código escrito internamente.

  • SBOM tira a opacidade — é a foto que ninguém tinha do que está rodando na software supply chain.
  • Assinatura prova proveniência, não prova ausência de backdoor (limite honesto).
  • Pinning e lockfiles eliminam surpresa de supply chain ao custo de manutenção.
  • Resposta a incidente exige plano ANTES do CVE — maintainer account takeover é recorrente.

~ 7 min de leitura · 1248 palavras

A fração que code review não cobre

Uma aplicação Node típica carrega entre 200 e 300 pacotes transitivos. O desenvolvedor declara cinco ou seis dependências diretas no package.json. O restante chega por cascata, sem revisão humana. Em Java, os relatórios Sonatype State of the Software Supply Chain apontam que aproximadamente 79% do código de produção é composto por dependências. O código interno representa uma minoria silenciosa.

O code review tradicional cobre pull requests, diffs e lógica de negócio. O revisor enxerga o que o time escreveu. A software supply chain escapa dessa inspeção. Nenhum merge request mostra o conteúdo do pacote `left-pad` ou da biblioteca de parsing que entrou por transitividade. O revisor aprova o código visível. O código invisível segue para produção sem questionamento.

Os números sustentam a assimetria. Um time que revisa 100% do código próprio cobre apenas 21% do que executa em runtime Java. Em Node, a cobertura efetiva é ainda menor. A revisão de código protege a lógica de negócio. A cadeia de fornecimento de software exige controles diferentes. Ignorar essa fração significa operar às cegas sobre a maior parte do sistema.

SBOM — a foto que ninguém tinha

SBOM significa Software Bill of Materials. Trata-se de um inventário estruturado de todos os componentes de software em um artefato. Cada entrada lista nome, versão, fornecedor, licença e relacionamentos. O SBOM transforma a dependência transitiva em item rastreável. Sem ele, a organização não sabe o que roda em produção.

Dois formatos dominam o mercado. CycloneDX nasceu no OWASP e foca em segurança. SPDX veio da Linux Foundation e prioriza conformidade de licenças. Ambos resolvem o problema central: dar nome e versão ao que antes era opaco. A escolha depende do ecossistema e das ferramentas de consumo.

A extração é imediata com ferramentas maduras. Syft gera SBOM a partir de imagens de container e diretórios. Cdxgen cobre múltiplas linguagens e gera CycloneDX. Trivy integra varredura de vulnerabilidades ao inventário. O comando leva segundos. A adoção não exige reescrita de pipeline.

O armazenamento correto é anexar o SBOM ao artifact no registry. OCI permite associar o documento à imagem como artifact. O time consulta o inventário sem reconstruir nada. O consumo prático ocorre no gate de CI. A pipeline falha se alguma vulnerabilidade exceder o threshold de CVSS definido.

  • SBOM é o inventário estruturado de componentes, versões e relações de um artefato.
  • CycloneDX prioriza segurança; SPDX prioriza conformidade de licenças.
  • Syft, cdxgen e trivy extraem SBOM em segundos, sem reescrita de pipeline.
  • Armazenar o SBOM como artifact no registry garante consulta imediata.
  • Gate de CI consome o SBOM e falha quando CVSS ultrapassa o limite definido.

Proveniência — assinatura e attestation

Proveniência responde a uma pergunta específica: quem construiu este artefato e como. A assinatura criptográfica vincula o binário a uma identidade verificável. Sigstore e cosign tornaram esse processo acessível. O desenvolvedor assina a imagem no momento do build. O consumidor verifica a assinatura antes do deploy.

SLSA define quatro níveis de maturidade para a cadeia de build. Level 1 exige que o build seja scriptado e produza proveniência. Level 2 adiciona controle de versão e build service. Level 3 torna o build hermético, sem acesso a rede ou fontes não declaradas. Level 4 exige revisão dupla e isolamento total. Cada nível reduz a superfície de ataque.

O limite honesto precisa ser declarado. Assinatura prova origem, não prova ausência de backdoor. Um maintainer comprometido pode assinar código malicioso com chave legítima. A attestation confirma que o build veio de um pipeline específico. Ela não audita o conteúdo do código-fonte. A distinção evita falsa sensação de segurança.

cosign verify \
  --certificate-identity https://github.com/org/repo/.github/workflows/release.yml@refs/heads/main \
  --certificate-oidc-issuer https://token.actions.githubusercontent.com \
  registry.example.com/app/image:latest
  • Sigstore e cosign vinculam artefato a identidade verificável no momento do build.
  • SLSA level 2 garante build scriptado; level 3 garante build hermético.
  • Assinatura prova origem e pipeline, não prova ausência de código malicioso.
  • A verificação deve ocorrer no deploy, não apenas no momento do build.

Higiene de consumo — pins, lockfiles, policies

O consumo de dependências exige disciplina. Lockfiles congelam o grafo exato de versões resolvidas. O comando `npm ci` instala exclusivamente a partir do package-lock.json commitado. Qualquer divergência entre manifest e lockfile interrompe a instalação. O mesmo princípio vale para `cargo –locked` no ecossistema Rust.

Go adota abordagem semelhante com go.sum. O arquivo registra hashes criptográficos de cada módulo. Python avança com PEP 740, que adiciona hashes ao pip freeze. A verificação de integridade impede substituição silenciosa de pacotes. O custo é manutenção contínua dos arquivos de lock.

Renovate e Dependabot automatizam atualizações, mas com diferenças operacionais. Dependabot abre pull requests simples e prioriza integração nativa com GitHub. Renovate oferece agrupamento, scheduling e políticas customizadas. Para supply chain, o Renovate permite atualizar em lotes e testar antes do merge. A escolha afeta a velocidade de resposta a vulnerabilidades.

Imagens Docker exigem atenção redobrada. Tags como `latest` ou `1.0` são mutáveis. O digest `@sha256:…` aponta para um conteúdo imutável. O Dockerfile deve fixar o digest, não a tag. A mudança elimina surpresas quando o maintainer republica uma tag.

  • `npm ci` e package-lock.json commitado garantem instalação determinística.
  • `cargo –locked` e go.sum aplicam verificação de integridade por hash.
  • PEP 740 adiciona hashes ao pip freeze no ecossistema Python.
  • Renovate permite agrupamento e políticas; Dependabot prioriza simplicidade.
  • Dockerfile deve usar digest `@sha256` em vez de tags mutáveis.

Resposta a incidente — quando o maintainer é o vetor

O caso event-stream, em 2018, mostrou o padrão. Um maintainer transferiu o pacote para um atacante. O novo dono inseriu código malicioso direcionado a wallets de criptomoeda. Milhões de downloads semanais distribuíram o payload. A detecção levou semanas.

ua-parser-js repetiu o roteiro em 2021. O maintainer teve a conta comprometida. Versões maliciosas foram publicadas no npm. O pacote era usado por milhares de aplicações. A resposta dependeu de alertas manuais e listas de dependentes.

xz-utils, em 2024, elevou o ataque a outro nível. O backdoor foi inserido ao longo de anos por um maintainer de confiança. O código malicioso visava SSH em distribuições Linux específicas. A descoberta foi acidental. O caso provou que confiança não é controle.

O padrão é claro: account takeover de maintainer insere código malicioso. A organização precisa de plano de resposta antes do CVE. SBOM permite localizar quem usa o pacote comprometido em minutos. Dados de contato dos responsáveis por cada serviço precisam existir antes do incidente.

  • event-stream (2018): transferência de ownership inseriu código malicioso em milhões de downloads.
  • ua-parser-js (2021): conta comprometida publicou versões maliciosas no npm.
  • xz-utils (2024): backdoor de anos inserido por maintainer de confiança.
  • SBOM e contatos pré-cadastrados reduzem o tempo de resposta de dias para minutos.

O que entra no orçamento dos próximos 90 dias

O custo em tempo de engenharia é previsível: dois a três dias para gerar SBOM no pipeline, um dia para configurar gate de CVSS, dois dias para migrar Dockerfiles para digest. A proposição é clara: SBOM primeiro, depois attestations. Sem inventário, a resposta a incidente é adivinhação. Com inventário, a software supply chain deixa de ser opaca e passa a ser auditável.

Leitura relacionada

Posts Similares

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *