JC Rueda
Ciberseguridad · Aviso

GitLab CE/EE (autogestionado) y Ruby (Onigmo) · Ejecución remota de código mediante expresiones regulares

Un atacante intentó aprovechar un fallo de máxima gravedad de GitLab contra la forja de Alpine Linux una semana después de publicarse el parche. Alpine no ha hallado pruebas de que lo lograra, pero ha reconstruido el servidor y ha descubierto que actualizar GitLab no siempre basta.

Publicado Lectura 9 min Ref. CVE-2026-97229 CVSS 10.0 (GitLab (CNA), aviso de la versión de parche 19.4.2 del 12 de octubre de 2026) Estado Explotación activa

Resumen

CVE-2026-97229 es un desbordamiento de entero (CWE-190) en el motor de expresiones regulares de Ruby (Onigmo). GitLab lo usa al procesar la configuración de CI/CD y puede permitir ejecutar código en el servidor. GitLab lo corrigió el 12 de octubre de 2026 en las versiones 19.2.8, 19.3.5 y 19.4.2, con una puntuación CVSS de 10,0. Los días 20 y 21 de octubre, un atacante intentó explotarlo contra la instancia de GitLab de Alpine Linux, que no estaba parcheada.

Alpine no ha encontrado pruebas de que el ataque tuviera éxito, pero tampoco puede descartarlo. Por eso ha reconstruido el servidor y ha restablecido todas las contraseñas. Según su verificación, sus paquetes y versiones no se manipularon. La lección principal es que, si GitLab se ejecuta con un Ruby propio, actualizar GitLab no corrige el fallo: también hay que actualizar Ruby.

Materias: Vulnerabilidades, Ejecución remota de código, GitLab, Ruby, Cadena de suministro de software, Respuesta a incidentes, Gestión de parches

Una semana después de que GitLab publicara el parche de una vulnerabilidad de máxima gravedad (CVSS 10,0), alguien intentó aprovecharla contra los servidores de Alpine Linux, una de las distribuciones de Linux más usadas en contenedores. El ataque «estuvo cerca de funcionar», según el propio proyecto. Alpine no ha encontrado pruebas de que el atacante llegara a ejecutar código, pero no puede descartarlo, así que ha tratado el servidor como comprometido y lo ha reconstruido desde cero. Su caso deja una advertencia que va más allá de Alpine: en ciertas instalaciones, actualizar GitLab no elimina el fallo.

Descripción

Qué es

GitLab es una plataforma para alojar código fuente y automatizar su compilación y pruebas. A esa automatización se le llama CI/CD, integración y entrega continuas, y se configura con un archivo llamado .gitlab-ci.yml. En ese archivo se pueden escribir expresiones regulares: patrones de texto que sirven para buscar o filtrar cadenas, por ejemplo «todas las ramas cuyo nombre empiece por release-».

GitLab está escrito en Ruby. El lenguaje Ruby evalúa esas expresiones con su motor interno, llamado Onigmo. CVE-2026-97229 es un desbordamiento de entero (CWE-190) en ese motor. Ocurre cuando un número supera el valor máximo que cabe en la variable que lo almacena y «da la vuelta» a un valor pequeño. Aquí afecta al cálculo del tamaño del patrón compilado. GitLab lo describe como «Integer Overflow in CI/CD Regular Expression Compiler». Según su aviso, «bajo ciertas condiciones» un usuario no autenticado podría ejecutar código arbitrario en el servidor.

El descubridor es el investigador Johan Carlsson (joaxcar), que lo comunicó a través del programa de recompensas de GitLab en HackerOne. Ruby confirma que este CVE corresponde al mismo fallo que CVE-2026-93577, corregido en el pull request #19020 de Ruby.

Versiones afectadas

  • GitLab CE/EE autogestionado (el que cada organización instala en sus propios servidores): de la 19.2 a la 19.2.7, de la 19.3 a la 19.3.4 y de la 19.4 a la 19.4.1. Alguna prensa cita la 19.3.4 como versión corregida, pero eso es un error. El aviso de GitLab indica la 19.3.5, y Alpine confirma que la 19.3.4 no incluía el arreglo.
  • GitLab.com ya estaba parcheado y los clientes de GitLab Dedicated no tienen que hacer nada, según GitLab.
  • Ruby anterior a 3.3.13, 3.4.12 y 4.0.9. Esto afecta a cualquier aplicación Ruby que compile expresiones regulares a partir de texto controlado por un atacante, con Regexp.new, Regexp.union, Regexp.compile o interpolando la entrada en /#{input}/. Las aplicaciones que solo usan expresiones escritas por sus desarrolladores no están expuestas.

El incidente de Alpine

Alpine publicó el 28 de octubre de 2026 un informe detallado. El 13 de octubre había actualizado su GitLab a la 19.3.4 en vez de a la 19.3.5 por error. El 20 de octubre, una cuenta recién registrada empezó a sondear la instancia. Los días 20 y 21 envió configuraciones de CI manipuladas que hicieron caer ocho veces los procesos de GitLab. En cuatro de esas caídas el atacante superó una parte del exploit, pero falló en el paso siguiente. También descargó la imagen de contenedor de GitLab que publica Alpine, lo que según el proyecto «sugiere» que estaba ajustando el exploit a su compilación exacta. El 22 de octubre Alpine actualizó a la 19.3.6, pero la instancia siguió siendo vulnerable por el motivo que se explica más abajo. El 23 bloqueó la cuenta. Los días 25 y 26 el atacante volvió a intentarlo sin éxito. El 27 Alpine cerró GitLab y el 28 terminó la reconstrucción.

Mecánica

Cómo funciona el fallo

Según el análisis de Rapid7, GitLab valida la expresión regular que recibe. Después, Onigmo la vuelve a compilar para UTF-8, la codificación de texto estándar, y es entonces cuando se produce el desbordamiento en el cálculo del tamaño del «programa» interno que representa el patrón. El resultado son instrucciones inválidas en memoria que, bien encadenadas, permiten saltarse el ASLR (la protección que coloca la memoria en posiciones aleatorias) y ejecutar órdenes en el servidor con el usuario de sistema git. Ruby advierte de que Regexp.timeout no protege frente a estos fallos y de que limitar la longitud del patrón tampoco es fiable, porque algunos se activan con patrones cortos.

Requisitos reales del ataque

El vector oficial (AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H) significa: ataque por red, baja complejidad, sin privilegios, sin interacción de la víctima y con impacto total en confidencialidad, integridad y disponibilidad. Rapid7 matiza que, en la práctica, el atacante necesita poder subir un .gitlab-ci.yml malicioso y una ruta de repositorio con caracteres UTF-8 a una rama de un proyecto público. Basta con una cuenta normal que pueda crear proyectos públicos. Si la instancia permite que cualquiera se registre, esa barrera desaparece, que es exactamente lo que pasó en Alpine. Rapid7 publicó una prueba de concepto (PoC, código que demuestra el ataque) el 13 de octubre.

Por qué actualizar GitLab no fue suficiente en Alpine

El arreglo no está en el código de GitLab. Son parches al Ruby que GitLab incluye en sus paquetes e imágenes oficiales. Las notas de las versiones corregidas mencionan los parches «Ruby regexp program size» y «repeat-range double-free». Alpine construía su imagen de contenedor con un Ruby estándar, así que la versión 19.3.6 seguía siendo vulnerable. Le ocurrirá lo mismo a quien ejecute GitLab desde el código fuente o en imágenes propias con un Ruby que no sea el que distribuye GitLab.

Qué habría quedado expuesto si el ataque hubiera tenido éxito

Alpine enumera lo que podría haberse expuesto, sin afirmar que ocurriera: correos, nombres e IP de todos los usuarios; hashes de contraseñas (versiones cifradas de forma irreversible); secretos de doble factor; variables de CI/CD y tokens de los ejecutores; credenciales de webhooks, integraciones y espejos; tokens personales (guardados como hash); y repositorios privados e incidencias confidenciales.

Respuesta del creador

GitLab

GitLab publicó el 12 de octubre de 2026 una versión crítica de parche (19.4.2, 19.3.5 y 19.2.8) y pidió a las instalaciones autogestionadas que actualizaran de inmediato. Además, publicó seis detecciones de amenazas para ayudar a identificar intentos de explotación, entre ellas una para caídas de los procesos nativos de Onigmo.

Ruby

El 23 de octubre, Ruby publicó las versiones 3.3.13, 3.4.12 y 4.0.9 con las correcciones de Onigmo vinculadas a cuatro CVE asignados por GitLab: CVE-2026-89078, CVE-2026-93577, CVE-2026-97229 y CVE-2026-110264. La rama 3.3 solo recibe parches de seguridad, pero el proyecto ha incluido estas correcciones de forma excepcional. Ruby no ha pedido CVE propios y debatirá si trata esta clase de fallos como vulnerabilidades.

Alpine Linux

Alpine ha optado por la vía prudente. Ha reconstruido GitLab desde cero, ha restablecido todas las contraseñas, ha sustituido las claves secretas de la aplicación y ha mantenido la instancia cerrada mientras la prueba. Sus conclusiones:

  • Confirmado por Alpine: el repositorio aports, los paquetes compilados del 20 al 24 de octubre y las versiones estables del 21 de octubre (3.21.9, 3.22.7, 3.23.7 y 3.24.3, incluidas las ISO y los minirootfs de los que salen las imágenes Docker oficiales) coinciden con registros externos a GitLab que el atacante no podía alcanzar: el clon de un desarrollador y los 45 servidores de compilación. Las claves de firma de paquetes nunca han estado en el servidor de GitLab.
  • Sin pruebas, pero sin poder descartarlo: no hay rastro de ejecución de código ni de fuga de datos por web o API. Sin embargo, un exploit con éxito no dejaría caídas ni rastro en los registros web, y Alpine ha perdido algunos registros del día del ataque. Tampoco registraba las conexiones salientes.
  • Pendiente: la instancia siguió siendo vulnerable hasta el cierre del 27 de octubre, así que Alpine está ampliando las comprobaciones de integridad hasta esa fecha.
  • Alpine ha detectado además intentos automatizados de inicio de sesión con contraseñas filtradas en otros servicios.

Autoridades

En la fecha de este aviso, CVE-2026-97229 no figura en el catálogo de vulnerabilidades explotadas de CISA (KEV) y no hemos podido consultar su ficha en NVD. No consta que GitLab haya confirmado ataques con éxito. El intento contra Alpine es un caso documentado de explotación intentada en un entorno real; no hay constancia de que lograra su objetivo. No hay atribución pública del atacante y no especulamos sobre ella.

Perspectiva jurídica

Si una organización con una instancia vulnerable no puede descartar el acceso, como le pasó a Alpine, conviene que lo valore como posible brecha de datos personales. Esa valoración afecta a la notificación a la AEPD en 72 horas (art. 33 RGPD) y, en su caso, a la comunicación a los afectados (art. 34). Si la entidad está sujeta a NIS2, deberá revisar también sus obligaciones de notificación de incidentes. Documentar las decisiones, como ha hecho Alpine con su cronología, forma parte de la diligencia debida.

Parches y mitigaciones

Versiones corregidas

  • GitLab CE/EE: 19.2.8, 19.3.5, 19.4.2 o posteriores.
  • Ruby: 3.3.13, 3.4.12, 4.0.9 o posteriores.
  • Imagen alpinelinux/gitlab: hay que volver a descargar la etiqueta 19.3.6. Solo la imagen publicada el 27 de octubre incluye Ruby 3.3.13. Cualquier 19.3.6 descargada antes de esa fecha, y todas las etiquetas anteriores, son vulnerables.
  • Paquete ruby de Alpine: Alpine 3.22, 3.23, 3.24 y edge incluyen Ruby 3.4.12, y Alpine 3.21 incluye Ruby 3.3.13. Se actualiza con apk upgrade.

Qué hacer ya

  1. Si usa los paquetes Omnibus o las imágenes oficiales de GitLab: actualice a una versión corregida. Cuidado: la 19.3.4 no está corregida.
  2. Si ejecuta GitLab con su propio Ruby (desde el código fuente o en una imagen propia): actualizar GitLab no basta. Compruebe con ruby -v que tiene una versión corregida o aplique los parches de Ruby que distribuye GitLab.
  3. Si no puede actualizar de inmediato: Rapid7 recomienda desactivar el autorregistro, restringir el acceso anónimo a proyectos públicos e impedir que usuarios no confiables creen proyectos o escriban en ellos. Esto corta la vía de ataque demostrada, pero no corrige el fallo.
  4. Revise indicios: caídas repetidas de los procesos de GitLab (errores 502, trabajos de CI fallidos), cuentas recién creadas que envían configuraciones de CI extrañas y las detecciones publicadas por GitLab. Si su instancia estuvo expuesta y no la parcheó a tiempo, considere rotar secretos: variables de CI/CD, tokens de ejecutores, tokens personales y credenciales de integraciones.
  5. Otras aplicaciones Ruby: si compilan expresiones regulares a partir de datos de usuarios, actualice Ruby o deje de hacerlo.
  6. Usuarios de gitlab.alpinelinux.org: cuando la instancia reabra, tendrán que crear una contraseña nueva con «Forgot your password?». Si reutilizaban esa contraseña en otros servicios, deben cambiarla también allí.

Fuentes