Trivy e Grype no DevSecOps: Scan de Vulnerabilidades e SBOM para Contêineres Docker em 2026
Como escanear vulnerabilidades em contêineres com Trivy e Grype, gerar SBOM em CycloneDX/SPDX, integrar a GitHub Actions/GitLab CI e tratar falsos positivos com VEX em 2026.
Trivy e Grype são os dois scanners de vulnerabilidades mais usados em pipelines DevSecOps para contêineres em 2026. O Trivy (Aqua Security) cobre imagens, sistemas de arquivos, repositórios Git, IaC, Kubernetes e gera SBOMs nativamente; já o Grype (Anchore) foca em imagens e SBOMs com integração estreita ao Syft. Neste guia eu mostro, do ponto de vista de quem ataca contêineres como ganha-pão, como instalar ambos, integrá-los a GitHub Actions e GitLab CI, gerar SBOMs em CycloneDX e SPDX, e tratar falsos positivos sem afrouxar o gate de segurança.
Trivy 0.58+ é o canivete suíço do DevSecOps em 2026: scaneia imagens, código, IaC, secrets e gera SBOM em CycloneDX/SPDX num único binário.
Grype 0.85+ combinado com Syft 1.18+ oferece a melhor precisão de detecção em imagens distroless e linguagens compiladas como Go e Rust.
Falhar o build com --exit-code 1 --severity HIGH,CRITICAL é o gate mínimo aceitável, mas exige uma política de exceções versionada em .trivyignore ou arquivo VEX.
SBOMs assinados com Cosign e armazenados em registries OCI viraram exigência da SLSA v1.1 e do Executive Order 14028 dos EUA, com adoção crescente na UE via CRA.
Trivy Operator no Kubernetes faz scan contínuo de workloads em execução, complementando ferramentas runtime como Falco e Tetragon.
O que é scan de vulnerabilidades em contêineres
Quando eu invado uma infraestrutura, a primeira coisa que procuro são imagens de contêineres desatualizadas. Uma node:18-alpine pinada há dois anos costuma carregar um OpenSSL com CVE crítico, um glibc vulnerável e meia dúzia de libs Node com prototype pollution. Scan de vulnerabilidades em contêineres é o processo de examinar cada camada da imagem (pacotes do SO base, dependências da linguagem como npm, pip, gem, go.mod, além de binários estáticos e até secrets esquecidos), comparando hashes e versões contra bancos como o NVD, GHSA, GitLab Advisory Database, Red Hat Security Data e o Aqua vuln-list.
Em 2026, o que mudou é a profundidade. Scanners modernos não olham só o manifesto package.json: eles desempacotam layers tar, leem /var/lib/dpkg/status, parseiam binários Go com buildinfo e identificam dependências Rust via Cargo.lock incrustado no binário. O resultado é um SBOM (Software Bill of Materials), basicamente uma lista de ingredientes, e um relatório de CVEs com severidade CVSS v4.0, KEV (Known Exploited Vulnerabilities) da CISA e, agora com Trivy 0.58, scores EPSS (probabilidade de exploração nos próximos 30 dias).
Sem esse scan na pipeline, você está enviando para produção, em média, 180 vulnerabilidades por imagem padrão segundo o relatório Sysdig Cloud-Native Security Report 2025. Com gate adequado, esse número cai para menos de 10, e nenhuma das que sobram é crítica.
Trivy vs Grype: qual escolher em 2026
A pergunta certa não é "qual é melhor", é "qual cobre o seu caso de uso primeiro". Eu uso os dois em projetos diferentes. Abaixo está a comparação que faço para clientes quando eles precisam decidir.
Critério
Trivy 0.58
Grype 0.85 + Syft 1.18
Mantenedor
Aqua Security
Anchore
Licença
Apache 2.0
Apache 2.0
Alvos suportados
Imagens, FS, Git, K8s, IaC, AWS, secrets
Imagens, FS, SBOM
Formato SBOM
CycloneDX 1.6, SPDX 2.3, SPDX 3.0
CycloneDX 1.6, SPDX 2.3, Syft JSON
Detecção em distroless
Boa (precisa Buildinfo)
Excelente (Syft é melhor)
IaC scanning (Terraform, K8s YAML)
Sim, nativo
Não (apenas K8s via plugin)
Velocidade média (imagem 500MB)
8 a 12s
15 a 20s
Integração K8s contínua
Trivy Operator
Sem operator próprio
EPSS e KEV
Sim (0.55+)
Sim (0.80+)
Resumindo o que vejo na prática: use Trivy se quiser um único binário para imagens, IaC, secrets e Kubernetes; é o padrão de fato em pipelines GitHub Actions. Use Grype + Syft quando precisa do melhor SBOM do mercado para imagens distroless ou para auditoria de compliance NIST 800-218 SSDF, onde o Syft tem cobertura superior de linguagens compiladas. Honestamente, para máxima confiança eu rodo os dois e cruzo resultados. Leva 30 segundos a mais e elimina os pontos cegos de cada scanner.
Instalando e configurando o Trivy
O Trivy é distribuído como binário estático, container, pacote nativo (apt/dnf/brew) e Helm chart. Em pipelines CI eu prefiro o binário estático: sem dependências, fácil de cachear, fácil de pinar versão. Em workstations Linux, o repositório oficial é a opção mais limpa porque garante atualizações via apt update.
# Debian/Ubuntu — repositório oficial Aqua Security
sudo apt-get install -y wget gnupg lsb-release
wget -qO - https://aquasecurity.github.io/trivy-repo/deb/public.key | \
sudo gpg --dearmor -o /usr/share/keyrings/trivy.gpg
echo "deb [signed-by=/usr/share/keyrings/trivy.gpg] \
https://aquasecurity.github.io/trivy-repo/deb $(lsb_release -sc) main" | \
sudo tee /etc/apt/sources.list.d/trivy.list
sudo apt-get update
sudo apt-get install -y trivy
# Confirme a versao (0.58+ tem EPSS e SPDX 3.0)
trivy --version
Para pipelines reproducíveis, pino a versão exata e baixo o binário direto:
# Binario estatico, ideal para CI
TRIVY_VERSION="0.58.1"
curl -sL "https://github.com/aquasecurity/trivy/releases/download/v${TRIVY_VERSION}/trivy_${TRIVY_VERSION}_Linux-64bit.tar.gz" \
| tar -xz -C /usr/local/bin trivy
trivy --version
Antes do primeiro scan, o Trivy baixa o banco de vulnerabilidades (~120MB). Em CI você quer cachear isso para não rebaixar a cada job. O arquivo ~/.cache/trivy é o alvo. Configure também o TRIVY_DB_REPOSITORY para um mirror OCI privado se sua rede bloquear o GitHub Container Registry. É uma exigência comum em pentests que faço em bancos e telecoms.
Como escanear imagens Docker com Trivy
O comando básico é trivy image <ref>, mas em produção você precisa de pelo menos três flags: --severity para filtrar ruído, --exit-code 1 para quebrar o build e --ignore-unfixed para não falhar por CVEs sem patch upstream (caso contrário você quebra todo build de imagem baseada em Debian estável).
# Scan basico, saida tabela colorida no terminal
trivy image nginx:1.27-alpine
# Scan de producao: falha o build se houver CVEs HIGH ou CRITICAL com fix disponivel
trivy image \
--severity HIGH,CRITICAL \
--ignore-unfixed \
--exit-code 1 \
--format json \
--output report.json \
myregistry.io/api:v2.4.1
# Scan combinado: vulnerabilidades, secrets e misconfig
trivy image \
--pkg-types os,library \
--vex repo \
--severity HIGH,CRITICAL \
--scanners vuln,secret,misconfig \
myregistry.io/api:v2.4.1
Note o --scanners vuln,secret,misconfig: o Trivy também procura secrets vazados (chaves AWS, tokens GitHub, JWTs) e más configurações em Dockerfiles (USER root, ADD com URL remota, sem HEALTHCHECK). Em quase todo pentest que executo, encontro pelo menos um token de produção esquecido em uma camada intermediária. Docker layer caching é o pior amigo do desenvolvedor distraído.
Para auditoria detalhada de redes corporativas, costumo cruzar o relatório do Trivy com o output de detecção de intrusões com Wazuh e Osquery. Se uma CVE crítica está presente na imagem E o Wazuh detecta processo suspeito tocando o binário vulnerável, você tem evidência forte de exploração ativa.
Como gerar SBOM com Trivy em CycloneDX e SPDX
SBOM (Software Bill of Materials) é a lista de ingredientes da sua imagem. Desde 2022, com o Executive Order 14028 dos EUA, e em 2026 com o Cyber Resilience Act da União Europeia entrando em vigor pleno, ter SBOM versionado e assinado deixou de ser nicho. Virou regulatório. O Trivy gera SBOM em dois formatos padrão (CycloneDX, mantido pela OWASP, e SPDX, mantido pela Linux Foundation) e em Syft JSON para interoperabilidade.
# SBOM CycloneDX 1.6, preferido pela maioria das ferramentas comerciais
trivy image \
--format cyclonedx \
--output sbom.cdx.json \
myregistry.io/api:v2.4.1
# SBOM SPDX 2.3 JSON, exigido por contratos com governo dos EUA (FedRAMP)
trivy image \
--format spdx-json \
--output sbom.spdx.json \
myregistry.io/api:v2.4.1
# Scan de uma imagem usando SBOM ja gerado (rapido, sem baixar a imagem)
trivy sbom sbom.cdx.json --severity CRITICAL
O fluxo correto em DevSecOps 2026 é assim: gerar SBOM no build, assinar com Cosign, enviar para o registry OCI ao lado da imagem e deixar que consumidores baixem o SBOM, validem assinatura e escaneiem novamente sob demanda. Isso desacopla a geração da análise. Quando o NVD adiciona um CVE novo amanhã para uma lib que você usou hoje, você reescaneia o SBOM em segundos, sem reconstruir a imagem.
# Assinar SBOM com Cosign keyless (OIDC), recomendado em CI
cosign attest \
--type cyclonedx \
--predicate sbom.cdx.json \
--yes \
myregistry.io/api:v2.4.1
Integrando Trivy ao GitHub Actions e GitLab CI
O lugar certo para o scan é o pipeline, não o laptop do dev. Eu prefiro um job dedicado que falha o build se houver CVEs críticas com fix disponível, gera SBOM como artefato e faz upload do resultado SARIF para o GitHub Security tab. Isso aparece no PR como anotação inline, exatamente onde o revisor olha.
Quem implementa pipeline de segurança costuma esquecer um detalhe: o scanner também precisa rodar em imagens já em produção, não só no build. Pelo menos uma vez por dia, scaneie o que está rodando no cluster, porque CVEs novas saem todo dia e a imagem que era limpa na quarta-feira pode ter três CRITICALs na sexta. É exatamente isso que o Trivy Operator resolve, e eu vou cobrir abaixo. Para a parte de runtime detection (processo malicioso já em execução), veja o guia comparando Falco e Tetragon para segurança runtime.
Grype + Syft: a alternativa do Anchore
Grype é, na minha visão, o melhor scanner do mercado para imagens distroless e binários Go/Rust. Isso porque ele consome SBOMs gerados pelo Syft, que tem o melhor catálogo de fontes de pacotes (mais de 30 ecossistemas, incluindo Cargo, Conan, dotnet deps.json, Erlang/Elixir hex e Hackage). Em pentests de stacks polyglot, o Grype encontra CVEs que outros scanners perdem.
# Instalar Grype + Syft (binarios estaticos)
curl -sSfL https://raw.githubusercontent.com/anchore/grype/main/install.sh | sh -s -- -b /usr/local/bin
curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh -s -- -b /usr/local/bin
# Gerar SBOM com Syft e escanear com Grype
syft myregistry.io/api:v2.4.1 -o cyclonedx-json > sbom.cdx.json
grype sbom:./sbom.cdx.json --fail-on high
# Fluxo direto (Grype chama Syft internamente)
grype myregistry.io/api:v2.4.1 \
--only-fixed \
--fail-on critical \
--output table
O Grype tem um truque excelente: --add-cpes-if-none. Quando o Syft não consegue inferir o CPE (identificador NVD) de um pacote, o Grype tenta gerar candidatos e cruza com o banco. Isso reduz falsos negativos em libs C/C++ compiladas estaticamente, onde a versão fica enterrada num símbolo BSS. Para mais detalhes consulte a documentação oficial do Grype no GitHub.
Tratando falsos positivos com .trivyignore e VEX
Todo pipeline de segurança morre por excesso de ruído. Quando o time de dev começa a ver builds quebrando por CVEs que não afetam o caminho de código real, ele vai pressionar para desligar o scanner. A solução não é desligar. É documentar exceções de forma versionada e auditável.
O Trivy aceita três mecanismos: .trivyignore (lista plana de CVEs ignorados), trivy-ignore.yaml (com expiração, contexto e razão) e arquivos VEX (Vulnerability Exploitability eXchange) no formato OpenVEX ou CycloneDX VEX. VEX é o padrão correto em 2026 porque é interoperável entre scanners: você mantém um único vex.json e aplica em Trivy, Grype e ferramentas comerciais.
# .trivyignore, formato simples
CVE-2023-12345
CVE-2024-67890
# trivy-ignore.yaml, recomendado em 2026
vulnerabilities:
- id: CVE-2023-12345
paths: ["usr/lib/x86_64-linux-gnu/libcrypto.so.3"]
statement: "Nao exploitavel: a funcao vulneravel EVP_PKEY_decrypt nunca eh chamada"
expired-at: "2026-12-31"
Aplicação: trivy image --vex vex.json myregistry.io/api:v2.4.1. Cada exceção precisa ter justification de uma lista fechada do padrão (component_not_present, vulnerable_code_not_present, vulnerable_code_not_in_execute_path, vulnerable_code_cannot_be_controlled_by_adversary, inline_mitigations_already_exist). Isso impede o típico "ignora porque o dev disse que tá tudo bem".
Trivy Operator no Kubernetes
Build-time scan resolve metade do problema. A outra metade é o que acontece com imagens já em execução: uma CVE descoberta hoje numa lib que você usa há seis meses. O Trivy Operator (parte do projeto Aqua Open Source) instala um operador Kubernetes que faz scan contínuo de toda imagem em execução, gera CRDs VulnerabilityReport e ConfigAuditReport, e exporta para Prometheus.
# Instalar via Helm
helm repo add aqua https://aquasecurity.github.io/helm-charts/
helm install trivy-operator aqua/trivy-operator \
--namespace trivy-system \
--create-namespace \
--set trivy.severity=HIGH\,CRITICAL \
--set trivy.ignoreUnfixed=true \
--set operator.scanJobsConcurrentLimit=5
# Consultar relatorios
kubectl get vulnerabilityreports -A
kubectl get configauditreports -A
# Exportar metricas para Prometheus
kubectl port-forward -n trivy-system svc/trivy-operator 8080:80
curl http://localhost:8080/metrics | grep trivy_image_vulnerabilities
Combinado com Kyverno ou Kubewarden como admission controller, você pode bloquear deploy de imagens não escaneadas ou com CVE crítica. Política como código, aplicada na entrada do cluster. Para validar a postura geral do host antes de admitir workloads sensíveis, vale rodar uma auditoria periódica com Lynis e CIS Benchmarks no nó worker. Um host comprometido invalida qualquer hardening de contêiner.
Para um mergulho profundo na spec do CycloneDX, incluindo o objeto vulnerabilities embutido e suporte a VDR/VEX, consulte a especificação oficial do CycloneDX mantida pela OWASP. A documentação do Trivy em trivy.dev tem exemplos completos de cada um dos modos cobertos aqui.
Perguntas Frequentes
Trivy é gratuito para uso comercial?
Sim. O Trivy é open source sob licença Apache 2.0, mantido pela Aqua Security, e pode ser usado livremente em projetos comerciais. A Aqua oferece uma versão paga (Aqua Premium) com banco de vulnerabilidades expandido e suporte SLA, mas o Trivy open source cobre os casos de uso da grande maioria das equipes DevSecOps.
Trivy detecta secrets vazados em imagens Docker?
Sim. Com a flag --scanners secret o Trivy procura mais de 100 tipos de secrets (chaves AWS, tokens GitHub, JWTs, chaves SSH privadas e strings de conexão de banco) em qualquer camada da imagem. É comum encontrar secrets em camadas intermediárias do Dockerfile mesmo quando o desenvolvedor "removeu" no estágio final, porque cada RUN gera uma camada permanente.
Como atualizar o banco de vulnerabilidades do Trivy?
O Trivy atualiza o DB automaticamente a cada execução, mas você pode forçar com trivy image --download-db-only. Em CI o DB é cacheado em ~/.cache/trivy; configure o cache do GitHub Actions ou GitLab para evitar download de 120MB a cada job. Desde 2024 o DB é distribuído via OCI em ghcr.io/aquasecurity/trivy-db.
Qual a diferença entre CycloneDX e SPDX para SBOM?
CycloneDX, mantido pela OWASP, é mais focado em segurança e suporta nativamente objetos de vulnerabilidades, VEX e assinaturas. SPDX, mantido pela Linux Foundation e padronizado como ISO/IEC 5962, é exigido em contratos governamentais dos EUA (FedRAMP) e foca em compliance de licenças. Para DevSecOps moderno, gere os dois; o custo é baixo e cobre todos os consumidores.
Posso usar Trivy sem ter Docker instalado?
Sim. O Trivy suporta scan de imagens diretamente de registries OCI via trivy image --image-src remote, sem precisar do Docker daemon. Também escaneia tarballs (trivy image --input image.tar) e sistemas de arquivos locais (trivy fs ./). Isso é útil em runners CI minimalistas ou em ambientes air-gapped.
Guia prático para assinar imagens Docker com Cosign 2.4 (keyless), anexar SBOM e attestations SLSA, e bloquear deploys não assinados no Kubernetes com Policy Controller.