{"id":591,"date":"2026-03-24T08:40:58","date_gmt":"2026-03-24T07:40:58","guid":{"rendered":"https:\/\/secure-pipelines.com\/?p=591"},"modified":"2026-03-24T18:38:48","modified_gmt":"2026-03-24T17:38:48","slug":"gitlab-ci-cd-security-definitive-guide","status":"publish","type":"post","link":"https:\/\/secure-pipelines.com\/es\/ci-cd-security\/gitlab-ci-cd-security-definitive-guide\/","title":{"rendered":"Seguridad de GitLab CI\/CD: La Gu\u00eda Definitiva"},"content":{"rendered":"<p>GitLab CI\/CD se ha convertido en la columna vertebral del DevSecOps moderno, ofreciendo una plataforma integrada donde el c\u00f3digo, los pipelines, el escaneo de seguridad y los despliegues convergen en una \u00fanica interfaz. Pero esa profunda integraci\u00f3n 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.<\/p>\n<p>Esta gu\u00eda definitiva cubre cada superficie relevante para la seguridad de GitLab CI\/CD \u2014 desde variables protegidas y scoping de runners hasta federaci\u00f3n OIDC y seguridad en pipelines de merge requests. Ya sea que est\u00e9s fortaleciendo una instalaci\u00f3n existente de GitLab o construyendo una pr\u00e1ctica de DevSecOps desde cero, este art\u00edculo te proporciona el conocimiento y las listas de verificaci\u00f3n accionables que necesitas.<\/p>\n<h2 class=\"wp-block-heading\">Por qu\u00e9 importa la seguridad de GitLab CI\/CD<\/h2>\n<p>GitLab se posiciona como la \u00abPlataforma DevOps \u00danica,\u00bb y con raz\u00f3n. El control de c\u00f3digo fuente, la gesti\u00f3n de incidencias, CI\/CD, el registro de contenedores, el registro de paquetes, el escaneo de seguridad y la gesti\u00f3n de despliegues conviven bajo un mismo techo. Esa consolidaci\u00f3n simplifica las herramientas \u2014 pero tambi\u00e9n concentra el riesgo. Un \u00fanico job de pipeline comprometido puede potencialmente leer c\u00f3digo fuente, robar credenciales, subir im\u00e1genes maliciosas y activar despliegues en producci\u00f3n.<\/p>\n<p>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 \u2014 ya sea a trav\u00e9s de una dependencia envenenada, un shared runner comprometido o un merge request malicioso \u2014 pueden exfiltrar secretos, manipular artefactos de compilaci\u00f3n 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.<\/p>\n<h2 class=\"wp-block-heading\">Comprendiendo el modelo de seguridad de GitLab CI<\/h2>\n<p>Antes de profundizar en los controles individuales, es \u00fatil comprender los cuatro pilares del modelo de seguridad de GitLab CI:<\/p>\n<ol class=\"wp-block-list\">\n<li><strong>Runners<\/strong> \u2014 la capa de c\u00f3mputo que ejecuta los jobs. La seguridad depende del aislamiento, el nivel de confianza y el scoping.<\/li>\n<li><strong>Variables<\/strong> \u2014 la configuraci\u00f3n y los secretos inyectados en los jobs. La protecci\u00f3n y el enmascaramiento determinan qui\u00e9n y qu\u00e9 puede acceder a ellos.<\/li>\n<li><strong>Environments<\/strong> \u2014 objetivos l\u00f3gicos de despliegue (staging, producci\u00f3n). Las reglas de protecci\u00f3n y las puertas de aprobaci\u00f3n controlan qui\u00e9n puede desplegar y d\u00f3nde.<\/li>\n<li><strong>Tokens<\/strong> \u2014 credenciales de corta duraci\u00f3n (<code>CI_JOB_TOKEN<\/code>, OIDC <code>id_tokens<\/code>) que autentican los jobs ante otros servicios. El scoping limita su radio de impacto.<\/li>\n<\/ol>\n<p>Cada medida de fortalecimiento en esta gu\u00eda se relaciona con uno o m\u00e1s de estos pilares. Domina los cuatro y tendr\u00e1s una postura de defensa en profundidad capaz de resistir tanto errores internos como ataques externos.<\/p>\n<h2 class=\"wp-block-heading\">Variables protegidas y enmascaradas<\/h2>\n<p>Las variables de CI\/CD son el mecanismo principal para inyectar secretos \u2014 claves API, credenciales cloud, contrase\u00f1as de bases de datos \u2014 en los jobs del pipeline. GitLab ofrece dos salvaguardas ortogonales: <strong>protecci\u00f3n<\/strong> y <strong>enmascaramiento<\/strong>.<\/p>\n<h3 class=\"wp-block-heading\">Variables protegidas<\/h3>\n<p>Cuando una variable se marca como <em>protegida<\/em>, GitLab solo la expone a los jobs que se ejecutan en <strong>ramas protegidas<\/strong> o <strong>tags protegidos<\/strong>. Este es un control cr\u00edtico: 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\u00f3n. La variable simplemente no existe en el entorno del job para refs no protegidos.<\/p>\n<p><strong>Mejores pr\u00e1cticas para variables protegidas:<\/strong><\/p>\n<ul class=\"wp-block-list\">\n<li>Marca cada secreto de producci\u00f3n como protegido. No hay raz\u00f3n v\u00e1lida para que un job de una rama de funcionalidad acceda a credenciales de producci\u00f3n.<\/li>\n<li>Limita qui\u00e9n puede hacer push o merge en ramas protegidas (rol Maintainer o superior). Esto crea una puerta humana antes de que los secretos sean accesibles.<\/li>\n<li>Usa variables con alcance de entorno cuando el mismo nombre de secreto difiere entre staging y producci\u00f3n. GitLab inyectar\u00e1 el valor correcto bas\u00e1ndose en la palabra clave <code>environment:<\/code> en la definici\u00f3n del job.<\/li>\n<li>Rota las variables protegidas regularmente. Incluso las variables protegidas pueden filtrarse a trav\u00e9s de logging mal configurado o runners comprometidos.<\/li>\n<\/ul>\n<h3 class=\"wp-block-heading\">Variables enmascaradas<\/h3>\n<p>El enmascaramiento evita que el valor de una variable aparezca en los logs de los jobs. GitLab reemplaza cualquier aparici\u00f3n del valor con <code>[MASKED]<\/code>. El enmascaramiento es una red de seguridad, no una frontera de seguridad \u2014 protege contra exposici\u00f3n accidental (por ejemplo, un comando <code>curl<\/code> verboso que registra cabeceras) pero no impide que un paso malicioso del job codifique el valor en Base64 o lo escriba en un artefacto.<\/p>\n<p><strong>Combina protecci\u00f3n y enmascaramiento.<\/strong> Una variable que est\u00e1 protegida <em>y<\/em> enmascarada te da la defensa incorporada m\u00e1s fuerte: alcance limitado por rama m\u00e1s redacci\u00f3n a nivel de logs.<\/p>\n<h2 class=\"wp-block-heading\">Tipos de runners y scoping<\/h2>\n<p>Los runners son donde tu c\u00f3digo realmente se ejecuta. Comprender los tipos de runners y sus implicaciones de seguridad es esencial para un entorno de GitLab CI fortalecido.<\/p>\n<h3 class=\"wp-block-heading\">Shared, Group y Project Runners<\/h3>\n<p>GitLab soporta tres alcances para runners:<\/p>\n<ul class=\"wp-block-list\">\n<li><strong>Shared runners<\/strong> \u2014 disponibles para todos los proyectos en la instancia. Convenientes pero de mayor riesgo: un proyecto malicioso puede potencialmente dejar artefactos, cach\u00e9s o procesos que afecten al siguiente job de un proyecto no relacionado.<\/li>\n<li><strong>Group runners<\/strong> \u2014 disponibles para todos los proyectos dentro de un grupo espec\u00edfico. Un punto medio razonable que limita la exposici\u00f3n entre proyectos mientras reduce la sobrecarga de gesti\u00f3n de runners.<\/li>\n<li><strong>Project runners<\/strong> \u2014 dedicados a un \u00fanico proyecto. M\u00e1ximo aislamiento, pero mayor costo operativo. Recomendado para repositorios de alta seguridad que manejan secretos de producci\u00f3n o datos sensibles de clientes.<\/li>\n<\/ul>\n<h3 class=\"wp-block-heading\">Protected Runners<\/h3>\n<p>Cualquier runner puede marcarse como <strong>protegido<\/strong>. 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\u00f3n solo ejecuta en <code>main<\/code>, y solo los jobs en <code>main<\/code> tienen acceso a los secretos de producci\u00f3n.<\/p>\n<p><strong>Lista de verificaci\u00f3n para el fortalecimiento de runners:<\/strong><\/p>\n<ul class=\"wp-block-list\">\n<li>Usa runners ef\u00edmeros (auto-escalados, destruidos despu\u00e9s de cada job) para eliminar la persistencia de datos entre jobs.<\/li>\n<li>Ejecuta Docker-in-Docker con <code>--privileged<\/code> solo cuando sea absolutamente necesario, y a\u00edsla esos runners en un grupo de seguridad dedicado.<\/li>\n<li>Deshabilita el executor shell en los shared runners. Usa executors de Docker o Kubernetes con contextos de seguridad restrictivos.<\/li>\n<li>Etiqueta los runners de despliegue a producci\u00f3n y bloqu\u00e9alos a proyectos espec\u00edficos y ramas protegidas.<\/li>\n<li>Audita los tokens de registro de runners \u2014 r\u00f3talos regularmente y revoca cualquier token filtrado inmediatamente.<\/li>\n<\/ul>\n<h2 class=\"wp-block-heading\">Entornos protegidos y aprobaciones de despliegue<\/h2>\n<p>Los environments de GitLab representan objetivos de despliegue como <code>staging<\/code>, <code>production<\/code> o <code>canary<\/code>. Proteger un entorno a\u00f1ade una capa de autorizaci\u00f3n que va m\u00e1s all\u00e1 de la protecci\u00f3n de ramas.<\/p>\n<h3 class=\"wp-block-heading\">C\u00f3mo funcionan los entornos protegidos<\/h3>\n<p>Cuando proteges un entorno, especificas qu\u00e9 usuarios o grupos tienen permiso para desplegar en \u00e9l. Incluso si un pipeline se ejecuta en una rama protegida, el job de despliegue no se ejecutar\u00e1 a menos que el usuario que lo activ\u00f3 tenga el permiso requerido. Esto crea una separaci\u00f3n de responsabilidades: los desarrolladores pueden hacer merge del c\u00f3digo, pero solo los desplegadores designados pueden llevarlo a producci\u00f3n.<\/p>\n<h3 class=\"wp-block-heading\">Aprobaciones de despliegue (Premium\/Ultimate)<\/h3>\n<p>Las ediciones Premium y Ultimate de GitLab ofrecen <strong>aprobaciones de despliegue<\/strong> \u2014 un mecanismo que pausa un job de despliegue y espera a que uno o m\u00e1s aprobadores designados den luz verde. Esto es invaluable para entornos regulados donde los procesos de gesti\u00f3n de cambios requieren aprobaci\u00f3n humana antes de que los cambios en producci\u00f3n entren en vigor.<\/p>\n<p><strong>Consejos de configuraci\u00f3n:<\/strong><\/p>\n<ul class=\"wp-block-list\">\n<li>Requiere al menos dos aprobadores para despliegues en producci\u00f3n para prevenir compromisos de una sola persona.<\/li>\n<li>Establece reglas de aprobaci\u00f3n a nivel de grupo para que se apliquen consistentemente en todos los proyectos dentro de una unidad de negocio.<\/li>\n<li>Combina las aprobaciones de despliegue con runners protegidos y variables protegidas para una defensa en capas.<\/li>\n<li>Usa la palabra clave <code>environment: deployment_tier<\/code> para clasificar entornos (production, staging, testing, development) y aplicar pol\u00edticas apropiadas a cada nivel.<\/li>\n<\/ul>\n<h2 class=\"wp-block-heading\">Scoping de CI_JOB_TOKEN<\/h2>\n<p>Cada job de GitLab CI recibe un <code>CI_JOB_TOKEN<\/code> generado autom\u00e1ticamente \u2014 una credencial de corta duraci\u00f3n 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.<\/p>\n<h3 class=\"wp-block-heading\">Limitando el acceso de CI_JOB_TOKEN<\/h3>\n<p>GitLab 15.9+ introdujo controles de <strong>alcance del job token de CI\/CD<\/strong>. Ahora puedes configurar una lista de permitidos de proyectos a los que el <code>CI_JOB_TOKEN<\/code> de un proyecto dado puede acceder. Esta es una configuraci\u00f3n obligatoria para cualquier organizaci\u00f3n consciente de la seguridad.<\/p>\n<p><strong>Pasos para fortalecer CI_JOB_TOKEN:<\/strong><\/p>\n<ol class=\"wp-block-list\">\n<li>Navega a <strong>Settings > CI\/CD > Token Access<\/strong> en tu proyecto.<\/li>\n<li>Habilita <strong>Limit CI_JOB_TOKEN access<\/strong> (esto restringe el token al proyecto actual por defecto).<\/li>\n<li>Agrega solo los proyectos espec\u00edficos a los que los jobs de este proyecto leg\u00edtimamente necesitan acceder.<\/li>\n<li>Revisa la lista de permitidos trimestralmente y elimina las entradas obsoletas.<\/li>\n<\/ol>\n<p>Con tokens con alcance limitado, incluso si un atacante compromete un job del pipeline, el radio de impacto se limita a los proyectos expl\u00edcitamente permitidos en lugar de toda la instancia de GitLab.<\/p>\n<h2 class=\"wp-block-heading\">Federaci\u00f3n OIDC con id_tokens<\/h2>\n<p>Las credenciales cloud codificadas directamente en variables de CI son un riesgo de seguridad persistente. El soporte de <strong>OIDC (OpenID Connect)<\/strong> de GitLab elimina este riesgo por completo al permitir que los jobs del pipeline se autentiquen ante proveedores cloud usando tokens de corta duraci\u00f3n, firmados criptogr\u00e1ficamente.<\/p>\n<h3 class=\"wp-block-heading\">C\u00f3mo funciona<\/h3>\n<p>Cuando defines un bloque <code>id_tokens<\/code> en tu <code>.gitlab-ci.yml<\/code>, GitLab genera un JWT firmado para cada job. El JWT contiene claims sobre el job \u2014 ruta del proyecto, nombre del ref, entorno, fuente del pipeline \u2014 que el proveedor cloud puede evaluar contra su pol\u00edtica de confianza.<\/p>\n<pre><code>deploy_production:\n  id_tokens:\n    GITLAB_OIDC_TOKEN:\n      aud: https:\/\/aws.example.com\n  script:\n    - |\n      export AWS_WEB_IDENTITY_TOKEN_FILE=$(mktemp)\n      echo \"$GITLAB_OIDC_TOKEN\" > $AWS_WEB_IDENTITY_TOKEN_FILE\n      aws sts assume-role-with-web-identity \\\n        --role-arn arn:aws:iam::123456789012:role\/gitlab-deploy \\\n        --web-identity-token file:\/\/$AWS_WEB_IDENTITY_TOKEN_FILE\n<\/code><\/pre>\n<p>En el lado del proveedor cloud (AWS, GCP, Azure), configuras una pol\u00edtica de confianza que solo acepta tokens de proyectos, ramas y entornos espec\u00edficos. Esto significa:<\/p>\n<ul class=\"wp-block-list\">\n<li><strong>Sin credenciales est\u00e1ticas<\/strong> que rotar o que puedan filtrarse.<\/li>\n<li><strong>Acceso granular<\/strong> \u2014 un token de una rama de funcionalidad puede ser rechazado por el proveedor cloud, incluso si el pipeline es v\u00e1lido por lo dem\u00e1s.<\/li>\n<li><strong>Auditabilidad<\/strong> \u2014 cada evento de autenticaci\u00f3n se registra con los claims completos del JWT.<\/li>\n<\/ul>\n<p>Para una inmersi\u00f3n profunda en los patrones de federaci\u00f3n OIDC en AWS, GCP y Azure, consulta nuestra gu\u00eda dedicada: <a href=\"https:\/\/secure-pipelines.com\/es\/ci-cd-security\/short-lived-credentials-workload-identity-federation-ci-cd-2\/\">Credenciales de corta duraci\u00f3n y federaci\u00f3n de identidad de carga de trabajo para CI\/CD<\/a>.<\/p>\n<h2 class=\"wp-block-heading\">Seguridad de pipelines de Merge Request<\/h2>\n<p>Los merge requests son el vector m\u00e1s com\u00fan para inyectar c\u00f3digo malicioso en los pipelines. Un contribuidor externo (o una cuenta comprometida) puede enviar un merge request que modifique <code>.gitlab-ci.yml<\/code> para exfiltrar secretos o establecer persistencia.<\/p>\n<h3 class=\"wp-block-heading\">Protecciones clave<\/h3>\n<ul class=\"wp-block-list\">\n<li><strong>Usa <code>rules: - if: $CI_PIPELINE_SOURCE == 'merge_request_event'<\/code><\/strong> 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.<\/li>\n<li><strong>Requiere \u00e9xito del pipeline antes del merge.<\/strong> Esto asegura que los escaneos de seguridad (SAST, escaneo de dependencias, detecci\u00f3n de secretos) se ejecuten en cada MR.<\/li>\n<li><strong>Limita <code>include:<\/code> a fuentes confiables.<\/strong> Los MR maliciosos pueden agregar directivas <code>include: remote:<\/code> que traen YAML controlado por el atacante. Usa una lista de permitidos de dominios de inclusi\u00f3n o fija a refs espec\u00edficos.<\/li>\n<li><strong>Habilita \u00abPipelines must succeed\u00bb y \u00abAll threads must be resolved\u00bb<\/strong> en la configuraci\u00f3n de merge requests de tu proyecto.<\/li>\n<li><strong>Revisa cuidadosamente los cambios en <code>.gitlab-ci.yml<\/code>.<\/strong> Cualquier MR que modifique la configuraci\u00f3n del pipeline deber\u00eda requerir aprobaci\u00f3n de un revisor consciente de la seguridad.<\/li>\n<\/ul>\n<h3 class=\"wp-block-heading\">Restricciones de pipelines de forks<\/h3>\n<p>Para proyectos p\u00fablicos o de c\u00f3digo abierto, los pipelines de forks presentan riesgos adicionales. GitLab te permite:<\/p>\n<ul class=\"wp-block-list\">\n<li>Ejecutar pipelines de forks en modo restringido sin acceso a las variables de CI del proyecto.<\/li>\n<li>Requerir aprobaci\u00f3n manual antes de ejecutar pipelines desde forks (disponible en Premium\/Ultimate).<\/li>\n<li>Usar runners separados y sin privilegios para los pipelines de forks.<\/li>\n<\/ul>\n<h2 class=\"wp-block-heading\">Detecci\u00f3n de secretos con plantillas SAST integradas<\/h2>\n<p>GitLab incluye plantillas SAST (Static Application Security Testing) integradas que incluyen detecci\u00f3n de secretos. Habilitarlas es sencillo:<\/p>\n<pre><code>include:\n  - template: Jobs\/Secret-Detection.gitlab-ci.yml\n  - template: Jobs\/SAST.gitlab-ci.yml\n<\/code><\/pre>\n<p>El esc\u00e1ner de detecci\u00f3n de secretos utiliza coincidencia de patrones y an\u00e1lisis de entrop\u00eda para identificar credenciales filtradas, claves API, claves privadas y tokens en tu c\u00f3digo 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.<\/p>\n<p><strong>Maximizando la efectividad de la detecci\u00f3n de secretos:<\/strong><\/p>\n<ul class=\"wp-block-list\">\n<li>Habilita la <strong>detecci\u00f3n de secretos a nivel de pipeline<\/strong> (no solo el escaneo hist\u00f3rico) para que cada commit sea verificado.<\/li>\n<li>Configura <strong>push rules<\/strong> para rechazar commits que contengan patrones de secretos conocidos (por ejemplo, <code>AKIA<\/code> para claves de acceso de AWS).<\/li>\n<li>Integra con la <strong>gesti\u00f3n de vulnerabilidades de GitLab<\/strong> para rastrear, clasificar y resolver los secretos detectados.<\/li>\n<li>Agrega patrones personalizados para formatos de secretos espec\u00edficos de la organizaci\u00f3n (claves API internas, tokens de cuentas de servicio).<\/li>\n<li>Ejecuta la detecci\u00f3n de secretos tanto en la rama de origen como en el resultado del merge para detectar secretos introducidos por conflictos de merge.<\/li>\n<\/ul>\n<h2 class=\"wp-block-heading\">Flujos de trabajo de despliegue seguro<\/h2>\n<p>Llevar c\u00f3digo desde un pipeline a un entorno de producci\u00f3n de forma segura requiere m\u00e1s que simplemente ejecutar <code>kubectl apply<\/code>. GitLab soporta varias estrategias de despliegue que equilibran velocidad con seguridad.<\/p>\n<h3 class=\"wp-block-heading\">Puertas manuales<\/h3>\n<p>Usa la palabra clave <code>when: manual<\/code> para crear puntos de aprobaci\u00f3n expl\u00edcitos en tu pipeline. Un patr\u00f3n com\u00fan es desplegar autom\u00e1ticamente en staging pero requerir un clic manual para producci\u00f3n. Combinado con entornos protegidos y aprobaciones de despliegue, esto crea un flujo de trabajo robusto de gesti\u00f3n de cambios.<\/p>\n<pre><code>deploy_production:\n  stage: deploy\n  environment:\n    name: production\n    deployment_tier: production\n  when: manual\n  only:\n    - main\n<\/code><\/pre>\n<h3 class=\"wp-block-heading\">Despliegues canary<\/h3>\n<p>GitLab se integra con Kubernetes para soportar despliegues canary de forma nativa. Al desplegar primero a un peque\u00f1o 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\u00e1s de uno de fiabilidad \u2014 una compilaci\u00f3n comprometida que llega al canary puede ser detectada y revertida antes de que se propague.<\/p>\n<h3 class=\"wp-block-heading\">GitOps con el GitLab Agent for Kubernetes<\/h3>\n<p>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\u00faster obtiene el estado deseado de un repositorio Git. Esto elimina la necesidad de credenciales kubeconfig de larga duraci\u00f3n en las variables de CI y reduce significativamente la superficie de ataque.<\/p>\n<p><strong>Mejores pr\u00e1cticas de seguridad en despliegues:<\/strong><\/p>\n<ul class=\"wp-block-list\">\n<li>Nunca almacenes kubeconfig o credenciales cloud como variables de CI no protegidas. Usa federaci\u00f3n OIDC o el GitLab Agent.<\/li>\n<li>Implementa automatizaci\u00f3n de rollback \u2014 si las verificaciones de salud fallan despu\u00e9s del despliegue, revierte autom\u00e1ticamente al estado anterior conocido como bueno.<\/li>\n<li>Firma las im\u00e1genes de contenedores y verifica las firmas antes del despliegue usando Cosign o Notary.<\/li>\n<li>Usa tags inmutables o referencias basadas en digest para im\u00e1genes de contenedores para prevenir ataques basados en tags.<\/li>\n<\/ul>\n<h2 class=\"wp-block-heading\">Errores de configuraci\u00f3n comunes<\/h2>\n<p>Incluso los equipos que entienden los conceptos de seguridad de GitLab CI suelen caer en estas trampas:<\/p>\n<h3 class=\"wp-block-heading\">1. Variables no protegidas que contienen secretos de producci\u00f3n<\/h3>\n<p>Este es el error de configuraci\u00f3n m\u00e1s com\u00fan y m\u00e1s peligroso. Si una contrase\u00f1a de base de datos de producci\u00f3n se almacena como una variable no protegida, cualquier desarrollador puede crear una rama, agregar un paso <code>echo $DB_PASSWORD<\/code> y leerla desde el log del job. Siempre protege y enmascara los secretos de producci\u00f3n.<\/p>\n<h3 class=\"wp-block-heading\">2. Shared runners excesivamente permisivos<\/h3>\n<p>Los shared runners con montaje del socket de Docker (<code>\/var\/run\/docker.sock<\/code>) o modo <code>--privileged<\/code> 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.<\/p>\n<h3 class=\"wp-block-heading\">3. Alcance de CI_JOB_TOKEN sin restricciones<\/h3>\n<p>Sin un scoping expl\u00edcito del token, un job comprometido en un proyecto de bajo valor puede usar su <code>CI_JOB_TOKEN<\/code> para acceder a las APIs y registros de proyectos de alto valor. Habilita las restricciones de alcance del token en cada proyecto.<\/p>\n<h3 class=\"wp-block-heading\">4. Falta de validaci\u00f3n del pipeline en merge requests<\/h3>\n<p>Si no se requiere que los pipelines tengan \u00e9xito antes del merge, los atacantes pueden enviar c\u00f3digo que evade los escaneos de seguridad. Habilita la configuraci\u00f3n \u00abPipelines must succeed\u00bb.<\/p>\n<h3 class=\"wp-block-heading\">5. Secretos codificados directamente en .gitlab-ci.yml<\/h3>\n<p>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 \u2014 nunca coloques un secreto en l\u00ednea.<\/p>\n<h3 class=\"wp-block-heading\">6. Sin registro de auditor\u00eda ni monitoreo<\/h3>\n<p>GitLab genera eventos de auditor\u00eda para cambios en la configuraci\u00f3n de CI\/CD, pero muchas organizaciones no env\u00edan estos logs a un SIEM ni configuran alertas. Sin monitoreo, los compromisos pueden pasar desapercibidos durante semanas.<\/p>\n<h3 class=\"wp-block-heading\">7. Registros de runners obsoletos<\/h3>\n<p>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.<\/p>\n<h2 class=\"wp-block-heading\">Lista de verificaci\u00f3n de implementaci\u00f3n<\/h2>\n<p>Usa esta lista de verificaci\u00f3n para fortalecer sistem\u00e1ticamente tu entorno de GitLab CI\/CD. Prioriza los elementos seg\u00fan tu modelo de amenazas y requisitos de cumplimiento.<\/p>\n<h3 class=\"wp-block-heading\">Variables y secretos<\/h3>\n<ul class=\"wp-block-list\">\n<li>\u2610 Todos los secretos de producci\u00f3n est\u00e1n marcados como protegidos y enmascarados.<\/li>\n<li>\u2610 Se utilizan variables con alcance de entorno para separar las credenciales de staging y producci\u00f3n.<\/li>\n<li>\u2610 No hay secretos codificados directamente en <code>.gitlab-ci.yml<\/code> ni en archivos del repositorio.<\/li>\n<li>\u2610 El calendario de rotaci\u00f3n de secretos est\u00e1 documentado y se cumple.<\/li>\n<li>\u2610 Se ha integrado un gestor de secretos externo (HashiCorp Vault, AWS Secrets Manager, GCP Secret Manager) para credenciales de alta sensibilidad.<\/li>\n<\/ul>\n<h3 class=\"wp-block-heading\">Runners<\/h3>\n<ul class=\"wp-block-list\">\n<li>\u2610 Los runners de despliegue a producci\u00f3n tienen alcance de proyecto y est\u00e1n protegidos.<\/li>\n<li>\u2610 Los shared runners usan executors ef\u00edmeros y containerizados.<\/li>\n<li>\u2610 El modo privilegiado est\u00e1 deshabilitado o restringido a grupos de runners dedicados.<\/li>\n<li>\u2610 Los tokens de registro de runners se rotan regularmente.<\/li>\n<li>\u2610 Los registros de runners obsoletos se auditan y eliminan trimestralmente.<\/li>\n<\/ul>\n<h3 class=\"wp-block-heading\">Entornos y despliegues<\/h3>\n<ul class=\"wp-block-list\">\n<li>\u2610 Los entornos de producci\u00f3n y staging est\u00e1n protegidos.<\/li>\n<li>\u2610 Las aprobaciones de despliegue est\u00e1n habilitadas para producci\u00f3n (Premium\/Ultimate).<\/li>\n<li>\u2610 Se configuran puertas manuales para los despliegues en producci\u00f3n.<\/li>\n<li>\u2610 Los procedimientos de rollback est\u00e1n documentados y probados.<\/li>\n<li>\u2610 Las im\u00e1genes de contenedores se firman y verifican antes del despliegue.<\/li>\n<\/ul>\n<h3 class=\"wp-block-heading\">Tokens y autenticaci\u00f3n<\/h3>\n<ul class=\"wp-block-list\">\n<li>\u2610 El alcance de <code>CI_JOB_TOKEN<\/code> est\u00e1 restringido en cada proyecto.<\/li>\n<li>\u2610 Se usan <code>id_tokens<\/code> OIDC en lugar de credenciales cloud est\u00e1ticas.<\/li>\n<li>\u2610 Las pol\u00edticas de confianza de IAM cloud validan los claims de ruta del proyecto, ref y entorno.<\/li>\n<li>\u2610 Los personal access tokens con alcance de CI\/CD se minimizan y auditan.<\/li>\n<\/ul>\n<h3 class=\"wp-block-heading\">Configuraci\u00f3n de pipelines y merge requests<\/h3>\n<ul class=\"wp-block-list\">\n<li>\u2610 \u00abPipelines must succeed\u00bb est\u00e1 habilitado para todas las ramas protegidas.<\/li>\n<li>\u2610 Las plantillas de detecci\u00f3n de secretos y SAST est\u00e1n incluidas en el pipeline por defecto.<\/li>\n<li>\u2610 Las push rules rechazan commits con patrones de secretos conocidos.<\/li>\n<li>\u2610 Los cambios en <code>.gitlab-ci.yml<\/code> requieren aprobaci\u00f3n de revisores de seguridad.<\/li>\n<li>\u2610 Los pipelines de forks est\u00e1n sandboxeados o requieren aprobaci\u00f3n manual.<\/li>\n<\/ul>\n<h3 class=\"wp-block-heading\">Monitoreo y cumplimiento<\/h3>\n<ul class=\"wp-block-list\">\n<li>\u2610 Los eventos de auditor\u00eda para cambios en la configuraci\u00f3n de CI\/CD se env\u00edan a un SIEM.<\/li>\n<li>\u2610 Se configuran alertas para actividad sospechosa (por ejemplo, nuevos registros de runners, cambios en variables, despliegues inesperados).<\/li>\n<li>\u2610 Los compliance pipelines (Ultimate) aplican jobs de seguridad obligatorios en todos los proyectos.<\/li>\n<li>\u2610 Las revisiones regulares de acceso cubren permisos de runners, acceso a variables y despliegues de entornos.<\/li>\n<\/ul>\n<p>Para una versi\u00f3n imprimible y de referencia r\u00e1pida de estas recomendaciones, consulta nuestra <a href=\"https:\/\/secure-pipelines.com\/es\/ci-cd-security\/gitlab-ci-security-cheat-sheet\/\">Hoja de referencia de seguridad de GitLab CI<\/a>.<\/p>\n<h2 class=\"wp-block-heading\">Laboratorio pr\u00e1ctico<\/h2>\n<p>Leer sobre seguridad es importante, pero la pr\u00e1ctica lo consolida. Nuestro laboratorio interactivo te gu\u00eda paso a paso en la securizaci\u00f3n de un pipeline real de GitLab CI \u2014 configurando variables protegidas, limitando el alcance de runners, configurando aprobaciones de entorno y m\u00e1s.<\/p>\n<p>\ud83d\udc49 <a href=\"https:\/\/secure-pipelines.com\/ci-cd-security\/lab-securing-gitlab-ci-pipelines-protected-variables-runners-environments\/\">Laboratorio: Securizaci\u00f3n de pipelines de GitLab CI \u2014 Variables protegidas, Runners y Entornos<\/a><\/p>\n<h2 class=\"wp-block-heading\">Herramientas y recursos<\/h2>\n<p>Las siguientes herramientas y recursos pueden ayudarte a evaluar y mejorar tu postura de seguridad de GitLab CI\/CD:<\/p>\n<h3 class=\"wp-block-heading\">Funcionalidades de seguridad nativas de GitLab<\/h3>\n<ul class=\"wp-block-list\">\n<li><strong>Security Dashboard<\/strong> \u2014 vista centralizada de vulnerabilidades en todos los proyectos de un grupo o instancia.<\/li>\n<li><strong>Compliance Pipelines (Ultimate)<\/strong> \u2014 aplican jobs de CI obligatorios (como detecci\u00f3n de secretos) que los maintainers del proyecto no pueden omitir ni modificar.<\/li>\n<li><strong>Audit Events API<\/strong> \u2014 acceso program\u00e1tico a los registros de cambios en la configuraci\u00f3n de CI\/CD para integraci\u00f3n con plataformas SIEM externas.<\/li>\n<li><strong>Dependency Scanning<\/strong> \u2014 identifica vulnerabilidades conocidas en las dependencias del proyecto. Comb\u00ednalo con la detecci\u00f3n de secretos para una cobertura integral de la cadena de suministro.<\/li>\n<li><strong>Container Scanning<\/strong> \u2014 escanea im\u00e1genes Docker en busca de vulnerabilidades a nivel de sistema operativo y de lenguaje antes de que lleguen a un registro.<\/li>\n<\/ul>\n<h3 class=\"wp-block-heading\">Herramientas de terceros y c\u00f3digo abierto<\/h3>\n<ul class=\"wp-block-list\">\n<li><strong><a href=\"https:\/\/github.com\/cider-security-research\/cimon\" rel=\"nofollow noopener\" target=\"_blank\">Cimon<\/a><\/strong> \u2014 agente de seguridad en tiempo de ejecuci\u00f3n para CI\/CD que monitorea y restringe el acceso a red\/archivos durante la ejecuci\u00f3n del pipeline.<\/li>\n<li><strong><a href=\"https:\/\/github.com\/step-security\/harden-runner\" rel=\"nofollow noopener\" target=\"_blank\">StepSecurity Harden-Runner<\/a><\/strong> \u2014 originalmente para GitHub Actions, pero los conceptos (filtrado de tr\u00e1fico saliente, monitoreo de procesos) se aplican tambi\u00e9n a los runners de GitLab.<\/li>\n<li><strong><a href=\"https:\/\/www.vaultproject.io\/\" rel=\"nofollow noopener\" target=\"_blank\">HashiCorp Vault<\/a><\/strong> \u2014 gestor de secretos est\u00e1ndar de la industria con integraci\u00f3n nativa con GitLab a trav\u00e9s de la palabra clave <code>vault<\/code> en <code>.gitlab-ci.yml<\/code>.<\/li>\n<li><strong><a href=\"https:\/\/github.com\/sigstore\/cosign\" rel=\"nofollow noopener\" target=\"_blank\">Cosign<\/a><\/strong> \u2014 firma y verificaci\u00f3n de im\u00e1genes de contenedores. Int\u00e9gralo en tu pipeline para firmar im\u00e1genes despu\u00e9s de la compilaci\u00f3n y verificarlas antes del despliegue.<\/li>\n<li><strong><a href=\"https:\/\/trivy.dev\/\" rel=\"nofollow noopener\" target=\"_blank\">Trivy<\/a><\/strong> \u2014 esc\u00e1ner de vulnerabilidades integral para contenedores, sistemas de archivos y repositorios Git. Ligero y f\u00e1cil de integrar en GitLab CI.<\/li>\n<\/ul>\n<h3 class=\"wp-block-heading\">Documentaci\u00f3n y referencias<\/h3>\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/docs.gitlab.com\/ee\/ci\/pipelines\/pipeline_security.html\" rel=\"nofollow noopener\" target=\"_blank\">Documentaci\u00f3n de seguridad de pipelines de GitLab CI\/CD<\/a><\/li>\n<li><a href=\"https:\/\/docs.gitlab.com\/ee\/ci\/runners\/\" rel=\"nofollow noopener\" target=\"_blank\">Documentaci\u00f3n de GitLab Runner<\/a><\/li>\n<li><a href=\"https:\/\/docs.gitlab.com\/ee\/ci\/cloud_services\/\" rel=\"nofollow noopener\" target=\"_blank\">GitLab OIDC para servicios cloud<\/a><\/li>\n<li><a href=\"https:\/\/owasp.org\/www-project-top-10-ci-cd-security-risks\/\" rel=\"nofollow noopener\" target=\"_blank\">OWASP Top 10 de riesgos de seguridad en CI\/CD<\/a><\/li>\n<\/ul>\n<h2 class=\"wp-block-heading\">Conclusi\u00f3n<\/h2>\n<p>GitLab CI\/CD es una plataforma DevSecOps potente e integrada \u2014 pero su seguridad es tan fuerte como tu configuraci\u00f3n. Los controles existen: variables protegidas, scoping de runners, aprobaciones de entorno, federaci\u00f3n OIDC, restricciones de CI_JOB_TOKEN, detecci\u00f3n de secretos y puertas de despliegue. El desaf\u00edo es habilitarlos de manera consistente y monitorearlos continuamente.<\/p>\n<p>Comienza con los elementos de mayor impacto: protege y enmascara todos los secretos de producci\u00f3n, limita el alcance de tus runners, restringe el acceso de CI_JOB_TOKEN y habilita la detecci\u00f3n de secretos en cada pipeline. Luego a\u00f1ade capas con OIDC para la autenticaci\u00f3n cloud, aprobaciones de despliegue para entornos de producci\u00f3n y compliance pipelines para la aplicaci\u00f3n a nivel organizacional.<\/p>\n<p>La seguridad no es una configuraci\u00f3n \u00fanica \u2014 es una disciplina continua. Revisa tu postura de seguridad de pipelines trimestralmente, audita los controles de acceso, rota las credenciales y mantente al d\u00eda con las funcionalidades de seguridad en evoluci\u00f3n de GitLab. Con las pr\u00e1cticas de esta gu\u00eda, tendr\u00e1s un entorno de GitLab CI\/CD que no solo es r\u00e1pido y productivo, sino genuinamente seguro.<\/p>\n<p>\u00bfListo para poner estos conceptos en pr\u00e1ctica? Comienza con nuestra <a href=\"https:\/\/secure-pipelines.com\/es\/ci-cd-security\/gitlab-ci-security-cheat-sheet\/\">Hoja de referencia de seguridad de GitLab CI<\/a> para una consulta r\u00e1pida, luego trabaja en el <a href=\"https:\/\/secure-pipelines.com\/ci-cd-security\/lab-securing-gitlab-ci-pipelines-protected-variables-runners-environments\/\">laboratorio pr\u00e1ctico<\/a> para desarrollar memoria muscular. Y para el contexto m\u00e1s amplio de la gesti\u00f3n de credenciales en todas las plataformas de CI\/CD, explora nuestra gu\u00eda sobre <a href=\"https:\/\/secure-pipelines.com\/es\/ci-cd-security\/short-lived-credentials-workload-identity-federation-ci-cd-2\/\">Credenciales de corta duraci\u00f3n y federaci\u00f3n de identidad de carga de trabajo<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>GitLab CI\/CD se ha convertido en la columna vertebral del DevSecOps moderno, ofreciendo una plataforma integrada donde el c\u00f3digo, los pipelines, el escaneo de seguridad y los despliegues convergen en una \u00fanica interfaz. Pero esa profunda integraci\u00f3n es un arma de doble filo: un pipeline mal configurado puede exponer secretos, permitir despliegues no autorizados o &#8230; <a title=\"Seguridad de GitLab CI\/CD: La Gu\u00eda Definitiva\" class=\"read-more\" href=\"https:\/\/secure-pipelines.com\/es\/ci-cd-security\/gitlab-ci-cd-security-definitive-guide\/\" aria-label=\"Leer m\u00e1s sobre Seguridad de GitLab CI\/CD: La Gu\u00eda Definitiva\">Leer m\u00e1s<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[55,57],"tags":[],"post_folder":[],"class_list":["post-591","post","type-post","status-publish","format-standard","hentry","category-ci-cd-security","category-gitlab-ci"],"_links":{"self":[{"href":"https:\/\/secure-pipelines.com\/es\/wp-json\/wp\/v2\/posts\/591","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/secure-pipelines.com\/es\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/secure-pipelines.com\/es\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/secure-pipelines.com\/es\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/secure-pipelines.com\/es\/wp-json\/wp\/v2\/comments?post=591"}],"version-history":[{"count":3,"href":"https:\/\/secure-pipelines.com\/es\/wp-json\/wp\/v2\/posts\/591\/revisions"}],"predecessor-version":[{"id":648,"href":"https:\/\/secure-pipelines.com\/es\/wp-json\/wp\/v2\/posts\/591\/revisions\/648"}],"wp:attachment":[{"href":"https:\/\/secure-pipelines.com\/es\/wp-json\/wp\/v2\/media?parent=591"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/secure-pipelines.com\/es\/wp-json\/wp\/v2\/categories?post=591"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/secure-pipelines.com\/es\/wp-json\/wp\/v2\/tags?post=591"},{"taxonomy":"post_folder","embeddable":true,"href":"https:\/\/secure-pipelines.com\/es\/wp-json\/wp\/v2\/post_folder?post=591"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}