Scanning de imagens Docker com Trivy

1. Introdução ao Trivy e Segurança de Imagens

O uso de contêineres Docker transformou a forma como desenvolvemos e implantamos aplicações. No entanto, imagens Docker frequentemente contêm vulnerabilidades de segurança introduzidas por bibliotecas, pacotes do sistema operacional ou dependências de aplicação. Um estudo recente mostrou que mais de 40% das imagens públicas no Docker Hub contêm vulnerabilidades de alta ou crítica severidade. Ignorar esses riscos pode expor seu ambiente a ataques como execução remota de código, escalonamento de privilégios e vazamento de dados.

O Trivy (desenvolvido pela Aqua Security) é uma ferramenta open-source de scanning de vulnerabilidades, projetada especificamente para contêineres, sistemas de arquivos e repositórios Git. Diferente de análises de código-fonte estático (SAST), que examinam o código da aplicação, o Trivy foca nos binários, bibliotecas e pacotes empacotados na imagem. Ele consulta bancos de dados como NVD (National Vulnerability Database), Red Hat OVAL, Debian Security Tracker e GitHub Advisory Database para identificar CVEs (Common Vulnerabilities and Exposures) conhecidas.

2. Instalação e Primeiros Passos

A instalação do Trivy é simples e pode ser feita de várias formas. No Linux (Ubuntu/Debian):

sudo apt-get install wget apt-transport-https gnupg lsb-release
wget -qO - https://aquasecurity.github.io/trivy-repo/deb/public.key | sudo apt-key add -
echo deb https://aquasecurity.github.io/trivy-repo/deb $(lsb_release -sc) main | sudo tee -a /etc/apt/sources.list.d/trivy.list
sudo apt-get update
sudo apt-get install trivy

No macOS via Homebrew:

brew install trivy

Ou usando o próprio Docker (útil para ambientes sem instalação permanente):

docker run --rm -v /var/run/docker.sock:/var/run/docker.sock aquasec/trivy image nginx:latest

O comando básico para escanear uma imagem local é:

trivy image nginx:latest

A saída exibe uma tabela com colunas: Biblioteca, Vulnerabilidade, Severidade, Instalado, Corrigido em. As severidades seguem a classificação CVSS: CRITICAL, HIGH, MEDIUM, LOW e UNKNOWN. Exemplo de saída simplificada:

nginx:latest (debian 11.6)
===========================
Total: 45 (UNKNOWN: 0, LOW: 20, MEDIUM: 18, HIGH: 6, CRITICAL: 1)

+----------------+------------------+----------+-------------------+------------------+
|   BIBLIOTECA    | VULNERABILIDADE  | SEVERIDADE | INSTALADO        | CORRIGIDO EM     |
+----------------+------------------+----------+-------------------+------------------+
| libcrypto1.1   | CVE-2023-3817    | CRITICAL  | 1.1.1n-0+deb11u5 | 1.1.1n-0+deb11u6 |
| libssl1.1      | CVE-2023-3817    | CRITICAL  | 1.1.1n-0+deb11u5 | 1.1.1n-0+deb11u6 |
+----------------+------------------+----------+-------------------+------------------+

3. Modos de Scanning e Opções Essenciais

O Trivy suporta diferentes alvos de scanning. Para escanear uma imagem diretamente de um registry remoto (sem baixar localmente):

trivy image --server https://registry.example.com minha-app:1.0

Para escanear um sistema de arquivos (útil para verificar diretórios com dependências):

trivy filesystem --severity CRITICAL,HIGH /caminho/para/projeto

Para escanear um repositório Git clonado:

trivy repo https://github.com/meuprojeto/minha-app.git

Opções essenciais incluem:

  • --severity CRITICAL,HIGH: filtra apenas vulnerabilidades com essas severidades
  • --ignore-unfixed: ignora vulnerabilidades sem correção disponível
  • --skip-dirs ou --skip-files: exclui diretórios/arquivos específicos do scan
  • --timeout 10m: define tempo máximo de execução (útil em pipelines)

Exemplo prático com filtros:

trivy image --severity CRITICAL,HIGH --ignore-unfixed --timeout 5m node:18-alpine

4. Integração com Pipeline CI/CD

A verdadeira potência do Trivy aparece quando integrado a pipelines de CI/CD, permitindo bloquear deploys de imagens inseguras.

GitHub Actions — exemplo de workflow que escaneia a imagem após o build:

name: Security Scan
on: [push, pull_request]

jobs:
  trivy-scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3

      - name: Build Docker image
        run: docker build -t minha-app:${{ github.sha }} .

      - name: Run Trivy vulnerability scanner
        uses: aquasecurity/trivy-action@master
        with:
          image-ref: 'minha-app:${{ github.sha }}'
          format: 'sarif'
          output: 'trivy-results.sarif'
          severity: 'CRITICAL,HIGH'

      - name: Upload SARIF to GitHub Security Tab
        uses: github/codeql-action/upload-sarif@v2
        with:
          sarif_file: 'trivy-results.sarif'

      - name: Fail if critical vulnerabilities found
        run: |
          trivy image --exit-code 1 --severity CRITICAL minha-app:${{ github.sha }}

GitLab CI — exemplo de job que quebra o pipeline se houver vulnerabilidades críticas:

trivy-scan:
  stage: test
  image: docker:20.10.16
  services:
    - docker:dind
  variables:
    DOCKER_HOST: tcp://docker:2375
  script:
    - apk add --no-cache curl
    - curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh
    - docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA .
    - trivy image --exit-code 1 --severity CRITICAL $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA

O parâmetro --exit-code 1 faz o Trivy retornar código de erro se vulnerabilidades forem encontradas, quebrando o pipeline automaticamente.

5. Geração de Relatórios e Formatos de Saída

O Trivy suporta múltiplos formatos de saída, essenciais para automação e auditoria:

  • table (padrão): legível para humanos
  • json: ideal para processamento programático
  • sarif: formato padrão para ferramentas de segurança (GitHub Security Tab, Azure DevOps)
  • html: relatório visual para stakeholders
  • cyclonedx: formato SBOM (Software Bill of Materials)

Gerando saída JSON para análise automatizada:

trivy image --format json --output resultado.json nginx:latest

Exemplo de trecho do JSON gerado:

{
  "Results": [
    {
      "Target": "nginx:latest (debian 11.6)",
      "Vulnerabilities": [
        {
          "VulnerabilityID": "CVE-2023-3817",
          "PkgName": "libcrypto1.1",
          "Severity": "CRITICAL",
          "InstalledVersion": "1.1.1n-0+deb11u5",
          "FixedVersion": "1.1.1n-0+deb11u6"
        }
      ]
    }
  ]
}

Gerando relatório SARIF para integração com o GitHub Security Tab:

trivy image --format sarif --output trivy-results.sarif node:18-alpine

6. Boas Práticas e Estratégias de Remediação

Nem toda vulnerabilidade identificada é um risco real para sua aplicação. É importante diferenciar:

  • Vulnerabilidades reais: afetam bibliotecas realmente utilizadas em tempo de execução
  • Falsos positivos: bibliotecas presentes na imagem mas não utilizadas pelo código

Estratégias de remediação eficientes:

  1. Rebuild da imagem: sempre que possível, reconstrua a imagem com a base atualizada
  2. Atualização da base image: troque ubuntu:latest por ubuntu:22.04 (versão específica) e mantenha-a atualizada
  3. Uso de imagens slim: prefira node:18-slim ou alpine — reduzem drasticamente a superfície de ataque
  4. Arquivo .trivyignore: para aceitar riscos documentados, crie um arquivo com CVEs a ignorar:
# .trivyignore
CVE-2023-1234
CVE-2023-5678

E execute:

trivy image --ignorefile .trivyignore nginx:latest

7. Limitações e Considerações Finais

O Trivy é excelente para identificar vulnerabilidades conhecidas em pacotes e bibliotecas, mas possui limitações importantes:

  • Não cobre vulnerabilidades de runtime: configurações incorretas de rede, permissões de contêiner, ou mau uso de capabilities do kernel
  • Não analisa configuração: erros como privileged: true ou montagens inseguras de volumes não são detectados
  • Depende de bancos de dados atualizados: vulnerabilidades recentes (zero-day) podem não ser detectadas até atualização do banco

Comparado a outras ferramentas:
- Clair: scanning estático similar, mas menos flexível em formatos de saída
- Snyk: oferece análise mais profunda de dependências de aplicação, mas é pago para funcionalidades avançadas
- Grype: alternativa open-source com foco em velocidade, mas banco de dados menos abrangente

A segurança de imagens Docker não é um evento único. Incorpore o Trivy em seu pipeline de CI/CD, execute scans regularmente (inclusive em imagens em produção) e estabeleça políticas claras de aceitação de riscos. Lembre-se: uma imagem segura hoje pode conter vulnerabilidades amanhã, à medida que novas CVEs são descobertas.


Referências