En 2019, Capital One sufrió una brecha que expuso datos de más de 100 millones de clientes en Estados Unidos y Canadá. El vector de ataque inicial fue una misconfiguration en un rol IAM de AWS — permisos excesivos en un recurso de infraestructura que había sido definido en código, revisado, aprobado y desplegado a producción. La infraestructura estaba correctamente versionada en un repositorio de control de cambios. El fallo de seguridad también.
Lo que hace ese caso especialmente instructivo no es que ocurriera, sino que era completamente evitable. La misconfiguration habría aparecido en cualquier escáner de IaC con una regla básica de permisos IAM. Nadie estaba ejecutando uno.
Por qué IaC amplifica el problema de las misconfigs
El movimiento hacia infraestructura como código surgió como solución a un problema real: los entornos definidos a mano son inconsistentes, difíciles de auditar y lentos de replicar. IaC resolvió todo eso. Pero al trasladar la infraestructura a código, también trasladó todos los patrones de error que ya conocíamos del desarrollo de software — solo que con consecuencias más graves.
Un bug en código de aplicación afecta a esa aplicación. Una misconfiguration en IaC afecta potencialmente a toda la infraestructura — y, a diferencia de un bug de software, no requiere que nadie la explote activamente para que cause daño. Una base de datos sin cifrado en reposo está siempre en ese estado. Un bucket S3 público está siempre expuesto. El ataque es opcional; la exposición no.
La otra diferencia es la persistencia. Un CVE en una dependencia se puede parchear en el siguiente ciclo de actualización. Una misconfiguration de infraestructura existe mientras ese recurso existe, a veces durante años. Las organizaciones acumulan recursos de infraestructura — se añaden, rara vez se eliminan — y las misconfigs viajan con ellos.
Qué es el escaneo de IaC
Infrastructure as Code security scanning analiza los ficheros de definición de infraestructura en busca de configuraciones que introduzcan riesgo de seguridad — antes de que se apliquen. El análisis ocurre sobre el código fuente, no sobre la infraestructura desplegada, lo que significa que los problemas se detectan en la fase de pull request, no semanas después de que el recurso lleve activo en producción.
Los formatos que cubre el análisis incluyen Terraform (el lenguaje HCL y los ficheros .tf), Kubernetes y Helm (manifiestos YAML para orchestración de contenedores), Dockerfile (definición de imágenes), CloudFormation y ARM Templates (los formatos nativos de AWS y Azure), y Ansible (playbooks de automatización de configuración). En la práctica, la mayoría de los equipos modernos tienen al menos tres o cuatro de estos formatos coexistiendo en el mismo repositorio.
El escáner de Gerion usa KICS (Keeping Infrastructure as Code Secure), el proyecto open source mantenido originalmente por Checkmarx y ahora con contribuciones de la comunidad. KICS cuenta con más de 2.000 queries de detección que cubren los principales proveedores de nube y las categorías de riesgo más relevantes: control de acceso, cifrado, exposición de red, configuración de contenedores y exposición de secretos.
Las categorías de riesgo más frecuentes
Exposición de red no intencionada
El patrón más común — y el que aparece con más frecuencia en brechas reales — es el Security Group o firewall configurado con reglas demasiado permisivas. La versión obvia es fácil de detectar en revisión:
resource "aws_security_group_rule" "ingress_all" { type = "ingress" from_port = 0 to_port = 65535 protocol = "-1" cidr_blocks = ["0.0.0.0/0"]}Cualquier puerto, cualquier protocolo, cualquier IP del planeta. Pero la versión que pasa desapercibida es más peligrosa porque parece razonable: un grupo de seguridad que abre solo el puerto 22 (SSH) a 0.0.0.0/0 justificado como “temporal para el debugging del entorno de staging”. Esa regla temporal lleva dos años en producción y nadie recuerda haberla creado.
KICS detecta ambas variantes, además de otras menos obvias: puertos de administración de bases de datos (3306, 5432, 27017) accesibles desde internet, subredes completas expuestas por error en vez de IPs individuales, y reglas de egress sin restricciones que permiten exfiltración de datos sin impedimento de red.
Almacenamiento con acceso público
Los buckets S3 mal configurados han sido el origen de tantas brechas de datos que AWS introdujo controles a nivel de cuenta para bloquearlos por defecto. Aun así, los errores persisten — especialmente cuando la configuración de acceso público se define explícitamente en Terraform para un caso de uso legítimo (un bucket de assets web estáticos, por ejemplo) y esa misma configuración se copia después a un bucket que contiene backups de base de datos.
resource "aws_s3_bucket_acl" "data_bucket" { bucket = aws_s3_bucket.data.id acl = "public-read"}KICS detecta buckets con ACLs públicas, buckets sin políticas de cifrado en reposo (SSE), buckets sin versioning activado (relevante para estrategias de backup) y configuraciones de bucket policy que otorgan permisos excesivos a roles IAM. La clave es que lo detecta en el fichero .tf, en el momento del pull request, antes de que el terraform apply ejecute el cambio en producción.
Credenciales hardcodeadas en manifiestos de Kubernetes
Kubernetes tiene un objeto Secret específicamente diseñado para gestionar credenciales de forma segura — separadas del código de la aplicación, montables como variables de entorno o volúmenes, y con control de acceso propio (RBAC). A pesar de eso, es frecuente encontrar credenciales directamente en los manifiestos de Deployment:
containers: - name: app image: myapp:latest env: - name: DATABASE_URL value: "postgres://admin:production_password@db.internal:5432/appdb" - name: STRIPE_SECRET_KEY value: "sk_live_abc123xyz"El problema no es solo que esas credenciales estén en el YAML que se aplica al cluster. Es que ese YAML está en un repositorio de git, posiblemente con docenas de colaboradores, visible en el historial completo incluso si se elimina en un commit posterior. KICS detecta patrones de credenciales hardcodeadas en manifiestos de Kubernetes antes de que lleguen al repositorio — y Gitleaks las detecta en el historial si ya llegaron.
Contenedores con permisos excesivos
La filosofía de seguridad de contenedores se basa en reducir la superficie de ataque: un proceso debería tener exactamente los permisos que necesita, nada más. En la práctica, los contenedores acaban corriendo con permisos muy por encima de lo necesario porque es la opción que funciona sin debuggear.
securityContext: privileged: true runAsUser: 0 allowPrivilegeEscalation: true capabilities: add: ["SYS_ADMIN", "NET_ADMIN"]Un contenedor con privileged: true tiene acceso casi completo al nodo de Kubernetes en el que corre — puede montar sistemas de ficheros del host, acceder a dispositivos de hardware, y en muchos casos escapar del namespace de contenedor completamente. Si existe una vulnerabilidad de container escape (y existen, con regularidad), la diferencia entre un contenedor privilegiado y uno con el mínimo de permisos es la diferencia entre un incidente contenido y una brecha de toda la infraestructura del nodo.
KICS detecta privileged: true, contenedores corriendo como root (runAsUser: 0 o ausencia de runAsNonRoot: true), capabilities excesivas, y la ausencia de configuraciones de seguridad básicas como readOnlyRootFilesystem o seccompProfile.
Cifrado desactivado o inexistente
Los proveedores de nube ofrecen cifrado en reposo y en tránsito en prácticamente todos sus servicios de almacenamiento y bases de datos. La mayoría están desactivados por defecto o requieren configuración explícita. Es sencillo terminar con una infraestructura de producción donde RDS tiene backups sin cifrar, EBS volumes sin cifrado, o traffic entre servicios internos sin TLS — no porque alguien tomara una decisión consciente de no cifrar, sino porque nadie activó la opción.
resource "aws_db_instance" "production" { identifier = "prod-db" instance_class = "db.t3.medium" storage_encrypted = false # desactivado explícitamente — o simplemente ausente # ...}KICS detecta recursos de almacenamiento y bases de datos sin cifrado configurado, conexiones sin TLS/SSL obligatorio, y certificados autofirmados en contextos de producción.
Por qué las misconfigs de IaC son más difíciles de revisar que el código
La revisión de seguridad en código de aplicación es difícil pero tiene metodología: un revisor experimentado busca patrones conocidos en lógica de negocio que controla. La revisión de seguridad en IaC tiene un problema diferente: un fichero Terraform de 600 líneas que define 40 recursos de AWS contiene cientos de atributos, cada uno con implicaciones de seguridad que dependen de los valores de otros atributos en otros recursos del mismo fichero o de ficheros relacionados.
Un revisor humano que no tiene el mapa completo de qué servicios hay en producción, qué datos manejan, y qué combinación de atributos crea exposición en cada servicio específico de AWS no puede hacer esa revisión de forma fiable. No es falta de capacidad — es que el espacio de configuraciones posibles es demasiado grande para revisión manual exhaustiva.
KICS resuelve esto con análisis estático: recorre todos los atributos de todos los recursos, evalúa combinaciones de valores contra más de 2.000 queries de detección, y produce una lista de hallazgos en segundos. No reemplaza la revisión de arquitectura — pero elimina la clase entera de errores que se detectan con reglas determinísticas.
Separar repositorios de infraestructura no resuelve el problema
Un patrón común en equipos maduros es separar el código de infraestructura del código de aplicación — un repositorio infra/ gestionado por el equipo de plataforma, separado de los repositorios de las aplicaciones. Tiene sentido organizativamente. Pero crea un problema de cobertura de seguridad: si los repositorios de aplicaciones están integrados con el pipeline de escaneo de Gerion pero el repositorio de infraestructura no, la cobertura es incompleta.
La CLI de Gerion se ejecuta como cualquier otro paso de CI/CD — en el mismo runner que el resto del pipeline, con acceso solo al código del repositorio actual. Añadirla al pipeline del repositorio de infraestructura es el mismo proceso que añadirla a cualquier otro:
- name: Gerion Security Scan run: | docker run --rm -v "$PWD:/code" \ -e GERION_API_URL=${{ secrets.GERION_API_URL }} \ -e GERION_API_KEY=${{ secrets.GERION_API_KEY }} \ ghcr.io/gerion-appsec/gerion-cli:latest scan-all /codeLos hallazgos de KICS del repositorio de infraestructura llegan a la misma plataforma que los hallazgos de SAST, SCA y Secrets de los repositorios de aplicaciones — normalizados, con el mismo modelo de priorización por rama y el mismo cálculo de impacto financiero. Una misconfiguration de Security Group en la rama main del repositorio de infraestructura tiene multiplicador 10×. La misma misconfiguration en una rama de feature, multiplicador 1×. El Financial Impact Engine no distingue entre tipo de repositorio — distingue entre lo que está en producción y lo que todavía no.
El resultado práctico es que el equipo de plataforma ve sus hallazgos de IaC en el mismo dashboard que el equipo de aplicaciones ve los suyos. No hay una herramienta separada para infraestructura, no hay un proceso de triage diferente, no hay un spreadsheet de tracking manual para misconfigs de Terraform. Un único backlog de seguridad, priorizado por coste real, con los hallazgos de todos los repositorios y todos los escáneres en un mismo sitio.