GitLab CI/CD se ha convertido en la columna vertebral del DevSecOps moderno, ofreciendo una plataforma integrada donde el código, los pipelines, el escaneo de seguridad y los despliegues convergen en una única interfaz. Pero esa profunda integración es un arma de doble filo: un pipeline mal configurado puede exponer secretos, permitir despliegues no autorizados o dar a los atacantes un punto de apoyo en tu infraestructura.
Esta guía definitiva cubre cada superficie relevante para la seguridad de GitLab CI/CD — desde variables protegidas y scoping de runners hasta federación OIDC y seguridad en pipelines de merge requests. Ya sea que estés fortaleciendo una instalación existente de GitLab o construyendo una práctica de DevSecOps desde cero, este artículo te proporciona el conocimiento y las listas de verificación accionables que necesitas.
Por qué importa la seguridad de GitLab CI/CD
GitLab se posiciona como la «Plataforma DevOps Única,» y con razón. El control de código fuente, la gestión de incidencias, CI/CD, el registro de contenedores, el registro de paquetes, el escaneo de seguridad y la gestión de despliegues conviven bajo un mismo techo. Esa consolidación simplifica las herramientas — pero también concentra el riesgo. Un único job de pipeline comprometido puede potencialmente leer código fuente, robar credenciales, subir imágenes maliciosas y activar despliegues en producción.
Los recientes ataques a la cadena de suministro han demostrado que los pipelines de CI/CD son objetivos de alto valor. Los atacantes que obtienen la capacidad de inyectar pasos en un pipeline — ya sea a través de una dependencia envenenada, un shared runner comprometido o un merge request malicioso — pueden exfiltrar secretos, manipular artefactos de compilación o moverse lateralmente hacia entornos cloud. GitLab proporciona un rico conjunto de controles para prevenir estos resultados, pero solo si los entiendes y los habilitas.
Comprendiendo el modelo de seguridad de GitLab CI
Antes de profundizar en los controles individuales, es útil comprender los cuatro pilares del modelo de seguridad de GitLab CI:
- Runners — la capa de cómputo que ejecuta los jobs. La seguridad depende del aislamiento, el nivel de confianza y el scoping.
- Variables — la configuración y los secretos inyectados en los jobs. La protección y el enmascaramiento determinan quién y qué puede acceder a ellos.
- Environments — objetivos lógicos de despliegue (staging, producción). Las reglas de protección y las puertas de aprobación controlan quién puede desplegar y dónde.
- Tokens — credenciales de corta duración (
CI_JOB_TOKEN, OIDCid_tokens) que autentican los jobs ante otros servicios. El scoping limita su radio de impacto.
Cada medida de fortalecimiento en esta guía se relaciona con uno o más de estos pilares. Domina los cuatro y tendrás una postura de defensa en profundidad capaz de resistir tanto errores internos como ataques externos.
Variables protegidas y enmascaradas
Las variables de CI/CD son el mecanismo principal para inyectar secretos — claves API, credenciales cloud, contraseñas de bases de datos — en los jobs del pipeline. GitLab ofrece dos salvaguardas ortogonales: protección y enmascaramiento.
Variables protegidas
Cuando una variable se marca como protegida, GitLab solo la expone a los jobs que se ejecutan en ramas protegidas o tags protegidos. Este es un control crítico: significa que un desarrollador que abra un merge request desde una rama de funcionalidad no puede escribir un paso de pipeline que muestre tus credenciales de AWS de producción. La variable simplemente no existe en el entorno del job para refs no protegidos.
Mejores prácticas para variables protegidas:
- Marca cada secreto de producción como protegido. No hay razón válida para que un job de una rama de funcionalidad acceda a credenciales de producción.
- Limita quién puede hacer push o merge en ramas protegidas (rol Maintainer o superior). Esto crea una puerta humana antes de que los secretos sean accesibles.
- Usa variables con alcance de entorno cuando el mismo nombre de secreto difiere entre staging y producción. GitLab inyectará el valor correcto basándose en la palabra clave
environment:en la definición del job. - Rota las variables protegidas regularmente. Incluso las variables protegidas pueden filtrarse a través de logging mal configurado o runners comprometidos.
Variables enmascaradas
El enmascaramiento evita que el valor de una variable aparezca en los logs de los jobs. GitLab reemplaza cualquier aparición del valor con [MASKED]. El enmascaramiento es una red de seguridad, no una frontera de seguridad — protege contra exposición accidental (por ejemplo, un comando curl verboso que registra cabeceras) pero no impide que un paso malicioso del job codifique el valor en Base64 o lo escriba en un artefacto.
Combina protección y enmascaramiento. Una variable que está protegida y enmascarada te da la defensa incorporada más fuerte: alcance limitado por rama más redacción a nivel de logs.
Tipos de runners y scoping
Los runners son donde tu código realmente se ejecuta. Comprender los tipos de runners y sus implicaciones de seguridad es esencial para un entorno de GitLab CI fortalecido.
Shared, Group y Project Runners
GitLab soporta tres alcances para runners:
- Shared runners — disponibles para todos los proyectos en la instancia. Convenientes pero de mayor riesgo: un proyecto malicioso puede potencialmente dejar artefactos, cachés o procesos que afecten al siguiente job de un proyecto no relacionado.
- Group runners — disponibles para todos los proyectos dentro de un grupo específico. Un punto medio razonable que limita la exposición entre proyectos mientras reduce la sobrecarga de gestión de runners.
- Project runners — dedicados a un único proyecto. Máximo aislamiento, pero mayor costo operativo. Recomendado para repositorios de alta seguridad que manejan secretos de producción o datos sensibles de clientes.
Protected Runners
Cualquier runner puede marcarse como protegido. Un runner protegido solo acepta jobs de ramas protegidas o tags protegidos. Esto se combina naturalmente con las variables protegidas: tu runner de despliegue a producción solo ejecuta en main, y solo los jobs en main tienen acceso a los secretos de producción.
Lista de verificación para el fortalecimiento de runners:
- Usa runners efímeros (auto-escalados, destruidos después de cada job) para eliminar la persistencia de datos entre jobs.
- Ejecuta Docker-in-Docker con
--privilegedsolo cuando sea absolutamente necesario, y aísla esos runners en un grupo de seguridad dedicado. - Deshabilita el executor shell en los shared runners. Usa executors de Docker o Kubernetes con contextos de seguridad restrictivos.
- Etiqueta los runners de despliegue a producción y bloquéalos a proyectos específicos y ramas protegidas.
- Audita los tokens de registro de runners — rótalos regularmente y revoca cualquier token filtrado inmediatamente.
Entornos protegidos y aprobaciones de despliegue
Los environments de GitLab representan objetivos de despliegue como staging, production o canary. Proteger un entorno añade una capa de autorización que va más allá de la protección de ramas.
Cómo funcionan los entornos protegidos
Cuando proteges un entorno, especificas qué usuarios o grupos tienen permiso para desplegar en él. Incluso si un pipeline se ejecuta en una rama protegida, el job de despliegue no se ejecutará a menos que el usuario que lo activó tenga el permiso requerido. Esto crea una separación de responsabilidades: los desarrolladores pueden hacer merge del código, pero solo los desplegadores designados pueden llevarlo a producción.
Aprobaciones de despliegue (Premium/Ultimate)
Las ediciones Premium y Ultimate de GitLab ofrecen aprobaciones de despliegue — un mecanismo que pausa un job de despliegue y espera a que uno o más aprobadores designados den luz verde. Esto es invaluable para entornos regulados donde los procesos de gestión de cambios requieren aprobación humana antes de que los cambios en producción entren en vigor.
Consejos de configuración:
- Requiere al menos dos aprobadores para despliegues en producción para prevenir compromisos de una sola persona.
- Establece reglas de aprobación a nivel de grupo para que se apliquen consistentemente en todos los proyectos dentro de una unidad de negocio.
- Combina las aprobaciones de despliegue con runners protegidos y variables protegidas para una defensa en capas.
- Usa la palabra clave
environment: deployment_tierpara clasificar entornos (production, staging, testing, development) y aplicar políticas apropiadas a cada nivel.
Scoping de CI_JOB_TOKEN
Cada job de GitLab CI recibe un CI_JOB_TOKEN generado automáticamente — una credencial de corta duración que autentica el job ante la API de GitLab, el registro de contenedores y el registro de paquetes. Por defecto, este token puede acceder a recursos entre proyectos, lo que crea un riesgo de movimiento lateral.
Limitando el acceso de CI_JOB_TOKEN
GitLab 15.9+ introdujo controles de alcance del job token de CI/CD. Ahora puedes configurar una lista de permitidos de proyectos a los que el CI_JOB_TOKEN de un proyecto dado puede acceder. Esta es una configuración obligatoria para cualquier organización consciente de la seguridad.
Pasos para fortalecer CI_JOB_TOKEN:
- Navega a Settings > CI/CD > Token Access en tu proyecto.
- Habilita Limit CI_JOB_TOKEN access (esto restringe el token al proyecto actual por defecto).
- Agrega solo los proyectos específicos a los que los jobs de este proyecto legítimamente necesitan acceder.
- Revisa la lista de permitidos trimestralmente y elimina las entradas obsoletas.
Con tokens con alcance limitado, incluso si un atacante compromete un job del pipeline, el radio de impacto se limita a los proyectos explícitamente permitidos en lugar de toda la instancia de GitLab.
Federación OIDC con id_tokens
Las credenciales cloud codificadas directamente en variables de CI son un riesgo de seguridad persistente. El soporte de OIDC (OpenID Connect) de GitLab elimina este riesgo por completo al permitir que los jobs del pipeline se autentiquen ante proveedores cloud usando tokens de corta duración, firmados criptográficamente.
Cómo funciona
Cuando defines un bloque id_tokens en tu .gitlab-ci.yml, GitLab genera un JWT firmado para cada job. El JWT contiene claims sobre el job — ruta del proyecto, nombre del ref, entorno, fuente del pipeline — que el proveedor cloud puede evaluar contra su política de confianza.
deploy_production:
id_tokens:
GITLAB_OIDC_TOKEN:
aud: https://aws.example.com
script:
- |
export AWS_WEB_IDENTITY_TOKEN_FILE=$(mktemp)
echo "$GITLAB_OIDC_TOKEN" > $AWS_WEB_IDENTITY_TOKEN_FILE
aws sts assume-role-with-web-identity \
--role-arn arn:aws:iam::123456789012:role/gitlab-deploy \
--web-identity-token file://$AWS_WEB_IDENTITY_TOKEN_FILE
En el lado del proveedor cloud (AWS, GCP, Azure), configuras una política de confianza que solo acepta tokens de proyectos, ramas y entornos específicos. Esto significa:
- Sin credenciales estáticas que rotar o que puedan filtrarse.
- Acceso granular — un token de una rama de funcionalidad puede ser rechazado por el proveedor cloud, incluso si el pipeline es válido por lo demás.
- Auditabilidad — cada evento de autenticación se registra con los claims completos del JWT.
Para una inmersión profunda en los patrones de federación OIDC en AWS, GCP y Azure, consulta nuestra guía dedicada: Credenciales de corta duración y federación de identidad de carga de trabajo para CI/CD.
Seguridad de pipelines de Merge Request
Los merge requests son el vector más común para inyectar código malicioso en los pipelines. Un contribuidor externo (o una cuenta comprometida) puede enviar un merge request que modifique .gitlab-ci.yml para exfiltrar secretos o establecer persistencia.
Protecciones clave
- Usa
rules: - if: $CI_PIPELINE_SOURCE == 'merge_request_event'para crear pipelines de MR dedicados que se ejecuten con privilegios reducidos. Los pipelines de MR desde forks no tienen acceso a variables protegidas por defecto. - Requiere éxito del pipeline antes del merge. Esto asegura que los escaneos de seguridad (SAST, escaneo de dependencias, detección de secretos) se ejecuten en cada MR.
- Limita
include:a fuentes confiables. Los MR maliciosos pueden agregar directivasinclude: remote:que traen YAML controlado por el atacante. Usa una lista de permitidos de dominios de inclusión o fija a refs específicos. - Habilita «Pipelines must succeed» y «All threads must be resolved» en la configuración de merge requests de tu proyecto.
- Revisa cuidadosamente los cambios en
.gitlab-ci.yml. Cualquier MR que modifique la configuración del pipeline debería requerir aprobación de un revisor consciente de la seguridad.
Restricciones de pipelines de forks
Para proyectos públicos o de código abierto, los pipelines de forks presentan riesgos adicionales. GitLab te permite:
- Ejecutar pipelines de forks en modo restringido sin acceso a las variables de CI del proyecto.
- Requerir aprobación manual antes de ejecutar pipelines desde forks (disponible en Premium/Ultimate).
- Usar runners separados y sin privilegios para los pipelines de forks.
Detección de secretos con plantillas SAST integradas
GitLab incluye plantillas SAST (Static Application Security Testing) integradas que incluyen detección de secretos. Habilitarlas es sencillo:
include:
- template: Jobs/Secret-Detection.gitlab-ci.yml
- template: Jobs/SAST.gitlab-ci.yml
El escáner de detección de secretos utiliza coincidencia de patrones y análisis de entropía para identificar credenciales filtradas, claves API, claves privadas y tokens en tu código fuente. Los resultados aparecen en el widget de seguridad del merge request, facilitando que los revisores detecten filtraciones antes de que lleguen a la rama por defecto.
Maximizando la efectividad de la detección de secretos:
- Habilita la detección de secretos a nivel de pipeline (no solo el escaneo histórico) para que cada commit sea verificado.
- Configura push rules para rechazar commits que contengan patrones de secretos conocidos (por ejemplo,
AKIApara claves de acceso de AWS). - Integra con la gestión de vulnerabilidades de GitLab para rastrear, clasificar y resolver los secretos detectados.
- Agrega patrones personalizados para formatos de secretos específicos de la organización (claves API internas, tokens de cuentas de servicio).
- Ejecuta la detección de secretos tanto en la rama de origen como en el resultado del merge para detectar secretos introducidos por conflictos de merge.
Flujos de trabajo de despliegue seguro
Llevar código desde un pipeline a un entorno de producción de forma segura requiere más que simplemente ejecutar kubectl apply. GitLab soporta varias estrategias de despliegue que equilibran velocidad con seguridad.
Puertas manuales
Usa la palabra clave when: manual para crear puntos de aprobación explícitos en tu pipeline. Un patrón común es desplegar automáticamente en staging pero requerir un clic manual para producción. Combinado con entornos protegidos y aprobaciones de despliegue, esto crea un flujo de trabajo robusto de gestión de cambios.
deploy_production:
stage: deploy
environment:
name: production
deployment_tier: production
when: manual
only:
- main
Despliegues canary
GitLab se integra con Kubernetes para soportar despliegues canary de forma nativa. Al desplegar primero a un pequeño porcentaje de pods y monitorear las tasas de error, puedes detectar problemas antes de que afecten a todos los usuarios. Este es un control de seguridad además de uno de fiabilidad — una compilación comprometida que llega al canary puede ser detectada y revertida antes de que se propague.
GitOps con el GitLab Agent for Kubernetes
El GitLab Agent for Kubernetes (anteriormente conocido como KAS) habilita un modelo GitOps basado en pull. En lugar de otorgar a tu pipeline de CI acceso directo a la API de Kubernetes, el agente que se ejecuta dentro del clúster obtiene el estado deseado de un repositorio Git. Esto elimina la necesidad de credenciales kubeconfig de larga duración en las variables de CI y reduce significativamente la superficie de ataque.
Mejores prácticas de seguridad en despliegues:
- Nunca almacenes kubeconfig o credenciales cloud como variables de CI no protegidas. Usa federación OIDC o el GitLab Agent.
- Implementa automatización de rollback — si las verificaciones de salud fallan después del despliegue, revierte automáticamente al estado anterior conocido como bueno.
- Firma las imágenes de contenedores y verifica las firmas antes del despliegue usando Cosign o Notary.
- Usa tags inmutables o referencias basadas en digest para imágenes de contenedores para prevenir ataques basados en tags.
Errores de configuración comunes
Incluso los equipos que entienden los conceptos de seguridad de GitLab CI suelen caer en estas trampas:
1. Variables no protegidas que contienen secretos de producción
Este es el error de configuración más común y más peligroso. Si una contraseña de base de datos de producción se almacena como una variable no protegida, cualquier desarrollador puede crear una rama, agregar un paso echo $DB_PASSWORD y leerla desde el log del job. Siempre protege y enmascara los secretos de producción.
2. Shared runners excesivamente permisivos
Los shared runners con montaje del socket de Docker (/var/run/docker.sock) o modo --privileged dan a los jobs control total del host. Un job malicioso puede escapar del contenedor, acceder a los datos de otros jobs o comprometer el propio runner.
3. Alcance de CI_JOB_TOKEN sin restricciones
Sin un scoping explícito del token, un job comprometido en un proyecto de bajo valor puede usar su CI_JOB_TOKEN para acceder a las APIs y registros de proyectos de alto valor. Habilita las restricciones de alcance del token en cada proyecto.
4. Falta de validación del pipeline en merge requests
Si no se requiere que los pipelines tengan éxito antes del merge, los atacantes pueden enviar código que evade los escaneos de seguridad. Habilita la configuración «Pipelines must succeed».
5. Secretos codificados directamente en .gitlab-ci.yml
Suena obvio, pero las credenciales siguen apareciendo en archivos YAML de pipeline con una frecuencia alarmante. Usa variables de CI, gestores de secretos externos u OIDC — nunca coloques un secreto en línea.
6. Sin registro de auditoría ni monitoreo
GitLab genera eventos de auditoría para cambios en la configuración de CI/CD, pero muchas organizaciones no envían estos logs a un SIEM ni configuran alertas. Sin monitoreo, los compromisos pueden pasar desapercibidos durante semanas.
7. Registros de runners obsoletos
Los runners que fueron registrados hace meses y olvidados pueden tener configuraciones desactualizadas, sistemas operativos sin parches o acceso a proyectos excesivamente amplio. Audita y limpia los runners obsoletos regularmente.
Lista de verificación de implementación
Usa esta lista de verificación para fortalecer sistemáticamente tu entorno de GitLab CI/CD. Prioriza los elementos según tu modelo de amenazas y requisitos de cumplimiento.
Variables y secretos
- ☐ Todos los secretos de producción están marcados como protegidos y enmascarados.
- ☐ Se utilizan variables con alcance de entorno para separar las credenciales de staging y producción.
- ☐ No hay secretos codificados directamente en
.gitlab-ci.ymlni en archivos del repositorio. - ☐ El calendario de rotación de secretos está documentado y se cumple.
- ☐ Se ha integrado un gestor de secretos externo (HashiCorp Vault, AWS Secrets Manager, GCP Secret Manager) para credenciales de alta sensibilidad.
Runners
- ☐ Los runners de despliegue a producción tienen alcance de proyecto y están protegidos.
- ☐ Los shared runners usan executors efímeros y containerizados.
- ☐ El modo privilegiado está deshabilitado o restringido a grupos de runners dedicados.
- ☐ Los tokens de registro de runners se rotan regularmente.
- ☐ Los registros de runners obsoletos se auditan y eliminan trimestralmente.
Entornos y despliegues
- ☐ Los entornos de producción y staging están protegidos.
- ☐ Las aprobaciones de despliegue están habilitadas para producción (Premium/Ultimate).
- ☐ Se configuran puertas manuales para los despliegues en producción.
- ☐ Los procedimientos de rollback están documentados y probados.
- ☐ Las imágenes de contenedores se firman y verifican antes del despliegue.
Tokens y autenticación
- ☐ El alcance de
CI_JOB_TOKENestá restringido en cada proyecto. - ☐ Se usan
id_tokensOIDC en lugar de credenciales cloud estáticas. - ☐ Las políticas de confianza de IAM cloud validan los claims de ruta del proyecto, ref y entorno.
- ☐ Los personal access tokens con alcance de CI/CD se minimizan y auditan.
Configuración de pipelines y merge requests
- ☐ «Pipelines must succeed» está habilitado para todas las ramas protegidas.
- ☐ Las plantillas de detección de secretos y SAST están incluidas en el pipeline por defecto.
- ☐ Las push rules rechazan commits con patrones de secretos conocidos.
- ☐ Los cambios en
.gitlab-ci.ymlrequieren aprobación de revisores de seguridad. - ☐ Los pipelines de forks están sandboxeados o requieren aprobación manual.
Monitoreo y cumplimiento
- ☐ Los eventos de auditoría para cambios en la configuración de CI/CD se envían a un SIEM.
- ☐ Se configuran alertas para actividad sospechosa (por ejemplo, nuevos registros de runners, cambios en variables, despliegues inesperados).
- ☐ Los compliance pipelines (Ultimate) aplican jobs de seguridad obligatorios en todos los proyectos.
- ☐ Las revisiones regulares de acceso cubren permisos de runners, acceso a variables y despliegues de entornos.
Para una versión imprimible y de referencia rápida de estas recomendaciones, consulta nuestra Hoja de referencia de seguridad de GitLab CI.
Laboratorio práctico
Leer sobre seguridad es importante, pero la práctica lo consolida. Nuestro laboratorio interactivo te guía paso a paso en la securización de un pipeline real de GitLab CI — configurando variables protegidas, limitando el alcance de runners, configurando aprobaciones de entorno y más.
👉 Laboratorio: Securización de pipelines de GitLab CI — Variables protegidas, Runners y Entornos
Herramientas y recursos
Las siguientes herramientas y recursos pueden ayudarte a evaluar y mejorar tu postura de seguridad de GitLab CI/CD:
Funcionalidades de seguridad nativas de GitLab
- Security Dashboard — vista centralizada de vulnerabilidades en todos los proyectos de un grupo o instancia.
- Compliance Pipelines (Ultimate) — aplican jobs de CI obligatorios (como detección de secretos) que los maintainers del proyecto no pueden omitir ni modificar.
- Audit Events API — acceso programático a los registros de cambios en la configuración de CI/CD para integración con plataformas SIEM externas.
- Dependency Scanning — identifica vulnerabilidades conocidas en las dependencias del proyecto. Combínalo con la detección de secretos para una cobertura integral de la cadena de suministro.
- Container Scanning — escanea imágenes Docker en busca de vulnerabilidades a nivel de sistema operativo y de lenguaje antes de que lleguen a un registro.
Herramientas de terceros y código abierto
- Cimon — agente de seguridad en tiempo de ejecución para CI/CD que monitorea y restringe el acceso a red/archivos durante la ejecución del pipeline.
- StepSecurity Harden-Runner — originalmente para GitHub Actions, pero los conceptos (filtrado de tráfico saliente, monitoreo de procesos) se aplican también a los runners de GitLab.
- HashiCorp Vault — gestor de secretos estándar de la industria con integración nativa con GitLab a través de la palabra clave
vaulten.gitlab-ci.yml. - Cosign — firma y verificación de imágenes de contenedores. Intégralo en tu pipeline para firmar imágenes después de la compilación y verificarlas antes del despliegue.
- Trivy — escáner de vulnerabilidades integral para contenedores, sistemas de archivos y repositorios Git. Ligero y fácil de integrar en GitLab CI.
Documentación y referencias
- Documentación de seguridad de pipelines de GitLab CI/CD
- Documentación de GitLab Runner
- GitLab OIDC para servicios cloud
- OWASP Top 10 de riesgos de seguridad en CI/CD
Conclusión
GitLab CI/CD es una plataforma DevSecOps potente e integrada — pero su seguridad es tan fuerte como tu configuración. Los controles existen: variables protegidas, scoping de runners, aprobaciones de entorno, federación OIDC, restricciones de CI_JOB_TOKEN, detección de secretos y puertas de despliegue. El desafío es habilitarlos de manera consistente y monitorearlos continuamente.
Comienza con los elementos de mayor impacto: protege y enmascara todos los secretos de producción, limita el alcance de tus runners, restringe el acceso de CI_JOB_TOKEN y habilita la detección de secretos en cada pipeline. Luego añade capas con OIDC para la autenticación cloud, aprobaciones de despliegue para entornos de producción y compliance pipelines para la aplicación a nivel organizacional.
La seguridad no es una configuración única — es una disciplina continua. Revisa tu postura de seguridad de pipelines trimestralmente, audita los controles de acceso, rota las credenciales y mantente al día con las funcionalidades de seguridad en evolución de GitLab. Con las prácticas de esta guía, tendrás un entorno de GitLab CI/CD que no solo es rápido y productivo, sino genuinamente seguro.
¿Listo para poner estos conceptos en práctica? Comienza con nuestra Hoja de referencia de seguridad de GitLab CI para una consulta rápida, luego trabaja en el laboratorio práctico para desarrollar memoria muscular. Y para el contexto más amplio de la gestión de credenciales en todas las plataformas de CI/CD, explora nuestra guía sobre Credenciales de corta duración y federación de identidad de carga de trabajo.