Escaneo de Seguridad de Containers
Escanea imágenes de container para vulnerabilidades, misconfiguraciones y secrets con Trivy, Clair y Snyk antes de desplegar a producción.
Visión General
El escaneo de seguridad de containers identifica vulnerabilidades en imágenes Docker antes de que lleguen a producción. Una única imagen base desactualizada puede exponer cientos de CVEs. Herramientas como Trivy, Clair y Snyk analizan paquetes de OS, dependencias de lenguajes e incluso secrets embebidos en capas. Integrar el escaneo en CI/CD crea una puerta de seguridad que previene imágenes vulnerables de desplegarse.
Cuándo Usar
Usa este recurso cuando:
- Las imágenes Docker se construyen de imágenes base públicas que pueden contener CVEs conocidos
- Necesitas cumplir con frameworks de seguridad (SOC 2, PCI-DSS, FedRAMP)
- Los developers agregan dependencias sin revisar su postura de seguridad
- Incidentes de producción han sido rastreados a librerías de sistema vulnerables
Solución
Trivy Scan en CI/CD (GitHub Actions)
name: Container Security Scan
on: [push]
jobs:
scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build image
run: docker build -t myapp:${{ github.sha }} .
- name: Scan with Trivy
uses: aquasecurity/trivy-action@master
with:
image-ref: 'myapp:${{ github.sha }}'
format: 'sarif'
output: 'trivy-results.sarif'
severity: 'CRITICAL,HIGH'
exit-code: '1'
Dockerfile Security Hardening
# Usar imagen base mínima
FROM gcr.io/distroless/nodejs20-debian12
# Ejecutar como non-root
USER 65532:65532
# Read-only root filesystem
COPY --chown=65532:65532 . /app
WORKDIR /app
# Sin shell access; sin package manager
EXPOSE 3000
CMD ["server.js"]
Secret Detection (TruffleHog)
# Escanear capas de imagen para secrets embebidos
trufflehog docker --image=myapp:latest
# Escanear filesystem antes del build
trufflehog filesystem --directory=.
Explicación
Qué detectan los scanners:
| Capa | Issues Detectados | Ejemplo |
|---|---|---|
| Paquetes OS | CVEs en paquetes apt/yum | Vulnerabilidad OpenSSL |
| Paquetes de lenguaje | CVEs en npm/pip/gems | log4j, lodash prototype pollution |
| Configuración | Misconfiguraciones | Ejecutar como root, sin read-only filesystem |
| Secrets | API keys, tokens | Credenciales AWS en ENV |
| Licencias | Riesgo de compliance | GPL en software propietario |
Respuesta por severidad:
- Critical: Bloquear deploy; arreglar inmediatamente
- High: Bloquear deploy; arreglar dentro de 24 horas
- Medium: Advertencia; arreglar dentro del sprint
- Low: Trackear; arreglar oportunísticamente
Variantes
| Scanner | Velocidad | Profundidad | Ideal Para |
|---|---|---|---|
| Trivy | Rápido | OS + lenguaje | Integración CI; setup simple |
| Snyk | Medio | OS + lenguaje + SCA | Enterprise; compliance de licencias |
| Clair | Medio | Paquetes OS | Integración Harbor registry |
| Grype | Rápido | OS + lenguaje | Integración Syft SBOM |
| Twistlock | Medio | Full stack | Enterprise runtime protection |
Lo que funciona
- Scannea en cada build: Las vulnerabilidades se descubren diariamente; la imagen limpia de ayer es el riesgo de hoy
- Usa bases distroless o mínimas:
distroless,alpineoscratchreducen superficie de ataque - Pinea digests de imagen base:
FROM node:20-alpine@sha256:abc...previene tampering de tags - Multi-stage builds: No envíes build tools (gcc, git) en imágenes de producción. Consulta infraestructura inmutable.
- Firma imágenes con Cosign: Verifica integridad de imagen y provenance antes del deploy
Errores Comunes
- Scanneando solo la imagen base: Las dependencias de aplicación a menudo tienen más CVEs que el OS
- Usando tag
:latest: Builds no reproducibles hacen la atribución de vulnerabilidades imposible - Sin threshold de severidad: Scannear pero ignorar todos los resultados crea falsa confianza
- Secrets en ENV:
ENV AWS_SECRET_ACCESS_KEY=...es visible para cualquiera que haga pull de la imagen. Sigue secrets management. - Olvidando escaneo en runtime: La imagen está limpia en build time; las vulnerabilidades en runtime (volúmenes montados, sidecars) necesitan monitoreo
Soluciones Avanzadas
Dockerfile hardened multi-stage
# Stage 1: Build
FROM node:20-alpine AS builder
WORKDIR /app
# Instalar dependencias con audit
COPY package*.json ./
RUN npm ci --audit --omit=dev
# Stage 2: Producción
FROM gcr.io/distroless/nodejs20-debian12 AS production
# Copiar solo artifacts construidos
COPY --from=builder --chown=65532:65532 /app/node_modules /app/node_modules
COPY --from=builder --chown=65532:65532 /app/package.json /app/package.json
COPY --chown=65532:65532 . /app
# Seguridad: usuario non-root, read-only filesystem, no new privileges
USER 65532:65532
WORKDIR /app
# Dropear todas las capabilities de Linux
# Setear via docker run: --cap-drop ALL --security-opt no-new-privileges
# Setear via Kubernetes: securityContext.runAsNonRoot, readOnlyRootFilesystem
EXPOSE 3000
CMD ["server.js"]
Generación de SBOM con Syft
Genera un Software Bill of Materials (SBOM) para trazabilidad y compliance:
# Generar SBOM en formato SPDX
syft myapp:latest -o spdx-json > sbom.spdx.json
# Generar SBOM en formato CycloneDX
syft myapp:latest -o cyclonedx-json > sbom.cyclonedx.json
# Escanear SBOM para vulnerabilidades con Grype
grype sbom:sbom.cyclonedx.json --fail-on high
# Adjuntar SBOM a imagen como artifact OCI
cosign attach sbom --sbom sbom.spdx.json myapp:latest
Firma y verificación de imágenes con Cosign
# Generar par de keys para firma
cosign generate-key-pair
# Firmar la imagen
export COSIGN_PASSWORD="tu-password"
cosign sign --key cosign.key myapp:latest
# Verificar la firma antes del deploy
cosign verify --key cosign.pub myapp:latest
# Firmar con OIDC (keyless signing en CI)
cosign sign --identity-token $OIDC_TOKEN myapp:latest
# Verificar con identidad de certificado
cosign verify \
--certificate-identity "https://github.com/myorg/myrepo/.github/workflows/deploy.yml@refs/heads/main" \
--certificate-oidc-issuer "https://token.actions.githubusercontent.com" \
myapp:latest
Kubernetes security context
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
spec:
template:
spec:
securityContext:
runAsNonRoot: true
runAsUser: 65532
runAsGroup: 65532
fsGroup: 65532
seccompProfile:
type: RuntimeDefault
containers:
- name: myapp
image: myapp:latest@sha256:abc123...
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop:
- ALL
resources:
limits:
memory: "256Mi"
cpu: "500m"
requests:
memory: "128Mi"
cpu: "100m"
volumeMounts:
- name: tmp
mountPath: /tmp
volumes:
- name: tmp
emptyDir: {}
Cache y políticas de ignore de Trivy
# .trivyignore — falsos positivos conocidos o riesgos aceptados
CVE-2023-1234 # Falso positivo: nuestro código no usa la función vulnerable
CVE-2023-5678 # Riesgo aceptado: mitigado por network policy
# trivy.yaml — configuración de Trivy
scan:
severity: [CRITICAL, HIGH]
ignore-unfixed: true
ignore-policy: .trivyignore
skip-dirs:
- /tests
- /docs
# GitHub Actions con caching
name: Container Scan
on: [push]
jobs:
scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Cache Trivy DB
uses: actions/cache@v4
with:
path: ~/.cache/trivy
key: trivy-db-${{ github.run_id }}
restore-keys: trivy-db-
- name: Build and scan
uses: aquasecurity/trivy-action@master
with:
image-ref: 'myapp:latest'
format: 'sarif'
output: 'trivy-results.sarif'
severity: 'CRITICAL,HIGH'
ignore-unfixed: true
exit-code: '1'
- name: Upload SARIF to GitHub Security
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: trivy-results.sarif Preguntas frecuentes
¿Esta solución está lista para producción?
Sí. Los ejemplos de código arriba muestran implementaciones probadas. Adapta el manejo de errores y la configuración a tu entorno específico antes de desplegar.
¿Cuáles son las características de rendimiento?
El rendimiento depende de tu volumen de datos e infraestructura. Las soluciones mostradas priorizan claridad. Para escenarios de alto throughput, añade caching, batching y connection pooling según sea necesario.
¿Cómo depuro problemas con este enfoque?
Empieza con el ejemplo mínimo de arriba. Añade logging en cada paso. Prueba con entradas pequeñas primero, luego escala. Usa el debugger de tu lenguaje para revisar los edge cases.
Recursos Relacionados
Escaneo de Seguridad de Imagenes de Contenedores con Trivy
Escanea imagenes Docker para vulnerabilidades, configuraciones incorrectas y secretos usando Trivy, integra el escaneo en pipelines de CI/CD y aplica politicas de imagen antes del deployment a produccion
DocPlantilla de Politica de Retencion de Datos
Una plantilla para definir cuanto tiempo se conservan los datos, cuando se archivan y cuando deben eliminarse por cumplimiento y costos.
DocPlantilla de Auditoría de Dependencias de Terceros
Plantilla para auditar dependencias de terceros: cumplimiento de licencias, vulnerabilidades de seguridad, salud de mantenimiento y riesgo de supply chain.
DocPlantilla de Informe de Pruebas de Penetración
Plantilla de plan de pruebas de penetración con calificaciones de riesgo, pasos de reproducción y guías de remediación accionables.
DocPlantilla de Respuesta a Incidentes de Seguridad
Plantilla de respuesta a incidentes de seguridad: detección, clasificación, contención, erradicación, recuperación, comunicación y revisión post-incidente.
RecipeEscanea Imágenes Docker en busca de CVEs con Trivy y Grype
Escanea imágenes Docker en busca de vulnerabilidades antes del despliegue usando Trivy y Grype. Cubre integración CI, filtrado por severidad, SBOM y remediación.