Escaneo de Vulnerabilidades en Contenedores con Trivy
Trivy es un escáner de vulnerabilidades de código abierto desarrollado por Aqua Security que analiza imágenes de contenedor, sistemas de archivos y repositorios de código para detectar CVEs conocidos, secretos expuestos y configuraciones incorrectas. Su velocidad, facilidad de uso y amplia base de datos de vulnerabilidades lo han convertido en la herramienta estándar para seguridad de contenedores en pipelines CI/CD. Esta guía cubre la instalación de Trivy, integración en CI/CD y generación de SBOMs.
Requisitos Previos
- Servidor Linux (Ubuntu 22.04/Debian 12 o CentOS 9/Rocky 9)
- Docker instalado (para escanear imágenes)
- Mínimo 1 GB de RAM y 1 GB de disco para la base de datos de vulnerabilidades
- Acceso a Internet para descargar la base de datos de CVEs
Instalación de Trivy
# Ubuntu/Debian: usar el repositorio oficial de Aqua Security
wget -qO - https://aquasecurity.github.io/trivy-repo/deb/public.key | \
gpg --dearmor -o /usr/share/keyrings/trivy-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/trivy-archive-keyring.gpg] \
https://aquasecurity.github.io/trivy-repo/deb $(lsb_release -sc) main" | \
tee /etc/apt/sources.list.d/trivy.list
apt-get update && apt-get install -y trivy
# CentOS/Rocky Linux
cat > /etc/yum.repos.d/trivy.repo << 'EOF'
[trivy]
name=Trivy repository
baseurl=https://aquasecurity.github.io/trivy-repo/rpm/releases/$releasever/$basearch/
gpgcheck=1
enabled=1
gpgkey=https://aquasecurity.github.io/trivy-repo/rpm/public.key
EOF
dnf install -y trivy
# Verificar la instalación
trivy --version
# Actualizar la base de datos de vulnerabilidades
trivy image --download-db-only
Escaneo de Imágenes de Contenedor
# Escanear una imagen pública del registro de Docker
trivy image nginx:latest
# Escanear una imagen con salida compacta (tabla)
trivy image --format table nginx:latest
# Escanear una imagen de un registro privado
trivy image --username usuario --password token \
registry.empresa.com/app:latest
# Escanear una imagen local (no pull)
docker build -t mi-app:latest .
trivy image --input mi-app.tar mi-app:latest
# Exportar imagen y escanear sin Docker daemon
docker save mi-app:latest > /tmp/mi-app.tar
trivy image --input /tmp/mi-app.tar
# Incluir vulnerabilidades no corregidas (unfixed)
trivy image --include-unfixed nginx:latest
# Escanear solo paquetes del SO (ignorar dependencias de aplicación)
trivy image --security-checks vuln --vuln-type os nginx:latest
# Escanear solo dependencias de aplicación (npm, pip, etc.)
trivy image --security-checks vuln --vuln-type library nginx:latest
Filtrado por Severidad
# Mostrar solo vulnerabilidades CRÍTICAS y ALTAS
trivy image --severity CRITICAL,HIGH nginx:latest
# Fallar el escaneo si hay vulnerabilidades críticas (útil en CI/CD)
trivy image --severity CRITICAL --exit-code 1 nginx:latest
echo "Código de salida: $?"
# Ignorar vulnerabilidades específicas (conocidas o aceptadas)
cat > /tmp/.trivyignore << 'EOF'
# Ignorar CVE específico porque ya está mitigado en nuestra configuración
CVE-2023-1234
# Ignorar otro CVE con justificación
CVE-2023-5678
EOF
trivy image --ignorefile /tmp/.trivyignore --severity CRITICAL,HIGH nginx:latest
# Ignorar vulnerabilidades sin parche disponible
trivy image --ignore-unfixed --severity CRITICAL,HIGH nginx:latest
# Definir umbral máximo de días para vulnerabilidades publicadas
trivy image --severity HIGH --ignore-policy /tmp/trivy-policy.rego nginx:latest
Escaneo de Sistema de Archivos
Trivy puede escanear el sistema de archivos local, ideal para repositorios de código:
# Escanear el directorio actual (busca dependencias y Dockerfiles)
trivy fs .
# Escanear un repositorio de código en busca de secretos y vulns
trivy fs --security-checks vuln,secret,config .
# Escanear solo secretos en el código (tokens, contraseñas, claves)
trivy fs --security-checks secret /ruta/al/proyecto
# Escanear un Dockerfile en busca de malas configuraciones
trivy config ./Dockerfile
# Escanear archivos de configuración de Kubernetes
trivy config /ruta/a/manifiestos-kubernetes/
# Escanear Helm charts
trivy config ./helm-chart/
# Escanear Terraform
trivy config ./terraform/
Generación de SBOM
Un SBOM (Software Bill of Materials) lista todos los componentes de software de una imagen:
# Generar SBOM en formato CycloneDX
trivy image --format cyclonedx --output sbom.json nginx:latest
# Generar SBOM en formato SPDX
trivy image --format spdx-json --output sbom.spdx.json nginx:latest
# Generar SBOM en formato SPDX de texto
trivy image --format spdx --output sbom.spdx nginx:latest
# Escanear un SBOM ya generado (sin necesitar la imagen)
trivy sbom sbom.json
# Generar informe de vulnerabilidades a partir de SBOM
trivy sbom --format table sbom.json
# Guardar el SBOM junto con el informe de vulnerabilidades
trivy image \
--format cyclonedx \
--output sbom-with-vulns.json \
--report summary \
nginx:latest
Integración en CI/CD
Integración con GitHub Actions:
# .github/workflows/security-scan.yml
name: Escaneo de Seguridad con Trivy
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
jobs:
scan:
name: Escanear imagen de contenedor
runs-on: ubuntu-latest
steps:
- name: Checkout del código
uses: actions/checkout@v4
- name: Construir imagen Docker
run: docker build -t mi-app:${{ github.sha }} .
- name: Escanear con Trivy (solo vulnerabilidades críticas)
uses: aquasecurity/trivy-action@master
with:
image-ref: mi-app:${{ github.sha }}
format: sarif
output: trivy-results.sarif
severity: CRITICAL,HIGH
exit-code: 1
ignore-unfixed: true
- name: Subir resultados a GitHub Security
uses: github/codeql-action/upload-sarif@v3
if: always()
with:
sarif_file: trivy-results.sarif
Integración en pipelines GitLab CI:
# .gitlab-ci.yml (sección de escaneo de seguridad)
# Añadir como job de seguridad en el pipeline
# trivy-scan.sh - Script para CI/CD genérico
cat > /usr/local/bin/trivy-scan-ci.sh << 'SCRIPT'
#!/bin/bash
IMAGE="${1:?Especificar imagen a escanear}"
SEVERITY="${SEVERITY:-CRITICAL,HIGH}"
EXIT_ON_VULN="${EXIT_ON_VULN:-1}"
echo "=== Escaneando imagen: $IMAGE ==="
echo "=== Severidad mínima: $SEVERITY ==="
# Actualizar base de datos de Trivy
trivy image --download-db-only --quiet
# Ejecutar escaneo
trivy image \
--severity "$SEVERITY" \
--exit-code "$EXIT_ON_VULN" \
--ignore-unfixed \
--format table \
"$IMAGE"
EXIT_CODE=$?
if [ $EXIT_CODE -eq 0 ]; then
echo "✓ Escaneo completado: sin vulnerabilidades $SEVERITY"
else
echo "✗ Escaneo fallido: se encontraron vulnerabilidades $SEVERITY"
fi
exit $EXIT_CODE
SCRIPT
chmod +x /usr/local/bin/trivy-scan-ci.sh
Aplicación de Políticas
Trivy soporta políticas en Rego (Open Policy Agent) para reglas personalizadas:
# Crear una política OPA/Rego para Trivy
mkdir -p /opt/trivy/policies
cat > /opt/trivy/policies/deny-high-crit.rego << 'EOF'
package main
import future.keywords
# Denegar imágenes con vulnerabilidades críticas en paquetes específicos
deny[msg] {
vuln := input.Results[_].Vulnerabilities[_]
vuln.Severity == "CRITICAL"
vuln.PkgName == "openssl"
msg := sprintf("Vulnerabilidad crítica en OpenSSL: %s", [vuln.VulnerabilityID])
}
# Denegar imágenes corriendo como root
deny[msg] {
input.Metadata.ImageConfig.Config.User == ""
msg := "La imagen ejecuta procesos como root (sin USER definido en Dockerfile)"
}
EOF
# Usar la política personalizada en el escaneo
trivy image \
--security-checks vuln,config \
--policy /opt/trivy/policies/ \
--exit-code 1 \
nginx:latest
Solución de Problemas
# Actualizar la base de datos de vulnerabilidades manualmente
trivy image --download-db-only
# Ver la versión de la base de datos actualmente instalada
trivy --version | grep DB
# Limpiar la caché de Trivy (si hay problemas con la base de datos)
trivy image --clear-cache
# o eliminar el directorio de caché
rm -rf ~/.cache/trivy
# Trivy timeout al descargar la base de datos
# Usar un timeout mayor
TRIVY_TIMEOUT=10m trivy image nginx:latest
# Usar una base de datos mirror (para entornos sin acceso a GitHub)
trivy image --db-repository ghcr.io/aquasecurity/trivy-db nginx:latest
# Modo sin conexión (con base de datos pre-descargada)
trivy image --offline-scan --skip-db-update nginx:latest
# Ver qué paquetes tiene una imagen (sin escanear vulnerabilidades)
trivy image --list-all-pkgs nginx:latest
# Debug del escaneo
trivy image --debug nginx:latest 2>&1 | head -50
Conclusión
Trivy es la herramienta más completa y accesible para la seguridad de contenedores, combinando escaneo de vulnerabilidades CVE, detección de secretos, análisis de configuraciones incorrectas y generación de SBOM en una sola herramienta sin configuración compleja. Su integración nativa en pipelines CI/CD con fallo de build automático ante vulnerabilidades críticas convierte el escaneo de seguridad en una parte natural del ciclo de desarrollo, desplazando la responsabilidad de seguridad hacia el principio del pipeline (shift-left security).


