Trivy e Docker Scout resolvem o mesmo problema central: descobrir, antes da produção, quais vulnerabilidades, licenças e dependências estão dentro das suas imagens de contêiner. Eles chegam a esse objetivo por caminhos diferentes, e entender essa diferença define qual usar, ou se usar os dois.
Uma imagem Docker raramente contém apenas o seu código. Ela carrega um sistema operacional base, bibliotecas do sistema, o runtime da linguagem (JRE, Node.js, Python) e dezenas ou centenas de dependências transitivas. Cada camada é uma superfície de ataque herdada, e a maior parte dessas vulnerabilidades não está no código que você escreveu.
Este artigo explica como cada ferramenta funciona, mostra os comandos do dia a dia, compara os dois lado a lado e apresenta um pipeline de CI/CD com GitHub Actions que aplica ambos. Os exemplos usam Java/Spring Boot e Node.js apenas como cenário; os comandos valem para qualquer stack.
Conceitos fundamentais
Sete conceitos aparecem em toda conversa sobre scan de imagens, e confundi-los é a origem da maioria dos relatórios mal interpretados.
| Conceito | O que é | Por que importa no scan |
|---|---|---|
| CVE | Identificador público de uma vulnerabilidade (ex.: CVE-2024-XXXX) | É a unidade que os scanners reportam |
| CVSS | Nota de severidade de 0 a 10 (Low, Medium, High, Critical) | Base para filtros como --severity HIGH,CRITICAL
|
| EPSS | Probabilidade estimada de exploração real nos próximos 30 dias | Ajuda a priorizar: CVSS alto com EPSS baixo pode esperar |
| KEV | Catálogo da CISA de vulnerabilidades já exploradas ativamente | Tratar como prioridade máxima, independentemente do CVSS |
| SBOM | Inventário de componentes da imagem (formatos SPDX e CycloneDX) | Permite reavaliar vulnerabilidades sem reescanear a imagem |
| VEX | Declaração de que uma CVE existe no componente, mas não é explorável no seu contexto | Forma auditável de suprimir falsos positivos |
| Provenance | Atestado de como, onde e por quem a imagem foi construída (SLSA) | Prova a origem da imagem na cadeia de suprimentos |
Duas ideias completam o quadro. A base image é a imagem do FROM: ela costuma responder pela maior parte das CVEs de um relatório, e trocá-la tende a render mais que corrigir dependências uma a uma. Já a SCA (Software Composition Analysis) é a técnica por trás dos dois scanners: identificar pacotes instalados (via dpkg, apk, rpm) e dependências de aplicação (pom.xml, package-lock.json, go.mod) e cruzá-los com bases de vulnerabilidades.
Um ponto sutil: um scanner só encontra o que consegue inventariar. Binários copiados à mão ou compilados estaticamente sem metadados passam despercebidos, o que justifica gerar SBOM no build e não apenas escanear a imagem pronta.
Trivy em detalhe
O Trivy é um scanner de segurança open source (licença Apache 2.0), mantido pela Aqua Security, distribuído como um único binário Go. Seu diferencial é a amplitude: o mesmo comando cobre imagens, sistemas de arquivos, repositórios Git, manifestos Kubernetes e arquivos de infraestrutura como código.
Como ele funciona
O Trivy extrai o conteúdo da imagem, identifica os pacotes do SO e das linguagens e consulta um banco local de vulnerabilidades (o trivy-db), baixado do registry no primeiro uso e atualizado periodicamente. Como a comparação acontece na sua máquina ou no runner de CI, ele funciona sem enviar a imagem para nenhum serviço externo, e pode operar offline com o banco em cache.
Tipos de scan
| Scanner | O que detecta | Flag |
|---|---|---|
| Vulnerabilidades | CVEs em pacotes do SO e de linguagens | --scanners vuln |
| Misconfiguration | Erros em Dockerfile, Terraform, Kubernetes, Helm, CloudFormation | --scanners misconfig |
| Secrets | Chaves de API, tokens e senhas embutidos | --scanners secret |
| Licenças | Licenças de dependências (ex.: GPL, AGPL) | --scanners license |
Alvos
O primeiro argumento define o alvo: image, fs (diretório local), repo (repositório remoto), rootfs, config (IaC), k8s (cluster) e sbom (reescanear um SBOM existente).
Comandos do dia a dia
# Scan básico de uma imagem
trivy image minha-app:1.0.0
# Somente HIGH e CRITICAL, ignorando CVEs sem correção disponível
trivy image --severity HIGH,CRITICAL --ignore-unfixed minha-app:1.0.0
# Falhar o comando (exit code 1) quando houver achados: ideal para CI
trivy image --exit-code 1 --severity CRITICAL minha-app:1.0.0
# Saída em JSON, SARIF ou template próprio
trivy image --format json --output relatorio.json minha-app:1.0.0
trivy image --format sarif --output trivy.sarif minha-app:1.0.0
# Gerar SBOM em CycloneDX e reescanear depois, sem a imagem
trivy image --format cyclonedx --output sbom.cdx.json minha-app:1.0.0
trivy sbom sbom.cdx.json
# Escanear o código-fonte e dependências do projeto
trivy fs --scanners vuln,secret,misconfig .
# Validar IaC (Terraform, Kubernetes, Dockerfile)
trivy config ./infra
# Resumo de um cluster Kubernetes
trivy k8s --report summary cluster
Suprimindo achados com critério
O arquivo .trivyignore lista CVEs a ignorar, e as versões recentes aceitam data de expiração e comentário por entrada, o que evita exceções eternas. Para um registro mais formal, o Trivy também consome documentos VEX (OpenVEX, CSAF, CycloneDX VEX) via --vex. Para configuração persistente, use um trivy.yaml em vez de repetir flags.
# .trivyignore
# Não explorável: a função vulnerável não é chamada pela aplicação
CVE-2024-00000
Banco de dados e desempenho em CI
O download do banco a cada execução é o principal gargalo e a causa mais comum de falhas por limite de requisições em runners compartilhados. Três práticas ajudam: cachear o diretório de cache do Trivy entre execuções, usar --skip-db-update quando o banco já estiver presente e espelhar o banco em um registry interno, apontando com --db-repository.
Trivy Operator
No Kubernetes, o Trivy Operator roda dentro do cluster e gera relatórios como recursos customizados (VulnerabilityReport, ConfigAuditReport, ExposedSecretReport). Isso cobre o que o scan de CI não vê: imagens que ficaram vulneráveis depois do deploy, porque uma CVE nova foi publicada.
Docker Scout em detalhe
O Docker Scout é a solução de análise da cadeia de suprimentos integrada ao ecossistema Docker: ele aparece no Docker Desktop, no Docker Hub, na CLI (docker scout) e em uma GitHub Action oficial. Em vez de apenas listar CVEs, ele conecta vulnerabilidades à imagem base, às políticas da organização e à evolução da imagem no tempo.
Como ele funciona
O Scout gera um índice de componentes (um SBOM) da imagem e o cruza com um banco de vulnerabilidades próprio, que agrega várias fontes de advisories e é atualizado continuamente. Quando a imagem está em um repositório com o Scout habilitado, a análise é guardada e reavaliada conforme novas CVEs surgem, sem exigir um novo scan manual. Para imagens locais, o mesmo motor roda sob demanda pela CLI.
Comandos do dia a dia
# Visão geral rápida: vulnerabilidades e base image
docker scout quickview minha-app:1.0.0
# Lista detalhada de CVEs, filtrando por severidade e correção disponível
docker scout cves --only-severity critical,high --only-fixed minha-app:1.0.0
# Escanear o diretório local, sem construir a imagem
docker scout cves --type fs .
# Recomendações de atualização da base image
docker scout recommendations minha-app:1.0.0
# Comparar duas versões e ver apenas o que mudou
docker scout compare --to minha-app:1.0.0 minha-app:1.1.0
# Exportar SBOM
docker scout sbom --format spdx minha-app:1.0.0
# Avaliar a imagem contra as políticas da organização
docker scout policy minha-app:1.0.0 --org minha-org
# Saída SARIF e exit code para CI
docker scout cves --format sarif --output scout.sarif --exit-code --only-severity critical,high minha-app:1.0.0
Recomendações de base image
Esse é o recurso mais característico. O docker scout recommendations compara a base atual com alternativas e propõe dois caminhos: atualizar para uma versão mais nova da mesma tag (menos CVEs com mudança mínima) ou trocar por outra variante (por exemplo, de uma imagem completa para uma slim). O relatório mostra quantas vulnerabilidades cada opção elimina, o que transforma a conversa sobre trocar de base image de opinião em número.
Políticas
O Scout avalia a imagem contra políticas e mostra o resultado como conforme ou não conforme. As políticas padrão cobrem, entre outras verificações, vulnerabilidades críticas e altas com correção disponível, vulnerabilidades de alto perfil, bases desatualizadas, licenças copyleft, presença de atestados de cadeia de suprimentos e usuário não root por padrão. Cada política pode ser ajustada ou criada sob medida na organização.
SBOM e provenance
O Scout lê os atestados que o BuildKit anexa à imagem. Para alimentá-lo com dados melhores, gere SBOM e provenance no build:
docker buildx build \
--sbom=true \
--provenance=mode=max \
--tag minha-org/minha-app:1.0.0 \
--push .
Com isso, a análise passa a usar o SBOM gerado no próprio build, mais fiel ao conteúdo real que a inferência feita depois, e a política de atestados fica satisfeita.
Limitações a considerar
O Scout é focado em imagens e dependências: ele não analisa IaC (Terraform, manifestos Kubernetes) nem procura secrets embutidos. Os recursos de monitoramento contínuo, políticas e integração com Docker Hub dependem do plano da organização, então confira o plano vigente antes de basear um processo nele.
Docker Scout vs Trivy
O Trivy é a escolha por amplitude e independência de plataforma; o Scout é a escolha por integração com o fluxo Docker e por orientação de ação (base image e políticas). A tabela resume as diferenças.
| Critério | Trivy | Docker Scout |
|---|---|---|
| Modelo | Open source (Apache 2.0), binário único | Recurso do ecossistema Docker, com planos por organização |
| Escopo | Vulnerabilidades, misconfiguration, secrets, licenças, IaC, Kubernetes | Vulnerabilidades, licenças, SBOM, políticas, recomendações de base image |
| Alvos | Imagem, filesystem, repositório, cluster, SBOM, IaC | Imagem e diretório local |
| Execução | Local ou em CI, com possibilidade de operar offline com banco em cache | CLI local, Docker Desktop, Docker Hub e GitHub Action |
| Recomendação de base image | Não nativa | Sim, com comparação de opções |
| Políticas | Via flags, exit code e Rego para misconfiguration | Políticas nativas com status de conformidade |
| Monitoramento contínuo | Trivy Operator no Kubernetes ou reexecução agendada | Reavaliação automática em repositórios habilitados |
| Formatos de saída | Table, JSON, SARIF, CycloneDX, SPDX, template | Texto, SARIF, SPDX, CycloneDX |
| Registry | Qualquer um | Melhor experiência com Docker Hub; funciona com outros registries |
| Ponto forte | Cobertura ampla e neutra | Orientação de correção e integração com Docker |
Quando usar cada um
- Trivy quando o pipeline envolve IaC, Kubernetes ou detecção de secrets, quando é preciso rodar em ambiente isolado ou quando se quer uma ferramenta neutra em relação a registry e nuvem.
- Docker Scout quando a equipe já vive no Docker Desktop e no Docker Hub, quando o objetivo é decidir qual base image adotar ou quando políticas por organização e comparação entre versões são prioridade.
- Os dois quando se quer cobertura ampla no CI (Trivy) e orientação de remediação para o time de desenvolvimento (Scout). Resultados podem divergir, porque cada ferramenta usa suas próprias fontes de dados e regras de correspondência. Divergência não indica erro de um dos lados: investigue o pacote e a fonte do advisory antes de decidir.
Integração em CI/CD com GitHub Actions
O padrão mais útil é construir a imagem uma vez, escaneá-la com os dois, publicar o relatório no GitHub e só então fazer o push. O pipeline abaixo bloqueia o merge quando há vulnerabilidade crítica com correção disponível e envia os resultados para a aba Security do repositório.
name: build-and-scan
on:
pull_request:
push:
branches: [main]
permissions:
contents: read
security-events: write # necessário para enviar SARIF
pull-requests: write # comentário do Scout no PR
env:
IMAGE: minha-org/minha-app:${{ github.sha }}
jobs:
scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@<commit-sha>
- uses: docker/setup-buildx-action@<commit-sha>
- name: Build (sem push)
uses: docker/build-push-action@<commit-sha>
with:
context: .
load: true
tags: ${{ env.IMAGE }}
sbom: true
provenance: mode=max
# --- Trivy: cobertura ampla, falha o job em CRITICAL com correção ---
- name: Trivy (imagem)
uses: aquasecurity/trivy-action@<commit-sha>
with:
image-ref: ${{ env.IMAGE }}
format: sarif
output: trivy.sarif
severity: CRITICAL,HIGH
ignore-unfixed: true
exit-code: '0' # o SARIF sempre é gerado; o gate vem no próximo passo
- name: Trivy (gate)
uses: aquasecurity/trivy-action@<commit-sha>
with:
image-ref: ${{ env.IMAGE }}
severity: CRITICAL
ignore-unfixed: true
exit-code: '1'
- name: Enviar SARIF do Trivy
if: always()
uses: github/codeql-action/upload-sarif@<commit-sha>
with:
sarif_file: trivy.sarif
category: trivy
# --- Docker Scout: orientação de correção e comparação com main ---
- name: Login no Docker Hub
uses: docker/login-action@<commit-sha>
with:
username: ${{ secrets.DOCKERHUB_USER }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Docker Scout
uses: docker/scout-action@<commit-sha>
with:
command: cves,recommendations
image: ${{ env.IMAGE }}
only-severities: critical,high
sarif-file: scout.sarif
write-comment: true
github-token: ${{ secrets.GITHUB_TOKEN }}
- name: Enviar SARIF do Scout
if: always()
uses: github/codeql-action/upload-sarif@<commit-sha>
with:
sarif_file: scout.sarif
category: docker-scout
Pontos de atenção no pipeline
-
Fixe as actions por commit SHA, como nos
<commit-sha>acima, em vez de tags móveis. Uma action de scanner roda com acesso ao seu runner e aos seus secrets, então ela própria é parte da cadeia de suprimentos que você quer proteger. -
Separe o relatório do gate. Gerar o SARIF com
exit-code: 0e aplicar o bloqueio em um passo próprio garante que o relatório chegue ao GitHub mesmo quando o build falha. -
Escaneie antes do push. Construir com
load: true, escanear e só depois publicar impede que uma imagem reprovada chegue ao registry. -
Cacheie o banco do Trivy com
actions/cachepara evitar falhas por limite de requisições e reduzir o tempo do job. -
Reescaneie periodicamente. Um workflow agendado (
schedule) sobre as imagens já publicadas detecta CVEs descobertas depois do deploy, que o scan no momento do build não pode ver.
Boas práticas e armadilhas comuns
O scanner mostra o problema, mas quem reduz o risco é a imagem que você constrói. As práticas abaixo têm o maior retorno.
Reduza a superfície antes de escanear
-
Use bases mínimas: variantes
slim,alpineou distroless eliminam pacotes que você nunca usa e, com eles, as CVEs associadas. - Use multi-stage build: compile em uma etapa e copie só o artefato final, deixando compiladores e ferramentas de build fora da imagem de produção.
-
Fixe a base por digest (
FROM imagem@sha256:...) e atualize de forma deliberada, para que o resultado do scan seja reprodutível. -
Rode como usuário não root com
USERno Dockerfile. - Reconstrua com frequência: uma imagem sem mudança de código acumula CVEs novas com o tempo.
Defina critérios de bloqueio realistas
Bloquear qualquer CVE de qualquer severidade paralisa o time e leva à desativação do scan. Um ponto de partida comum é bloquear CRITICAL e HIGH com correção disponível e apenas reportar o restante. O filtro --ignore-unfixed (Trivy) e --only-fixed (Scout) existem para isso, mas lembre que CVEs sem correção continuam sendo risco: elas devem ser acompanhadas, não esquecidas.
Trate exceções como dívida com prazo
Toda supressão deve ter justificativa e data de revisão. Prefira VEX ou entradas com expiração a um .trivyignore que só cresce. Uma CVE suprimida sem registro de por quê é indistinguível de uma CVE esquecida.
Armadilhas frequentes
- Achar que zero CVEs significa seguro. O scan cobre vulnerabilidades conhecidas em componentes inventariados; não detecta falhas de lógica na sua aplicação nem configuração insegura em runtime.
- Escanear só no build. O risco muda depois do deploy; combine o scan de CI com reescaneamento agendado, Trivy Operator ou o monitoramento do Scout.
- Priorizar só por CVSS. Combine severidade com correção disponível, presença no catálogo KEV e EPSS; uma CVE crítica em um pacote que a aplicação não carrega pode esperar, uma média explorada ativamente não.
- Ignorar divergências entre ferramentas. Se Trivy e Scout discordam, verifique a fonte do advisory e a versão do pacote antes de concluir qual está certo.
-
Deixar o banco desatualizado. Um scan com banco antigo gera falsa sensação de segurança, especialmente em ambientes isolados com
--skip-db-update.
Conclusão
Trivy e Docker Scout se complementam mais do que competem. O Trivy entrega cobertura ampla, neutra e executável em qualquer ambiente, incluindo IaC, secrets e Kubernetes. O Docker Scout entrega contexto: qual base image trocar, o que mudou entre duas versões e se a imagem cumpre as políticas da organização.
Um caminho prático para começar:
- Rode
trivy imageedocker scout quickviewna imagem de produção atual e compare os resultados. - Use
docker scout recommendationspara escolher uma base image menor ou mais atual. - Adicione o pipeline de GitHub Actions com bloqueio apenas para CRITICAL com correção disponível.
- Passe a gerar SBOM e provenance no build.
- Agende o reescaneamento das imagens publicadas e, em Kubernetes, avalie o Trivy Operator.
Referências
Flags, nomes de inputs das actions e recursos dependem da versão e do plano; confirme sempre na documentação oficial antes de adotar um comando em produção.
Top comments (0)