El Mini Shai-Hulud ha vuelto. Como ya dije antes, aún no habíamos visto el alcance total del ataque.
La campaña de npm de la que informamos en abril, cuando tenía como objetivo paquetes de SAP, se ha convertido ahora en un ataque de mucho mayor envergadura. Nuestro equipo de malware ha detectado 373 entradas maliciosas de versiones de paquetes en 169 nombres de paquetes de npm.
El objetivo fundamental sigue siendo el mismo: robar credenciales de los equipos de los desarrolladores y de los servidores de CI/CD, para luego utilizarlas con el fin de acceder a más paquetes.
Lo que ha cambiado es la magnitud y la forma de distribución. Esta oleada no parece simplemente el resultado de alguien que publica manualmente versiones maliciosas. El malware está diseñado para ejecutarse dentro de los sistemas de compilación, robar credenciales de acceso a npm y GitHub, y aprovechar vías de publicación de confianza para subir nuevos paquetes comprometidos.
Si has leído nuestra entrada anterior, «Mini Shai-Hulud ataca paquetes npm de SAP con un ladrón de datos secretos basado en Bun», esta es la continuación: la misma idea, pero con un alcance mucho mayor.
Qué Sucedió
TanStack sigue siendo uno de los clústeres más destacados, pero ya no es el único. El conjunto afectado incluye ahora paquetes de @squawk, @tanstack, @uipath, @tallyui, @beproduct, @mistralai, @draftlab, @draftauth, @taskflow-corp, @tolka, y varios paquetes sin ámbito.
Los grupos más grandes de esta campaña son:
@squawk: 87 entradas de versión de paquete@tanstack: 83 entradas de versión de paquete@uipath: 66 entradas de versión de paquete- Paquetes sin ámbito: 39 entradas de paquete y versión
@tallyui: 30 entradas de versiones de paquetes@beproduct: 18 entradas de versiones de paquetes
Esta lista sigue en constante evolución. Lo importante no es solo el número de paquetes, sino dónde se ejecutan. Es probable que estos paquetes se instalen en entornos de desarrollo locales, tareas de integración continua, flujos de trabajo de lanzamiento y sistemas de compilación internos.
Ahí es precisamente donde suelen encontrarse los tokens de npm, los tokens de GitHub, las credenciales de la nube, los tokens de cuentas de servicio de Kubernetes y los secretos de implementación.
Paquetes y versiones afectados
Lista actualizada de paquetes y versiones que nuestro equipo ha identificado:
@tanstack/historial:1.161.9,1.161.12@tanstack/react-router:1.169.5,1.169.8@tanstack/router-core:1.169.5,1.169.8@tanstack/router-utils:1.161.11,1.161.14@tanstack/router-plugin:1.167.38,1.167.41@tanstack/rutas-de-archivos-virtuales:1.161.10,1.161.13@tanstack/router-generator:1.166.45,1.166.48@tanstack/start-server-core:1.167.33,1.167.36@tanstack/start-client-core:1.168.5,1.168.8@tanstack/iniciar-contexto-de-almacenamiento:1.166.38,1.166.41@tanstack/start-plugin-core:1.169.23,1.169.26@tanstack/react-start-server:1.166.55,1.166.58@tanstack/react-start-client:1.166.51,1.166.54@tanstack/start-fn-stubs:1.161.9,1.161.12@tanstack/react-start:1.167.68,1.167.71@tanstack/react-start-rsc:0.0.47,0.0.50@mistralai/mistralai:2.2.2,2.2.3,2.2.4@tanstack/react-router-devtools:1.166.16,1.166.19@tanstack/router-devtools-core:1.167.6,1.167.9@tanstack/router-devtools:1.166.16,1.166.19@tanstack/router-ssr-query-core:1.168.3,1.168.6@tanstack/react-router-ssr-query:1.166.15,1.166.18@tanstack/router-cli:1.166.46,1.166.49@tanstack/zod-adapter:1.166.12,1.166.15@tanstack/eslint-plugin-router:1.161.9@tanstack/router-vite-plugin:1.166.53,1.166.56@tanstack/nitro-v2-vite-plugin:1.154.12,1.154.15@mistralai/mistralai-gcp:1.7.1,1.7.2,1.7.3@tanstack/solid-router:1.169.5,1.169.8@tanstack/solid-start:1.167.65,1.167.68@tanstack/solid-start-client:1.166.50,1.166.53@tanstack/solid-start-server:1.166.54,1.166.57@tanstack/solid-router-devtools:1.166.16,1.166.19@tanstack/iniciar-funciones-del-servidor-estático:1.166.44,1.166.47@tanstack/vue-router:1.169.5,1.169.8@uipath/apollo-react:4.24.5@tanstack/solid-router-ssr-query:1.166.15,1.166.18acción segura:0.8.3,0.8.4@tanstack/valibot-adapter:1.166.12,1.166.15@tanstack/vue-start:1.167.61,1.167.64@uipath/apollo-wind:2.16.2@uipath/cli:1.0.1@tanstack/vue-start-server:1.166.50,1.166.53@squawk/tipos:0.8.2,0.8.3,0.8.4@uipath/rpa-tool:0.9.5@squawk/mcp:0.9.1,0.9.2,0.9.3,0.9.4@tanstack/vue-start-client:1.166.46,1.166.49@squawk/tiempo:0.5.6,0.5.7,0.5.8,0.5.9@squawk/espacio aéreo:0.8.1,0.8.2,0.8.3,0.8.4@squawk/datos-del-registro-de-la-OACI:0.8.4,0.8.5,0.8.6,0.8.7@tanstack/arktype-adapter:1.166.12,1.166.15@squawk/plan de vuelo:0.5.2,0.5.3,0.5.4,0.5.5@squawk/aeropuertos:0.6.2,0.6.3,0.6.4,0.6.5@mesadev/sdk:0.28.3@squawk/geo:0.4.4,0.4.5,0.4.6,0.4.7@mesadev/rest:0.28.3@squawk/datos-del-procedimiento:0.7.3,0.7.4,0.7.5,0.7.6@squawk/datos-de-ayudas-a-la-navegación:0.6.4,0.6.5,0.6.6,0.6.7@squawk/corregir-datos:0.6.4,0.6.5,0.6.6,0.6.7@squawk/ayudas a la navegación:0.4.2,0.4.3,0.4.4,0.4.5@squawk/correcciones:0.3.2,0.3.3,0.3.4,0.3.5@squawk/datos-de-aeropuertos:0.7.4,0.7.5,0.7.6,0.7.7@squawk/datos-de-vías-aéreas:0.5.4,0.5.5,0.5.6,0.5.7@squawk/unidades:0.4.3,0.4.4,0.4.5,0.4.6@squawk/procedimientos:0.5.2,0.5.3,0.5.4,0.5.5@squawk/airways:0.4.2,0.4.3,0.4.4,0.4.5@squawk/registro-icao:0.5.2,0.5.3,0.5.4,0.5.5@uipath/apollo-core:5.9.2@squawk/notams:0.3.6,0.3.7,0.3.8,0.3.9@uipath/sistema de archivos:1.0.1@uipath/solutionpackager-tool-core:0.0.34@squawk/cálculos-de-vuelo:0.5.4,0.5.5,0.5.6,0.5.7@squawk/datos-del-espacio-aéreo:0.5.3,0.5.4,0.5.5,0.5.6@mistralai/mistralai-azure:1.7.1,1.7.2,1.7.3@uipath/herramienta-de-soluciones:1.0.1@tanstack/eslint-plugin-start:0.0.4,0.0.7@uipath/maestro-tool:1.0.1@uipath/codedapp-tool:1.0.1@uipath/agent-tool:1.0.1@draftlab/auth:0.24.1,0.24.2@uipath/orchestrator-tool:1.0.1@uipath/integrationservice-tool:1.0.2@taskflow-corp/cli:0.1.24,0.1.25,0.1.26,0.1.27,0.1.28,0.1.29@tanstack/vue-router-ssr-query:1.166.15,1.166.18@uipath/rpa-legacy-tool:1.0.1@uipath/herramienta-de-soluciones-verticales:1.0.1@uipath/flow-tool:1.0.2@uipath/codedagent-tool:1.0.1@uipath/common:1.0.1@uipath/resource-tool:1.0.1@uipath/auth:1.0.1@uipath/docsai-tool:1.0.1@uipath/case-tool:1.0.1@uipath/api-workflow-tool:1.0.1@tanstack/vue-router-devtools:1.166.16,1.166.19@uipath/test-manager-tool:1.0.2@uipath/robot:1.3.4@uipath/traces-tool:1.0.1@uipath/agent-sdk:1.0.2@uipath/integrationservice-sdk:1.0.2@uipath/maestro-sdk:1.0.1@uipath/data-fabric-tool:1.0.2@mesadev/saguaro:0.4.22@uipath/tasks-tool:1.0.1@uipath/insights-tool:1.0.1@uipath/insights-sdk:1.0.1@uipath/uipath-python-bridge:1.0.1@draftlab/db:0.16.1@uipath/ap-chat:1.5.7@uipath/project-packager:1.1.16@uipath/packager-tool-case:0.0.9@uipath/packager-tool-workflowcompiler-browser:0.0.34@uipath/packager-tool-connector:0.0.19@uipath/packager-tool-workflowcompiler:0.0.16@uipath/packager-tool-webapp:1.0.6@uipath/packager-tool-apiworkflow:0.0.19@uipath/packager-tool-functions:0.1.1ADN-ts:3.0.1,3.0.2,3.0.3,3.0.4@uipath/widget.sdk:1.2.3@uipath/recursos-herramienta:0.1.11@uipath/agent.sdk:0.0.18punto de cruz:1.1.3,1.1.4,1.1.5,1.1.6@uipath/codedagents-tool:0.1.12@uipath/aops-policy-tool:0.3.1@uipath/solution-packager:0.0.35@draftlab/auth-router:0.5.1,0.5.2cmux-agent-mcp:0.1.3,0.1.4,0.1.5,0.1.6,0.1.7,0.1.8agentwork-cli:0.1.4,0.1.5@uipath/packager-tool-bpmn:0.0.9@draftauth/core:0.13.1,0.13.2@dirigible-ai/sdk:0.6.2,0.6.3@uipath/packager-tool-flow:0.0.19Selector de ramas de Git:1.3.3,1.3.4,1.3.5,1.3.6,1.3.7wot-api:0.8.1,0.8.2,0.8.3,0.8.4git-git-git:1.0.8,1.0.9,1.0.10,1.0.11,1.0.12@beproduct/nestjs-auth:0.1.2,0.1.3,0.1.4,0.1.5,0.1.6,0.1.7,0.1.8,0.1.9,0.1.10,0.1.11,0.1.12,0.1.13,0.1.14,0.1.15,0.1.16,0.1.17,0.1.18,0.1.19@ml-toolkit-ts/xgboost:1.0.3,1.0.4nextmove-mcp:0.1.3,0.1.4,0.1.5,0.1.6,0.1.7ml-toolkit-ts:1.0.4,1.0.5@uipath/telemetría:0.0.7@draftauth/cliente:0.2.1,0.2.2@ml-toolkit-ts/preprocesamiento:1.0.2,1.0.3@tallyui/conector-medusa:1.0.1,1.0.2,1.0.3@uipath/tool-workflowcompiler:0.0.12@uipath/vss:0.1.6@tallyui/tema:0.2.1,0.2.2,0.2.3@tallyui/almacenamiento-sqlite:0.2.1,0.2.2,0.2.3@uipath/solutionpackager-sdk:1.0.11@tallyui/connector-vendure:1.0.1,1.0.2,1.0.3@tallyui/core:0.2.1,0.2.2,0.2.3@tallyui/conector-woocommerce:1.0.1,1.0.2,1.0.3@tallyui/componentes:1.0.1,1.0.2,1.0.3@uipath/ui-widgets-carga-de-varios-archivos:1.0.1@tallyui/pos:0.1.1,0.1.2,0.1.3@tallyui/base de datos:1.0.1,1.0.2,1.0.3@supersurkhet/cli:0.0.2,0.0.3,0.0.4,0.0.5,0.0.6,0.0.7@tallyui/conector-shopify:1.0.1,1.0.2,1.0.3@tolka/cli:1.0.2,1.0.3,1.0.4,1.0.5,1.0.6@supersurkhet/sdk:0.0.2,0.0.3,0.0.4,0.0.5,0.0.6,0.0.7@uipath/herramienta-de-políticas-de-acceso:0.3.1@uipath/herramienta-de-contextualización:0.1.1@uipath/herramienta-gubernamental:0.3.1@uipath/admin-tool:0.1.1@uipath/identity-tool:0.1.1@uipath/llmgw-tool:1.0.1@uipath/resourcecatalog-tool:0.1.1@uipath/funciones-herramienta:1.0.1@uipath/access-policy-sdk:0.3.1@uipath/herramienta-de-plataforma:1.0.1
Cómo funciona la nueva ola
En la vulnerabilidad de SAP, los paquetes afectados añadieron un preinstall gancho que se soltó setup.mjs, que a continuación utilizó Bun para ejecutar una gran carga útil ofuscada denominada execution.js.
Esta ola sigue una trayectoria ligeramente diferente.
En los paquetes TanStack comprometidos, el archivo tar del paquete incluye un nuevo archivo ofuscado en el directorio raíz del paquete:
router_init.js
El paquete comprometido también añade una dependencia opcional que apunta a un paquete alojado en GitHub
"optionalDependencies": {
"@tanstack/setup": "github:tanstack/router#79ac49eedf774dd4b0cfa308722bc463cfe5885c"
}Esa dependencia de Git contiene un preparar guion:
"scripts": {
"prepare": "bun run tanstack_runner.js && exit 1"
}Este es el truco. npm ejecuta scripts del ciclo de vida de las dependencias de Git durante la instalación. Así, un paquete que parece una dependencia normal puede acceder discretamente a una dependencia alojada en GitHub y ejecutar su preparar engancharlo y ejecutar la carga útil.
El && salir 1 El final también resulta interesante. Dado que la dependencia es opcional, el hecho de que se produzca un error tras la ejecución de la carga útil puede hacer que la instalación parezca menos sospechosa. El código malicioso ya se ha ejecutado en el momento en que npm considera que la dependencia opcional ha fallado.
Por qué es importante la publicación de confianza en este contexto
Uno de los aspectos más problemáticos de esta actualización es el uso de la publicación de confianza.
La publicación de confianza tiene como objetivo eliminar los tokens de npm de larga duración de los flujos de trabajo de lanzamiento. Un flujo de trabajo de GitHub Actions puede utilizar OIDC para solicitar un token de publicación de npm de corta duración, publicar el paquete y adjuntar la procedencia al lanzamiento.
Eso está bien cuando el flujo de trabajo es claro.
La situación es mucho peor cuando se ejecuta código controlado por el atacante dentro del flujo de trabajo. En ese caso, es posible que el atacante ni siquiera necesite robar un token de npm de larga duración. Puede utilizar los propios permisos OIDC del flujo de trabajo para generar un token de publicación durante la compilación y publicar desde allí.
Esto también significa que la procedencia no es un indicador de seguridad definitivo. Un paquete malicioso puede proceder igualmente del flujo de trabajo de GitHub Actions previsto si dicho flujo de trabajo se utilizó de forma indebida durante el lanzamiento.
En pocas palabras: la procedencia te indica dónde se compiló el paquete. No garantiza que la compilación fuera segura.
Lo que la carga maliciosa intenta robar
La carga útil está diseñada para entornos de CI/CD y de desarrollo.
Busca:
- Tokens de GitHub
- Tokens de npm
- Tokens OIDC de GitHub Actions
- Credenciales de AWS y metadatos de la instancia
- Archivos de cuentas de servicio de Kubernetes
- Tokens de HashiCorp Vault y puntos de conexión locales de Vault
- variables de entorno
- secretos del sistema de archivos local
La carga útil también contiene una lógica de propagación. Tras robar los tokens, intenta utilizarlos para localizar paquetes que la víctima pueda publicar, modificar los archivos de los paquetes, inyectar la dependencia maliciosa, actualizar las versiones y publicar nuevas versiones comprometidas.
Eso es lo que hace que este malware sea algo más que un simple ladrón de información. El malware no solo intenta robarle a la víctima actual, sino que también intenta convertir el acceso de la víctima a la versión liberada en la siguiente vía de infección.
¿Qué ha cambiado tras el ataque a SAP?
La actualización de SAP fue más reducida en cuanto al número de paquetes, pero tuvo un gran impacto, ya que afectó a las herramientas de desarrollo de la empresa.
Esta tendencia es más generalizada. Los paquetes de TanStack se utilizan ampliamente en las aplicaciones modernas de JavaScript, especialmente en el enrutamiento y en las herramientas de React de ciclo completo. Un paquete comprometido en esa parte del árbol de dependencias puede propagarse rápidamente a muchos sitios.
También hay algunos cambios técnicos:
- los paquetes de SAP utilizados
setup.mjsyexecution.js - La nueva versión de TanStack utiliza
router_init.jsy un repositorio alojado en GitHub@tanstack/configuracióndependencia - La nueva tendencia se apoya más en GitHub Actions, OIDC, la publicación en npm y el reempaquetado de paquetes
- la carga útil sigue basándose en Bun y sigue centrada en el robo de información confidencial
Sin embargo, el patrón es siempre el mismo: conseguir ejecución de código durante la instalación, robar credenciales y utilizar esas credenciales para publicar más malware.
Detección y mitigación
Empieza por los archivos de bloqueo y las cachés de paquetes.
Buscar espacios de nombres y paquetes afectados:
@squawk/@tanstack/@uipath/@tallyui/@beproduct/nestjs-auth@mistralai/@draftauth/@draftlab/@taskflow-corp/cli@tolka/cli@ml-toolkit-ts/@mesadev/@dirigible-ai/sdk@supersurkhet/- los paquetes sin ámbito mencionados anteriormente, incluidos
acción segura,ADN-ts,punto de cruz,cmux-agent-mcp,agentwork-cli,Selector de ramas de Git,wot-api,git-git-git,nextmove-mcp, yml-toolkit-ts
Busca los nuevos archivos de carga útil y los marcadores de dependencias:
router_init.jsrouter_runtime.jstanstack_runner.js@tanstack/configuracióngithub:tanstack/router#79ac49eedf774dd4b0cfa308722bc463cfe5885cejecuta tanstack_runner.js
Buscar en los registros de CI:
- ejecución inesperada de Bun durante
npm install - errores en las dependencias opcionales relacionados con
@tanstack/configuración - conexiones salientes durante la instalación de dependencias
- Actividad de publicación en npm desde flujos de trabajo que no deberían haberse publicado
- Solicitudes de tokens OIDC en GitHub Actions durante pasos inesperados
Si se ha ejecutado una versión de un paquete comprometida en un equipo de desarrollo o en un servidor de integración continua, actualiza las claves de acceso de ese entorno. No te limites a los tokens de npm.
Girar o revisar:
- Tokens de npm y acceso para publicar paquetes
- Secretos de GitHub PAT y GitHub Actions
- credenciales de la nube
- Tokens de cuentas de servicio de Kubernetes
- Tokens de Vault
- secretos de implementación
Además, revisa las publicaciones recientes en npm, las ejecuciones de GitHub Actions y los registros de procedencia. Un registro de procedencia válido no debe considerarse una prueba de que el paquete esté libre de problemas.
Indicadores de Compromiso
Archivos y cargas útiles:
router_init.jsrouter_runtime.jstanstack_runner.jsrouter_init.jsSHA-256:ab4fcadaec49c03278063dd269ea5eef82d24f2124a8e15d7b90f2fa8601266ctanstack_runner.jsSHA-256:2ec78d556d696e208927cc503d48e4b5eb56b31abc2870c2ed2e98d6be27fc96
Marcadores de paquetes:
@tanstack/configuracióngithub:tanstack/router#79ac49eedf774dd4b0cfa308722bc463cfe5885cprepararscript en ejecuciónejecuta tanstack_runner.js- archivo de carga útil de nivel raíz incluido fuera del contenido habitual del paquete
Indicadores de red y de servicio:
hxxp://filev2[.]getsession[.]org/file/hxxp://169[.]254[.]169[.]254/latest/meta-data/iam/security-credentials/hxxp://169[.]254[.]170[.]2hxxps://registry[.]npmjs[.]org/-/npm/v1/tokensvault[.]svc[.]cluster[.]local:8200
Marcadores de campaña:
Ha aparecido un mini Shai-Hulud- Nombres de repositorios inspirados en «Dune» utilizados para la salida de «worm» y el entorno de pruebas
Conclusión
Mini Shai-Hulud ha pasado de ser un incidente de menor envergadura centrado en SAP a convertirse en un ataque más amplio a la cadena de suministro de npm.
La lección importante no es solo que se hayan visto comprometidos más paquetes. Es que el malware se basa en el funcionamiento de los sistemas de lanzamiento modernos. Se ejecuta durante la instalación, busca credenciales de CI/CD, se aprovecha de las rutas de publicación de GitHub y npm, e intenta introducirse en el siguiente paquete.
Si alguno de los paquetes afectados se ha ejecutado en tu entorno, considera que el equipo o el ejecutor están expuestos hasta que se hayan renovado los datos confidenciales y se haya revisado la actividad de publicación reciente.
Cómo Aikido lo detecta
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 es usuario de Aikido, puede crear una cuenta y conectar sus repositorios. Nuestra cobertura de malware está incluida en el plan gratuito, sin necesidad de tarjeta de crédito.
Para una cobertura más amplia en todo su equipo, el Endpoint Protection de Aikido le proporciona visibilidad y control sobre los paquetes de software instalados en los dispositivos de su equipo. Cubre extensiones de navegador, librerías de código, plugins de IDE y dependencias de compilación, todo en un solo lugar. Detenga el malware antes de que se instale.
Para protegerte en el futuro, te recomendamos 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 Aikido Intel antes de instalarlos.

