¿Por qué y cómo se escanean las imágenes de contenedor en busca de vulnerabilidades antes de llegar a producción?
Toda imagen de contenedor es una pila congelada de dependencias ajenas, y cualquier capa puede cargar un CVE conocido y divulgado que nadie en tu equipo ha leído jamás.
APRENDE HACIENDOPon a prueba tu intuición3 pasos
¿Por qué y cómo se escanean las imágenes de contenedor en busca de vulnerabilidades antes de llegar a producción?
Usa los ejemplos y la explicación de la lección para comprobar tu idea.
Reflexión personal. No se envía a ningún servicio de IA.#Una imagen de contenedor es una pila congelada de decisiones ajenas
Cuando escribes FROM node:20-slim o FROM eclipse-temurin:21-jre, no solo estás eligiendo un runtime — estás heredando un sistema operativo base, los paquetes instalados por su gestor de paquetes, y la versión que estuviera vigente de cada librería transitiva el día que se construyó esa imagen base. Tu propio código de aplicación suele ser la capa más pequeña y más revisada de la imagen. Los paquetes del sistema operativo base, el runtime del lenguaje y tu árbol de dependencias son las capas que nadie de tu equipo escribió y que casi nadie lee línea por línea — y cualquiera de ellas puede estar cargando una entrada de Common Vulnerabilities and Exposures (CVE) publicada después de que se construyera la imagen.
El escaneo de imágenes existe para responder una sola pregunta antes de que una carga de trabajo llegue a un clúster: ¿este conjunto exacto de capas, en estas versiones fijadas exactas, contiene una vulnerabilidad conocida y divulgada?
#Cómo inspecciona realmente un escáner una imagen
Las imágenes de contenedor son sistemas de archivos por capas — cada instrucción RUN, COPY o ADD en un Dockerfile produce una capa, y la imagen final es esas capas apiladas junto con un manifiesto que describe el orden. Un escáner no ejecuta la imagen; la desempaqueta estáticamente y la recorre como un sistema de archivos, buscando bases de datos de paquetes conocidas:
- Gestores de paquetes a nivel de sistema operativo (dpkg para Debian/Ubuntu, rpm para RHEL, apk de Alpine, etc.), que revelan las versiones exactas de los paquetes del SO instalados.
- Manifiestos de dependencias a nivel de lenguaje incluidos en la imagen (por ejemplo, un
package-lock.json,requirements.txt,go.sum, o los JARs en el classpath de una imagen Java).
A partir de esto, el escáner construye (o lee, si generaste uno en tiempo de build) un Software Bill of Materials (SBOM) — un inventario estructurado y procesable por máquina de cada paquete y versión presente en la imagen, por capa. El SBOM se contrasta luego contra bases de datos de vulnerabilidades: la National Vulnerability Database (NVD), GitHub Security Advisories (GHSA) y avisos específicos de la distro (Debian Security Tracker, secdb de Alpine, feeds OVAL de Red Hat). Cada coincidencia recibe un identificador CVE y una puntuación de severidad CVSS (Crítica/Alta/Media/Baja), y el escáner reporta qué capa la introdujo.
#Herramientas comunes y en qué puntos se escanea
Escáneres populares incluyen Trivy, Grype, Clair, Docker Scout, y opciones comerciales como Snyk Container. Difieren sobre todo en la frescura de su base de datos, la velocidad y el soporte de formatos de SBOM (SPDX, CycloneDX) — el enfoque subyacente es el mismo. El escaneo debe ocurrir en tres puntos, no solo en uno:
- Local / pre-commit. Un desarrollador escanea antes de hacer push, detectando temprano una imagen base obviamente desactualizada, cuando es más barato corregirla.
- Filtro del pipeline de CI. Después de construir la imagen, el job de CI la escanea y aplica la política antes de que la imagen se suba al registro o se despliegue — este es el punto de control de mayor impacto porque es una parada obligatoria por la que pasa todo el mundo.
- Escaneo continuo del registro. Las imágenes que ya están en el registro, desplegadas hace semanas, se reescanean periódicamente, porque constantemente se divulgan nuevos CVEs contra software antiguo y sin cambios. Una imagen que estaba "limpia" el día que se construyó puede volverse vulnerable un mes después sin ningún cambio de código de tu parte.
#Hacer que el filtro de CI realmente bloquee el pipeline
Un escaneo que solo produce un reporte que nadie lee es teatro. La decisión de ingeniería real es la política: qué severidad hace fallar el build, y cuál es el proceso de excepción. Una política típica:
- Fallar el build ante cualquier hallazgo Crítico, sin excepciones sin una exención explícita y con fecha de vencimiento.
- Fallar ante hallazgos Altos a menos que aún no exista una corrección aprobada upstream, en cuyo caso el equipo registra una excepción documentada y con vencimiento (con un ticket y una fecha de reverificación) en lugar de silenciar el hallazgo para siempre.
- Permitir que Medio/Bajo pasen con visibilidad (dashboard, ticket) pero sin bloquear despliegues.
- Rastrear "días desde el último escaneo completamente limpio" como métrica — una lista de excepciones creciente es en sí misma una señal de que las imágenes base están desactualizadas.
Las exenciones necesitan fecha de vencimiento. Una entrada permanente en .trivyignore para un CVE es exactamente cómo las excepciones "temporales" se convierten en riesgo permanente y silencioso.
#Triaje: no todo CVE es explotable en tu contexto
Un escáner reporta una coincidencia de paquete-versión — no tiene idea de si tu aplicación alguna vez llama a la ruta de código vulnerable. Un CVE en una función de descompresión poco usada de una librería de compresión puede ser irrelevante si tu app nunca descomprime entradas no confiables. Por eso la salida del escaneo necesita un paso humano de triaje, y no un bloqueo ciego y automático ante cualquier Crítico: los equipos que tratan cada hallazgo como igual de urgente se agotan por fatiga de alertas y empiezan a aprobar exenciones por reflejo, lo cual anula todo el control.
🧠 Check your understanding
0/2 · 0/2 answered1. Un escáner de imágenes de contenedor funciona principalmente:
2. ¿Por qué es necesario reescanear continuamente imágenes ya desplegadas, aunque no haya cambios de código?