Informe de incidente de seguridad: Compromiso de acción de GitHub xygeni-action

Resumen Ejecutivo

El 3 de marzo de 2026, Xygeni detectó actividad sospechosa que afectaba al repositorio utilizado para publicar la acción de GitHub xygeni/xygeni-action. Dicha actividad se originó a partir de credenciales comprometidas asociadas a un token de mantenedor y a una aplicación de GitHub instalada en el repositorio.

Durante el incidente, un atacante intentó introducir código malicioso en el repositorio a través de una serie de pull requestsEstos intentos fueron bloqueados por las reglas de protección de ramas existentes, lo que impidió que el código se fusionara con la rama principal del repositorio.

Sin embargo, el atacante posteriormente explotó un vector separado moviendo la etiqueta mutable v5 para que hiciera referencia a un elemento malicioso. commit creado durante el pull request intentos. Por lo tanto, los flujos de trabajo que hacen referencia a xygeni/xygeni-action@v5 podrían recuperar el código comprometido sin ningún cambio visible en sus definiciones de flujo de trabajo.

La manipulación de la etiqueta se detectó el 9 de marzo tras informes de la comunidad. La etiqueta comprometida se retiró de inmediato y se iniciaron los procedimientos de respuesta ante incidentes.

Nuestra investigación determinó lo siguiente:

  • No se ha incorporado ningún código malicioso a la rama principal del repositorio.
  • Hay No hay evidencia de vulneración de la plataforma SaaS de Xygeni. o datos del cliente.
  • La ventana de exposición se limitó a flujos de trabajo que hacen referencia a xygeni/xygeni-action@v5 entre 3 y 9 de marzo de 2026.
  • La etiqueta comprometida se ha eliminado de forma permanente y no se volverá a crear.

Tras el descubrimiento de la manipulación de etiquetas, Xygeni implementó múltiples mejoras de seguridad en sus repositorios y procesos de lanzamiento, entre las que se incluyen:

  • Eliminación de la etiqueta comprometida y guía de migración a Referencias fijadas con SHA.
  • Cumplimiento de liberación inmutabilidad a través de repositorios.
  • Refuerzo de los permisos del repositorio y del acceso de los colaboradores.
  • Obligatorio firmado criptográficamente commits Para los encargados del mantenimiento.
  • Restricción del acceso de escritura a un grupo limitado de mantenedores y administradores.

Publicamos este informe para brindar transparencia sobre el incidente, compartir las lecciones aprendidas y ayudar a fortalecer las prácticas de seguridad en todo el ecosistema de GitHub Actions.

Si bien el ataque aprovechó una vulnerabilidad conocida de GitHub Actions relacionada con etiquetas mutables, el incidente también destaca la importancia de una protección integral del repositorio, una gestión estricta de las credenciales y una defensa en profundidad. CI/CD .

La transparencia y la colaboración son esenciales para mejorar la resiliencia de la cadena de suministro de software.

Resumen del incidente

Este informe documenta la investigación de un incidente de seguridad que afecta al público. xygeni/acción xygeni Repositorio de GitHub Actions.

El 3 de marzo de 2026, un atacante utilizó credenciales comprometidas asociadas con la automatización del repositorio para introducir código malicioso a través de una serie de pull request intentos. La carga útil contenía un implante de comando y control disfrazado de telemetría de versión de escáner.

Las reglas de protección de la rama del repositorio impidieron con éxito que el código malicioso se fusionara con el repositorio. rama principalSin embargo, el atacante manipuló posteriormente el mutable v5 , redirigiéndolo a un commit que contiene la carga útil inyectada. Debido a que muchos flujos de trabajo hacen referencia a GitHub Actions usando etiquetas de versión principal, esto envenenamiento por etiquetas flujos de trabajo descendentes permitidos que hacen referencia a xygeni/xygeni-action@v5 para recuperar el código comprometido sin ningún cambio visible en la configuración de su flujo de trabajo.

Como proveedor de software supply chain security estampaciónXygeni opera una infraestructura que se integra directamente en el desarrollo. pipelines y CI/CD entornos. Los proyectos en este ámbito son objetivos frecuentes de ataques que buscan comprometer las herramientas de desarrollo ampliamente utilizadas para llegar a entornos posteriores.

Cronograma

Fase 1: El Malicioso Pull Requests (3 de marzo, 10:22–10:50 UTC)

A las 10:22 UTC del 3 de marzo de 2026, un atacante inició un ataque rápido y coordinado contra el repositorio xygeni-action utilizando dos identidades comprometidas: el token de acceso personal (PAT) de un mantenedor y la clave privada de una aplicación de GitHub (xygeni-onboarding-app-dev). Durante los siguientes 28 minutos, tres pull requests Se crearon y cerraron, inyectando cada uno código shell ofuscado en action.yml.

El enfoque del atacante fue metódico y adaptable:

  • PR # 46 (10:22–10:29 UTC): Creado por el mantenedor comprometido PAT bajo la rama feat/telemetría del escánerEl atacante intentó fusionar las ramas, pero las reglas de protección de ramas lo bloquearon. La solicitud de extracción se cerró sin fusión.
  • Reconocimiento (10:39–10:40 UTC): El atacante probó el acceso a la aplicación GitHub creando e inmediatamente eliminando una rama llamada acceso a la aplicación de pruebaEsto confirmó que la aplicación tenía acceso de escritura al repositorio.
  • PR # 47 (10:41–10:44 UTC): Un segundo intento utilizando el PAT del mantenedor, ahora bajo una rama renombrada. mejora/telemetría del escánerNuevamente bloqueado por la protección de ramas. El atacante intentó usar la aplicación de GitHub para aprobar la solicitud de extracción (PR), eludiendo el requisito de dos revisores al hacer que una identidad comprometida aprobara el trabajo de la otra. Esto también falló.
  • PR # 48 (10:45–10:49 UTC): Los roles se intercambiaron: la aplicación GitHub creó la PR (push) commit 4bf1d4e), y el mantenedor PAT envió la revisión de aprobación. Esto también fue rechazado por la protección de la rama.

Ninguna de las solicitudes de extracción llegó a la rama principal. Nuestras reglas de protección de ramas se mantuvieron: el requisito de dos aprobaciones, la regla de que el último envío debe ser aprobado por alguien que no sea quien lo envió, y la restricción para eludir estas configuraciones, todo ello combinado para bloquear cualquier intento de fusión.

Nuestro equipo detectó la actividad anómala durante la revisión rutinaria de solicitudes de extracción e inició una respuesta a incidentes a las 12:21 UTC, menos de dos horas después de la primera solicitud de extracción maliciosa. La respuesta incluyó la eliminación de flujos de trabajo, la conservación del código malicioso para análisis forense y la protección del repositorio.

Fase 2: El envenenamiento de la etiqueta

Aunque la protección de ramas impidió con éxito que el código malicioso llegara a la rama principal, el atacante aprovechó un vector separado. Utilizando las credenciales de la aplicación GitHub comprometidas, el atacante movió la etiqueta mutable v5 para que apuntara a commit 4bf1d4e — el malicioso commit del PR #48 que aún existía en el almacén de objetos del repositorio incluso después de que se eliminara la rama del PR.

Es fundamental destacar que esta manipulación de etiquetas no se produjo inmediatamente después de las solicitudes de extracción (PR). Los registros de actividad del repositorio de GitHub no muestran los eventos de envío forzado de etiquetas del mismo modo que las operaciones de rama, lo que limita la posibilidad de reconstruir la marca de tiempo exacta de la modificación de la etiqueta. Sin embargo, se confirmó que la etiqueta había sido manipulada cuando la comunidad dio la voz de alarma el 9 de marzo.

Esta es la clave: las reglas de protección de ramas no protegen las etiquetas. commit El archivo que contenía la puerta trasera se encontraba en la base de datos de objetos Git del repositorio, y la etiqueta v5 —a la que hacían referencia los flujos de trabajo posteriores— podía redirigirse silenciosamente a él. Cualquier flujo de trabajo que utilizara xygeni/xygeni-action@v5 descargaría el código comprometido, sin que se observara ningún cambio en la rama principal ni en los archivos de flujo de trabajo de los repositorios que lo consumían.

Causa principal

Nuestra investigación concluyó que la causa principal fue la vulneración de la clave privada de una aplicación de GitHub (xygeni-onboarding-app-dev) que había sido instalada en el repositorio.

Esta aplicación de GitHub se creó originalmente para probar la experiencia de incorporación en la plataforma de Xygeni. Tenía permisos de escritura en el repositorio, permisos que, en retrospectiva, eran más amplios de lo necesario para su propósito original.

Con la clave privada de una aplicación de GitHub, un atacante puede:

  • Generar tokens de instalación de corta duración a voluntad
  • Crear y aprobar pull requests
  • Push commits a través de Git por HTTPS
  • Mover las etiquetas: la acción crucial que hizo que este incidente tuviera un gran impacto.

El atacante utilizó tanto la clave PAT del mantenedor comprometida como las credenciales de la aplicación de GitHub en un intento coordinado: cuando una identidad no podía eludir las protecciones por sí sola, se utilizaron ambas identidades en conjunto: una para crear y la otra para aprobar.

Aún se está investigando el método exacto por el cual se extrajo la clave privada. Las claves privadas de las aplicaciones de GitHub (archivos .pem) pueden filtrarse debido a flujos de trabajo mal configurados, equipos de desarrolladores comprometidos o almacenamiento inseguro en Secreto.

Comportamiento de carga útil maliciosa

El código inyectado era un implante compacto de comando y control. Fue diseñado para ejecutarse silenciosamente junto con el escáner legítimo, en tres fases:

  • Registro. El implante se comunica con un servidor C2 en 91.214.78.178 (disfrazado mediante DNS comodín de nip.io como security-verify.91.214.78.178.nip.io), enviando el nombre de host, el nombre de usuario y la versión del sistema operativo del corredor.
  • Bucle de sondeo. Durante 180 segundos (dentro de los tiempos de espera típicos de las tareas de CI), el implante sondea al servidor C2 cada 2-7 segundos en busca de comandos para ejecutar.
  • Ejecución de comandos. Los comandos recibidos se ejecutan mediante eval, con la salida comprimida (zlib), codificada en base64 y reenviada al servidor C2.

Las variables se introdujeron en silencio, sus nombres fueron deliberadamente concisos y el intervalo de sondeo se aleatorizó para evitar la detección de patrones de tráfico.

Si el implante se hubiera ejecutado en un ejecutor de CI, el atacante habría tenido acceso al token de GitHub, a Secretos del repositorio, al código fuente y, potencialmente, a las claves de firma de artefactos. El implante podría haber permitido la ejecución de comandos en un ejecutor de CI si se hubiera ejecutado dentro de un flujo de trabajo que hiciera referencia a la etiqueta comprometida.

En este momento, tenemos No hay evidencia de que la carga útil se haya ejecutado en ningún entorno de CI del cliente. o que los Secretos fueron exfiltrados a través de la acción.

Infraestructura C2

El servidor C2 estaba alojado en Partner Hosting LTD (AS215826), registrado en 71-75 Shelton Street, Covent Garden, Londres, una dirección de oficina virtual de uso común. La infraestructura se había aprovisionado recientemente (la subred se modificó por última vez solo 5 días antes del ataque) y la IP ya estaba asociada con RAT, ladrones de información y cargadores en las fuentes de inteligencia de amenazas. La infraestructura y las herramientas indican que un atacante capaz y familiarizado con CI/CD .

Asesoramiento de exposición

Observaciones clave

Las etiquetas mutables son un riesgo conocido, pero la inercia es poderosa.

El ecosistema de GitHub Actions tiene un problema bien documentado: las etiquetas mutables. Cuando los usuarios hacen referencia a action@v5, confían en que la etiqueta apunta a código seguro. Sin embargo, cualquier persona con permisos de escritura puede modificar las etiquetas de forma forzada. Este es el principal vector de ataque en la cadena de suministro de GitHub Actions, y lo sabíamos; aun así, nuestra documentación seguía recomendando a los usuarios usar @v5.

La protección de ramas no es protección de etiquetas.

Nuestras reglas de protección de ramas funcionaron exactamente como se esperaba. Impidieron que el código malicioso se fusionara con main. Pero el atacante no necesitaba fusionar, solo necesitaba una commit en el repositorio (que proporciona cualquier rama de PR) y la capacidad de mover una etiqueta. La protección de la rama nos dio una falsa sensación de seguridad integral.

Las nuevas funciones no ofrecen protección retroactiva.

GitHub introdujo liberación inmutabilidad En octubre de 2025, se implementará una función que impide la modificación de las etiquetas asociadas a las versiones. Ya lo teníamos en cuenta, pero no habíamos comprendido del todo sus implicaciones:

  • Solo protege las etiquetas asociadas a las versiones de GitHub, no las etiquetas independientes.
  • No ofrece protección retroactiva: las versiones existentes creadas antes de habilitar la función siguen siendo modificables.
  • Las reglas de protección de etiquetas (una función independiente) deben configurarse por separado.

Si hubiéramos habilitado la inmutabilidad de la versión y nos hubiéramos asegurado de que la etiqueta v5 estuviera asociada a una versión protegida, el envenenamiento de etiquetas habría fallado.

Ámbitos de aplicación de GitHub excesivamente permisivos

La aplicación de GitHub tenía permisos de escritura que excedían sus necesidades operativas. En una organización compleja con múltiples aplicaciones, bots e integraciones, es fácil que se acumulen permisos innecesarios. Cada permiso adicional representa una mayor vulnerabilidad.

Correcciones al registro público

El informe de los investigadores fue fundamental para alertar a la comunidad, y agradecemos su rápida respuesta. Sin embargo, nuestra investigación interna reveló algunos detalles que difieren de su relato:

  • Cronología del envenenamiento por etiquetasEl informe del investigador sitúa el cambio de etiqueta v5 aproximadamente a las 10:49 UTC del 3 de marzo, inmediatamente después de que se cerraran las solicitudes de extracción. Nuestra investigación no pudo confirmar esta hora, ya que los eventos de envío forzado de etiquetas no se registran en el registro de actividad del repositorio de GitHub. Lo que sí sabemos es que la etiqueta fue manipulada en algún momento después del ataque malicioso. commit fue creado antes de que la comunidad lo descubriera el 9 de marzo.
  • La commit no estaba “firmado con el correo electrónico de un mantenedor”. El informe del investigador describe el primer ataque malicioso commit como “firmado con la dirección de correo electrónico de un mantenedor”, pero esto confunde los metadatos del autor de Git con la firma criptográfica; son cosas fundamentalmente diferentes. commit No estaba firmado criptográficamente. El atacante simplemente estableció el campo de autor de Git con el correo electrónico de otro mantenedor, algo que cualquiera puede hacer, ya que los metadatos del autor de Git son autoinformados y no autenticados. commit Se realizó un envío utilizando el PAT del mantenedor comprometido; el mantenedor cuyo correo electrónico se utilizó no se vio comprometido y solo aparece en el registro de actividad del repositorio a partir de las 12:21 UTC como parte del equipo de respuesta a incidentes.
  • Las identidades involucradasEl investigador describió la identidad del mantenedor y el bot de la aplicación GitHub como evidencia de «credenciales robadas en lugar de una acción interna». Podemos confirmar que la clave PAT clásica de un mantenedor y la clave privada de la aplicación GitHub se vieron comprometidas. Ambas fueron utilizadas por el mismo atacante externo. La solicitud de extracción n.° 48 aparece bajo el usuario fantasma porque fue creada por la instalación de la aplicación GitHub, no por una cuenta humana eliminada.
  • El número de repositorios afectadosEl informe del investigador hacía referencia a más de 137 repositorios que utilizaban @v5. Nuestra revisión de los resultados de la búsqueda de código de GitHub no confirmó esa cifra. En el momento de nuestro último análisis, no encontramos repositorios públicos que utilizaran activamente xygeni/xygeni-action@v5 en flujos de trabajo ejecutables. Las referencias identificadas correspondían a ejemplos de documentación dentro de los repositorios de Xygeni, que desde entonces se han actualizado. En la práctica, la mayoría de los clientes utilizan la descarga del escáner basada en CLI y la función Managed Scan de Xygeni, que invoca internamente la acción y utiliza una versión con SHA fijado y validada internamente que no se ve afectada por la manipulación de etiquetas. Dado que la búsqueda de código de GitHub solo indexa repositorios públicos, no podemos determinar con un 100 % de certeza si los repositorios privados pueden haber hecho referencia a la etiqueta. Según la información disponible, la exposición real posterior parece ser significativamente menor que la informada inicialmente.

[Actualizaremos esta sección una vez que concluya nuestra investigación.]

Acciones de respuesta

Respuesta inmediata (3 de marzo)

  • Las solicitudes de extracción maliciosas fueron señaladas y bloqueadas (la protección de la rama impidió la fusión).
  • Se extrajo el código malicioso y se conservó para su análisis forense.
  • Dominio C2 e IP registrados como indicadores de compromiso.
  • La aplicación de GitHub comprometida (xygeni-onboarding-app-dev) fue eliminada del repositorio.
  • Todos los PAT contribuyentes fueron rotados.
  • Se revisaron los registros de auditoría del repositorio; no se encontraron evidencias de fusiones no autorizadas previas.

Guía de remediación

Remediación (9 y 10 de marzo)

  • Se eliminó la etiqueta v5 comprometida.
  • Liberar inmutabilidad Se habilitó para el repositorio y se aplicó globalmente en todos los repositorios propiedad de Xygeni.
  • Se endurecieron las normas de protección de sucursales, incluyendo la firma obligatoria commits (Xygeni utiliza hardware respaldado commit firma)
  • La etiqueta v5 no se recreó intencionadamente para dejar claro que había sido comprometida y para fomentar la migración a referencias con SHA.
  • La documentación se actualizó para hacer referencia a la versión completa. commit SHA (13c6ed2797df7d85749864e2cbcf09c893f43b23) correspondiente a v6.4.0
  • GitHub Actions se deshabilitó temporalmente en el repositorio como medida de precaución.
  • Los permisos de escritura estaban restringidos: solo dos mantenedores designados y dos administradores del repositorio conservan el acceso de escritura.

Para usuarios de xygeni-action

Si estabas usando xygeni/xygeni-action@v5, deberías:

  • Actualizar inmediatamente tu flujo de trabajo para fijarlo a la caja fuerte commit SHA:

uses: xygeni/xygeni-action@13c6ed2797df7d85749864e2cbcf09c893f43b23

  • Audita tus registros de CI para cualquier conexión saliente a 91.214.78.178 o security-verify.91.214.78.178.nip.io durante el período comprendido entre el 3 y el 9 de marzo de 2026.
  • Gira cualquier Secretos que estuvieron expuestos a corredores de CI durante ese período.
  • Como alternativa, puede utilizar un Descarga y verificación directa del escáner

Por qué no lo revelamos públicamente el 3 de marzo

Esta es una pregunta a la que debemos dar una respuesta honesta.

El 3 de marzo, cuando nuestro equipo respondió a las solicitudes de extracción maliciosas, se determinó que el ataque se había contenido por completo en la etapa de solicitud de extracción. Las reglas de protección de ramas se mantuvieron. No se había fusionado código malicioso con la rama principal. Ningún ejecutor de integración continua había ejecutado la carga útil. Se rotó el PAT comprometido, se eliminó la aplicación de GitHub y los registros de auditoría del repositorio no mostraron evidencia de fusiones no autorizadas previas. El incidente se clasificó como de gravedad media (P2): un intento de intrusión bloqueado.

Según esta evaluación, no se consideró necesaria ninguna divulgación pública. En retrospectiva, dicha evaluación fue incompleta.

Lo que pasamos por alto fue el envenenamiento de etiquetas. La etiqueta v5 se había movido silenciosamente para apuntar al elemento malicioso. commit, pero esto no era visible en las mismas superficies de auditoría que estábamos revisando. Los registros de actividad del repositorio de GitHub muestran los cambios de etiquetas de manera diferente a las operaciones de rama, lo que hizo que la modificación fuera menos visible durante la investigación inicial. Nuestra respuesta al incidente se centró en el vector de ataque visible: el pull requests y la rama principal, y no se comprobó si las etiquetas habían sido manipuladas.

En retrospectiva, esta es una de las lecciones clave de este incidente: no se puede revelar lo que se desconoce. Nuestra respuesta el 3 de marzo fue rápida y eficaz contra la amenaza que pudimos detectar. Pero el atacante tenía una segunda vía de ataque, más sigilosa, que pasó desapercibida durante seis días, hasta que la comunidad la descubrió.

Divulgación pública (9 de marzo)

El 9 de marzo de 2026, los miembros de la comunidad abrieron un problema #54, cuestionando el código malicioso y la etiqueta v5 comprometida. Los investigadores publicaron un análisis detallado que ayudó a generar conciencia en todo el ecosistema.

Queremos reconocer la labor del investigador al difundir la alerta y proporcionar orientación práctica a los usuarios afectados. Asimismo, deseamos aclarar ciertos detalles de su informe en los que nuestra investigación interna llegó a conclusiones diferentes; abordamos estas cuestiones en la sección de Correcciones.

Lecciones para el ecosistema

  • Fijar acciones por SHA, no por etiquetaLas etiquetas mutables son la mayor superficie de ataque en el ecosistema de GitHub Actions. acción@ en todos los flujos de trabajo de producción.
  • Comprenda los límites de cada función de seguridad.La protección de ramas protege las ramas. La protección de etiquetas protege las etiquetas. La inmutabilidad de las versiones protege las versiones. No son intercambiables, y las brechas entre ellas son precisamente donde operan los atacantes.
  • Auditar los permisos de la aplicación de GitHub sin deescaneosoCada aplicación instalada con permisos de escritura es un posible vector de movimiento lateral. Aplique el principio de mínimo privilegio, rote las claves y revise periódicamente qué aplicaciones están instaladas en repositorios críticos.
  • Trate a los ejecutores de CI como entornos hostiles.La monitorización de la salida de red, los ejecutores efímeros y el aislamiento de Secretos no son opcionales para los repositorios en la cadena de suministro de software.
  • Las nuevas funciones de seguridad requieren una adopción proactiva.La inmutabilidad de las versiones de GitHub estuvo disponible durante meses antes de este incidente. Las funciones que no están habilitadas no brindan protección; la seguridad no es algo que se dé por sentado.
  • No firmado commitpueden tener identidades falsificadasGit commit autor y commitLos campos ter son autoinformados: cualquiera puede establecerlos en cualquier valor. Sin criptografía commit firma (GPG, SSH o S/MIME), no hay garantía de que una commit En realidad, fue escrito por la persona que dice ser. En este incidente, el atacante estableció el autor del primer archivo malicioso. commit a la dirección de correo electrónico de otro mantenedor, creando una atribución falsa. Requiere firma commitLas reglas de protección de ramas eliminan este vector.
  • La complejidad aumenta la superficie de ataque.La interacción entre las PAT, las aplicaciones de GitHub, las reglas de protección de ramas, la semántica de las etiquetas y la inmutabilidad de las versiones creó un entorno donde el atacante encontró puntos débiles que ninguna de estas características cubría individualmente. Simplifique siempre que sea posible. Comprenda el modelo de amenazas completo, incluso cuando no pueda hacerlo.

Indicadores de compromiso (IOC)

Tipo Valor
Dirección IP91.214.78.178
Dominio C2verificación-de-seguridad.91.214.78.178.nip.io
Puntos finales C2/b/in (registro), /b/q (asignación de tareas), /b/r (exfiltración)
Encabezado de autorizaciónXB: sL5x#9kR!vQ2$mN7
ASNAS215826 (Partner Hosting LTD)
Servernginx/1.18.0 (Ubuntu)
TLSCertificado autofirmado

AGRADECIMIENTOS

Agradecemos a los investigadores de seguridad y a los miembros de la comunidad que informaron sobre este problema, incluidos los colaboradores del problema. #54 y a los investigadores por sus análisis públicos. La transparencia y la colaboración son la clave para lograr que la cadena de suministro de software sea más resiliente para todos.

Como titular de software supply chain security Como empresa, reconocemos que los proyectos en este ámbito son objetivos atractivos. Lo que importa es cómo respondemos: con transparencia, con rigor y con la humildad de aprender de nuestros propios puntos ciegos. Nos exigimos lo mismo. standard lo establecemos para nuestros clientes
sca-tools-software-herramientas-de-analisis-de-composicion
Priorice, solucione y proteja sus riesgos de software
Además, te ofrecemos una prueba gratuita de 7 días de nuestra Business Edition para que puedas explorar las funciones avanzadas de la plataforma SecurityScorecard.
No se requiere tarjeta de crédito

Asegure el desarrollo y entrega de software

con la suite de productos Xygeni