Escanear imágenes de contenedor antes del despliegue ha pasado de ser "buena práctica" a requisito en pipelines modernos. Dos herramientas open-source dominan este espacio: Trivy[1] de Aqua Security y Grype[2] de Anchore. Ambas hacen bien el trabajo básico, con diferencias sutiles que importan según el contexto.

Puntos clave

  • Trivy y Grype cubren más del 95% de los mismos CVE en escenarios típicos; la diferencia real está en el ecosistema y la velocidad.

  • Trivy destaca en escaneo de IaC (Terraform, Kubernetes manifests) y tiene mejor integración todo-en-uno.

  • Grype brilla cuando ya se usa Syft para generar SBOMs: el pipeline SBOM→escaneo es nativo.

  • El mayor problema operativo de ambas no es la cobertura, sino la fatiga por falsos positivos: .trivyignore y VEX son la respuesta.

  • Lo importante es tener al menos una de las dos: ambas son mejor que ninguna.

Qué hace cada una

Las dos escanean imágenes (y más) contra bases de datos de vulnerabilidades conocidas. Detectan:

  • Paquetes de sistema operativo vulnerables (apt, rpm, apk).

  • Dependencias de lenguaje con CVE (npm, pip, gem, go.mod, Cargo).

  • Ficheros de configuración problemáticos (Dockerfiles con patrones inseguros, manifests Kubernetes expuestos).

  • SBOMs en varios formatos.

La salida es una lista de vulnerabilidades con severidad, paquete afectado y CVE ID.

Diferencias de arquitectura

Trivy

  • Base de datos interna Trivy DB[3]: sincroniza desde múltiples fuentes (NVD, vendor advisories, GitHub Security Advisories).

  • Formato comprimido (~50 MB), diseñado para escaneos offline.

  • Soporta imágenes, filesystems locales, repositorios git e IaC (Terraform, CloudFormation, Kubernetes).

  • Modo cliente-servidor para escaneos distribuidos.

Grype

  • Base de datos Vulnerability Database[4]: compilada desde fuentes similares.

  • Usa Syft[5] para generación de SBOM (mismo equipo), haciendo el pipeline SBOM→escaneo nativo.

  • Más modular: Syft genera el SBOM, Grype lo escanea, herramientas adicionales lo consumen.

  • Soporta attestations de SBOM vía cosign.

Cobertura comparada

En tests sobre cinco imágenes (alpine, debian, node, python, ruby):

  • Ambas detectan la gran mayoría de CVE conocidas en paquetes de SO.

  • Trivy suele detectar más en ecosistemas de lenguaje por integración más directa con lockfiles.

  • Grype destaca con imágenes con SBOM precomputado por Syft, eliminando la reindexación.

  • Ambas pueden dar falsos positivos por versiones backporteadas: el parche está aplicado pero el número de versión sigue siendo el "vulnerable" para el CVE base.

La diferencia de cobertura es menor del 5% en escenarios típicos. Más relevante: la velocidad de actualización de bases de datos y la calidad de interpretación de severidad.

Pipeline CI/CD con etapas de build, test y despliegue, donde se integra el escaneo de imágenes con Trivy o GrypePipeline CI/CD con etapas de build, test y despliegue, donde se integra el escaneo de imágenes con Trivy o Grype (Imagen: GModena (WMF), CC BY-SA 4.0, vía Wikimedia Commons)

Rendimiento

Benchmarks sobre una imagen Python 3.11 de ~200 MB:

  • Trivy: 3-5 segundos en primera ejecución con caché de DB, < 1s en ejecuciones subsiguientes.

  • Grype: 4-6 segundos en primera ejecución, ~2s en subsiguientes.

Para CI con imágenes grandes (>1 GB, multi-stack), la velocidad importa. Con 50-100 builds/día, cualquiera de las dos es suficiente. En pipelines con cientos de builds/hora, Trivy es algo más rápido en ambas medidas.

Integración en CI

Trivy en GitHub Actions

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

El flag exit-code: '1' falla el build si hay CRITICAL o HIGH. Integración con el GitHub Security tab[6] vía SARIF.

Grype en GitLab CI

scan_image:
  stage: test
  script:
    - grype my-app:$CI_COMMIT_SHA -o sarif > grype.sarif
    - grype my-app:$CI_COMMIT_SHA --fail-on high

Ambas se integran con SonarQube, DefectDojo y otros agregadores de resultados.

Gestión de falsos positivos

El problema operacional más común: demasiados falsos positivos generan fatiga y llevan a ignorar alertas reales. Dos enfoques complementarios:

  • .trivyignore[7] (Trivy) o equivalente en Grype: listar explícitamente CVEs que no aplican (parche aplicado, funcionalidad no usada).

  • VEX (Vulnerability Exploitability eXchange): formato emergente para declarar qué vulnerabilidades son explotables en el contexto específico. Ambas herramientas añaden soporte activamente.

Mantener estas listas requiere disciplina: revisión trimestral para no acumular supresiones obsoletas que oculten problemas reales.

Más allá del escaneo básico

Ambas herramientas van más allá de los CVE:

  • Políticas y compliance: reglas que fallan builds si se usan imágenes base no permitidas o si las imágenes superan cierto tamaño.

  • Licencias: detectar dependencias con licencias incompatibles (GPL en producto comercial cerrado).

  • Secrets: detectar API keys o credenciales expuestas en layers de imagen (Trivy tiene --scanners secret).

Para contexto sobre la capa de defensa más amplia, ver ataques a la cadena de suministro y cómo defenderse: el escaneo es una capa, no la única. La cadena completa incluye SLSA nivel 3 para atestiguar la procedencia del build. La integración de estas herramientas en Kubernetes 1.27 se complementa con admission controllers que verifican atestados antes de admitir imágenes.

Conclusión

Trivy y Grype son alternativas prácticamente equivalentes para escaneo de imágenes. La diferencia suele estar en el ecosistema más amplio: si ya se usa Anchore/Syft, Grype encaja de forma natural; si se busca una herramienta todo-en-uno con mejor integración IaC, Trivy. Lo importante es tener al menos una integrada en el pipeline: cualquiera de las dos es mejor que ninguna.

Fuentes:

  1. Documentación oficial de Trivy[1]
  2. Grype: repositorio oficial en GitHub (Anchore)[2]
  3. Trivy DB: fuentes de vulnerabilidades (Aqua Security)[3]
  4. Trivy: filtrado y fichero .trivyignore[7]
  5. GitHub Docs: integrar SARIF con el Security tab[6]

Preguntas frecuentes

¿Cómo hago que el build falle si Trivy o Grype encuentran vulnerabilidades graves?

En Trivy, con severity: 'CRITICAL,HIGH' y exit-code: '1' en la action de GitHub el build falla si aparece algo CRITICAL o HIGH, y el formato SARIF se integra con el Security tab de GitHub. En Grype, el flag --fail-on high cumple la misma función en GitLab CI. Ambas se integran también con SonarQube, DefectDojo y otros agregadores.

¿Qué hago con los falsos positivos por versiones backporteadas?

Lístalos explícitamente en .trivyignore (Trivy) o su equivalente en Grype cuando el parche ya está aplicado o la funcionalidad no se usa. Considera también VEX, el formato emergente para declarar qué vulnerabilidades son explotables en tu contexto, que ambas herramientas están incorporando. Revisa esas listas trimestralmente para no acumular supresiones obsoletas que oculten problemas reales.

¿Cuánto tarda un escaneo y cuál de las dos es más rápida?

Sobre una imagen Python 3.11 de unos 200 MB, Trivy tarda 3-5 segundos en la primera ejecución con caché de DB y menos de 1 segundo en las siguientes. Grype tarda 4-6 segundos y unos 2 segundos, respectivamente. Con 50-100 builds al día cualquiera sirve; en pipelines con cientos de builds por hora Trivy suele ser algo más rápida.

Fuentes

  1. Trivy
  2. Grype
  3. Trivy DB
  4. Vulnerability Database
  5. Syft
  6. GitHub Security tab
  7. .trivyignore