Cinco eventos Timeout::Error de un mismo cliente en treinta minutos, todos procedentes del renderizador OtherMarkup mientras procesa archivos .org. Ese es el umbral que propone el equipo de seguridad de GitLab para detectar intentos contra CVE-2026-110264, y no consigo quitármelo de la cabeza. La mayoría de las instancias de GitLab que he administrado a lo largo de los años nunca renderizaron a propósito un solo documento de Org-mode. Pero todas ellas lo habrían renderizado para un desconocido anónimo, y resulta que ahí está todo el problema.
Primero los hechos, en pocas palabras, porque los necesitas antes que nada. El 21 de octubre de 2026, GitLab publicó un parche crítico fuera de ciclo para CE y EE: 19.5.1, 19.4.3, 19.3.6, 19.2.9, 19.1.9, 19.0.10 y 18.11.13. El fallo es un desbordamiento de enteros (CWE-190) en la forma en que Onigmo, el motor de expresiones regulares de Ruby, maneja patrones que un contenido Org controlado por el atacante puede moldear a través de org-ruby. Un cálculo de tamaño da la vuelta, se toca memoria que no se debería tocar y, en las condiciones adecuadas, un usuario sin autenticar consigue ejecutar código en el servidor. El vector es CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H, así que puntúa un 10.0 redondo. El rango afectado se remonta a la rama 7.0. GitLab.com y las versiones de Dedicated indicadas ya están corregidas. Si tienes tu propia instancia, deja de leer, actualiza y luego vuelve. Y comprueba que Puma y Sidekiq se han reiniciado de verdad con la nueva versión, porque un paquete instalado que no se está ejecutando no ha arreglado nada.
Lo que me inquieta no es tanto el desbordamiento como el sitio donde estaba el agujero. Los fallos de memoria en motores de regex escritos en C son un problema viejo y conocido, y dejaré que la gente de Go presuma un par de frases de sus comprobaciones de límites. Lo que no me quito de encima es que una forja de código, una herramienta cuyo trabajo es custodiar nuestro código fuente y nuestras claves de despliegue, ejecutaba un renderizador de documentos minoritario para visitantes sin autenticar, y ese camino desembocaba directamente en código nativo. Nadie en un equipo de plataforma típico se sentó nunca a decidir que los usuarios anónimos pudieran hacer que el servidor compilara regex a partir de notas de Emacs. Venía incluido en el paquete de «renderizamos bonito tu README», eso sonaba inofensivo y, durante años, lo fue.
La objeción más sólida merece que la escuchemos con justicia, porque estoy medio de acuerdo con ella. No puedes predecir qué parser tendrá el siguiente fallo. Quitas Org-mode y el trimestre que viene será AsciiDoc, o el sanitizador de Markdown, o el generador de miniaturas. Quienes viven en archivos Org son usuarios reales con necesidades reales, y un proveedor que entrega lo mínimo acaba entregando un producto peor. Parchear es la única solución que escala, y GitLab parcheó siete ramas en la misma publicación. Es justo. Si lo que sacas de todo esto es reducir cada funcionalidad a un simple cuadro de texto, perderás esa discusión con tus usuarios, y te lo tendrás merecido.
Mi respuesta es que no tiene por qué ser todo o nada. La clave está en quién puede llegar al renderizador. Un renderizador que solo pueden activar los miembros autenticados de un proyecto es un fallo esperando a alguien de dentro. Un renderizador que cualquier cliente de la red puede activar sin iniciar sesión es un fallo esperando a todo internet, y eso es exactamente lo que te dicen el AV:N y el PR:N de la cadena del vector. Los formatos minoritarios en rutas públicas y sin autenticación deberían activarse de forma explícita en cada instancia, y deberían aparecer como una línea en el panel de administración que puedas desactivar. Hoy por hoy son una propiedad emergente del árbol de dependencias. Las pautas de detección dejan claro el coste: un crash nativo [BUG] con frames como onig_compile o match_at es el desenlace ruidoso, y GitLab dice sin rodeos que un exploit exitoso puede ser silencioso. No hay monitorización que te salve de un camino que no sabías que existía.
Ahora dale la vuelta y apúntalo a nuestro propio código, porque las apps PHP están llenas del mismo patrón. Construimos patrones PCRE a partir de la entrada del usuario en filtros de búsqueda, helpers de resaltado y tablas de rutas. Distribuimos parsers de BBCode y Markdown, extensiones de sintaxis wiki y previsualizadores de «pega lo que quieras», a menudo en páginas que no piden iniciar sesión. PHP te da unas protecciones decentes: existe preg_quote, existe pcre.backtrack_limit y el motor lleva años de endurecimiento. Pero las protecciones solo sirven en los caminos de código que alguien recuerda que están ahí. Me apostaría un buen café a que la mayoría de los proyectos maduros en Laravel o Symfony tienen al menos un endpoint público cuyo pipeline de renderizado no ha leído nadie del equipo actual.
Así que sí, primero parchea, conserva los logs de Workhorse y Sidekiq antes de lanzarte a reiniciar con demasiado entusiasmo, y rota los tokens si la instancia estuvo expuesta y algo en el registro de auditoría no cuadra. Después dedica una tarde a la tarea menos vistosa: haz una lista de cada formato y cada regex influida por el usuario que tus sistemas procesan para alguien que no se ha autenticado, y pregúntate si cada uno se gana su sitio. Escribir la lista es rápido. Borrar entradas es donde empieza la verdadera discusión.
Y eso me lleva a lo que me gustaría que me contaras. La última vez que auditaste una herramienta autoalojada o tu propia app, ¿encontraste algún renderizador o parser expuesto al tráfico anónimo cuya necesidad nadie supiera explicar? Y cuando propusiste desactivarlo, ¿quién se opuso y tenía razón?




Comentarios
Aún no hay comentarios — escribe el primero.
Inicia la conversación
Sin cuenta ni contraseña — introduce tu correo y te enviamos un enlace de acceso de un solo uso. ¿Primera vez? Todo se configura automáticamente.
Tu valoración se aplicará automáticamente al iniciar sesión.
Revisa tu bandeja de entrada
Hemos enviado un enlace de acceso a …. Ábrelo en este dispositivo — esta pestaña te conectará automáticamente.
¿No llega nada? Mira en la carpeta de spam — y marca el correo como «No es spam» para que la próxima vez llegue directo.