Seguridad del pipeline de CI/CD: tu código pasó todos los escaneos. ¿Y tu pipeline?
Muchos programas de seguridad de aplicaciones invierten mucho esfuerzo en el código: análisis estático en cada pull request, escaneo de dependencias, detección de secretos, revisión de infraestructura como código. Después, todo ese código pasa por un sistema de compilación que guarda claves de la nube, certificados de firma y permisos para desplegar en producción. Y ese sistema suele recibir mucha menos atención que el código que compila.
Es un problema, porque quien controla tu pipeline no necesita una vulnerabilidad en tu aplicación. El pipeline ya tiene el acceso que busca. Esta guía explica cómo se atacan los pipelines de CI/CD, qué revisar según el OWASP Top 10 CI/CD Security Risks y qué controles marcan más la diferencia.
Por qué el pipeline es un blanco tan bueno
Un sistema de CI/CD es, por diseño, una máquina que ejecuta código de muchos orígenes con credenciales muy potentes. En una compilación típica descarga tu código fuente, baja dependencias y plugins de terceros, ejecuta scripts que puede cambiar cualquiera con permisos de escritura y luego usa secretos para publicar paquetes, subir imágenes o desplegar en la nube.
Cada uno de esos pasos es un lugar donde corre código ajeno al lado de tus credenciales. Por eso los compromisos de pipeline suelen ser silenciosos y amplios: un solo paso envenenado puede llegar a todos los repositorios que lo usan.
Un caso real: una acción, unos 23 000 repositorios
En marzo de 2025 se comprometió la popular GitHub Action tj-actions/changed-files. Según BleepingComputer, la usaban unos 23 000 repositorios. Los atacantes usaron un token de acceso personal robado de una cuenta bot con acceso privilegiado, subieron un commit malicioso el 14 de marzo y cambiaron de forma retroactiva varias etiquetas de versión para que apuntaran a él. El código malicioso volcaba los secretos de la memoria del runner en los logs del workflow, y en los repositorios públicos cualquiera podía leer esos logs.
El incidente se registró como CVE-2025-30066. CISA publicó una alerta, lo agregó a su catálogo de vulnerabilidades explotadas conocidas (KEV) y mencionó entre los secretos en riesgo claves de acceso a la nube, tokens de acceso personal de GitHub, tokens de npm y claves RSA privadas.
La lección no es sobre una acción en particular. Los equipos que la referenciaban por una etiqueta de versión recibieron el código malicioso automáticamente, sin ningún cambio en sus propios repositorios. Los que la tenían fijada a un SHA de commit completo, no.
El OWASP Top 10 CI/CD Security Risks
El Top 10 CI/CD Security Risks de OWASP, publicado por primera vez en 2022, es el mapa más útil de dónde fallan los pipelines. Los diez riesgos son:
- CICD-SEC-1: controles de flujo insuficientes. El código puede llegar a producción sin una revisión o aprobación independiente.
- CICD-SEC-2: gestión de identidades y accesos inadecuada. Demasiadas cuentas, cuentas abandonadas y permisos amplios en el control de código y en la CI.
- CICD-SEC-3: abuso de la cadena de dependencias. Ataques a través de los paquetes que descarga tu compilación. Ya vimos una forma en paquetes maliciosos de código abierto.
- CICD-SEC-4: ejecución de pipeline envenenado (PPE). Lograr que el pipeline ejecute comandos del atacante.
- CICD-SEC-5: controles de acceso del pipeline insuficientes (PBAC). Los pasos del pipeline llegan a más secretos y sistemas de los que necesitan.
- CICD-SEC-6: higiene de credenciales insuficiente. Secretos demasiado potentes, de vida demasiado larga o compartidos en exceso.
- CICD-SEC-7: configuración insegura del sistema. Valores por defecto débiles y servidores de CI, runners y plugins sin parchear.
- CICD-SEC-8: uso no gobernado de servicios de terceros. Integraciones y apps conectadas al control de código con permisos que nadie revisa.
- CICD-SEC-9: validación de integridad de artefactos deficiente. Nada prueba que lo que despliegas es lo que compilaste a partir de código revisado.
- CICD-SEC-10: registro y visibilidad insuficientes. No hay logs suficientes para detectar o investigar un ataque al pipeline.
La ejecución de pipeline envenenado, en palabras simples
La PPE merece una mirada más detallada porque sorprende a muchos equipos. OWASP la describe como un atacante con acceso al control de código que manipula el proceso de compilación sin tener acceso al entorno de compilación. Los comandos maliciosos se ejecutan entonces con la identidad del pipeline y con sus secretos.
OWASP describe tres variantes:
- PPE directa: el atacante edita el propio archivo de configuración de la CI, por ejemplo en una rama sin protección o en un pull request.
- PPE indirecta: la configuración está protegida, así que el atacante cambia archivos que el pipeline invoca, como Makefiles, scripts, código de pruebas o la configuración del linter.
- PPE pública: un proyecto público ejecuta en su pipeline código sin revisar de colaboradores externos, así que un usuario anónimo puede dispararlo.
Los controles que más importan
No hace falta resolver los diez riesgos a la vez. Estos controles atacan los patrones de falla anteriores y están respaldados por la guía de endurecimiento de seguridad de GitHub Actions y por el proyecto de OWASP.
Fija las acciones y plugins de terceros
GitHub recomienda fijar las acciones a un SHA de commit completo y comprobar que ese SHA viene del repositorio de la acción, no de un fork. Una etiqueta se puede mover; un SHA de commit, no. Combínalo con una lista de acciones aprobadas y un proceso para actualizar esos SHA de forma deliberada.
Dale el mínimo privilegio a tokens y pasos
Configura los permisos por defecto del GITHUB_TOKEN como solo lectura y amplíalos por job solo donde haga falta. La guía de higiene de credenciales de OWASP agrega que cada pipeline y cada paso debe acceder solo a los secretos que necesita, y que no se deben reutilizar las mismas credenciales en distintos contextos.
Prefiere credenciales de corta duración
En lugar de guardar claves de la nube de larga duración como secretos del pipeline, usa OpenID Connect para que los workflows se autentiquen directamente con el proveedor de nube con tokens de corta vida. OWASP lo resume así: prefiere credenciales temporales a las estáticas, y rota las estáticas que no puedas eliminar.
Trata el código no confiable como no confiable
Evita los disparadores que corren con secretos sobre código de forks si no los necesitas; GitHub advierte en particular sobre pull_request_target. OWASP recomienda ejecutar en nodos aislados, lejos de los secretos, los pipelines que corren código sin revisar, y pedir aprobación para los que inician colaboradores externos. GitHub también dice que los runners autoalojados casi nunca deberían usarse en repositorios públicos.
Protege la definición del pipeline
Agrega el directorio de workflows a CODEOWNERS para que cualquier cambio en los archivos del pipeline requiera la aprobación de un revisor designado, y asegúrate de que toda rama que pueda disparar un pipeline con secretos tenga protección de rama. Así cubres la PPE directa y la indirecta.
Mantén los secretos fuera de los logs y de los artefactos
Enmascara los secretos en la salida de consola y revisa los logs existentes. OWASP también recomienda verificar que no queden secretos en artefactos como capas de imágenes de contenedor, binarios o charts de Helm. Si un secreto se filtra, sigue el orden de nuestra guía de respuesta a secretos filtrados: primero revoca, después limpia.
Registra el pipeline como si fuera producción
Guarda los logs de auditoría del control de código, de los servidores de CI y de las cuentas de nube, y asegúrate de poder responder preguntas básicas después de un incidente: qué workflow corrió, con qué versión de cada acción y qué secretos podía leer.
Por dónde empezar esta semana
- Haz la lista de acciones y plugins de terceros que usan tus pipelines y fíjalos a SHA de commit.
- Configura como solo lectura los permisos por defecto de los tokens.
- Ubica los pipelines que guardan claves de la nube de larga duración y planifica su paso a OIDC.
- Revisa qué workflows corren sobre código de forks y a qué secretos llegan.
- Pon los archivos de workflow bajo CODEOWNERS.
Preguntas frecuentes
¿Es solo un problema de GitHub? No. La lista de OWASP es neutral respecto al fabricante y aplica a GitLab CI, Jenkins, Azure DevOps y otros. Aquí usamos GitHub Actions porque su guía es pública y concreta.
¿Los escáneres de código cubren el pipeline? En parte. El escaneo de secretos y el SCA detectan algunos problemas, como una clave filtrada o una dependencia maliciosa, pero los permisos, la configuración de los runners y las integraciones de terceros necesitan su propia revisión. En SAST, SCA, secretos e IaC explicamos qué cubre cada escáner.
¿Fijar a un SHA significa no recibir actualizaciones nunca? No. Significa que las actualizaciones llegan cuando tú decides revisar y cambiar el SHA, no cuando alguien mueve una etiqueta.
Cómo ayuda priorIQ.ai
CodeIQ escanea tus repositorios y pipelines: SAST, SCA con detección de paquetes maliciosos, escaneo de contenedores y de infraestructura como código, y secretos en todo el historial de git con validación de secretos activos, además de una compuerta en el pipeline que frena los problemas nuevos antes de que se integren. Sus hallazgos entran en PriorIQ Core con el mismo modelo de riesgo que los endpoints y la nube, así que un secreto activo en un log de compilación o una dependencia riesgosa compite por atención según su riesgo real, en una sola cola priorizada. Solicita una demo.