Marcos Ramírez BETA
Servidor con señales de advertencia de ataque a la cadena de suministro de npm, tema ciberseguridad oscuro

Análisis: Ataque a TanStack, por qué pnpm es más seguro que npm

· ⏱ 9+ min lectura

El 11 de mayo de 2026, la comunidad de desarrollo JavaScript recibió una noticia inquietante: un atacante había logrado publicar 84 versiones maliciosas en 42 paquetes del ecosistema TanStack. El incidente, documentado oficialmente como CVE-2026-45321 y clasificado como severity Critical por el National Vulnerability Database, demostró cómo tres vulnerabilidades conocidas podían encadenarse para comprometer una de las cadenas de suministro de software más utilizadas del ecosistema JavaScript.

El ataque no fue detectado internamente por TanStack. Fue un investigador externo, ashishkurmi de StepSecurity, quien advierte sobre las versiones maliciosas aproximadamente 20 minutos después de su publicación. Este detalle es crucial: la ventana de exposición existiría durante al menos 20 minutos, tiempo más que suficiente para que miles de desarrolladores ejecutaran npm install y acumularan credenciales comprometidas en sus sistemas.

Las tres vulnerabilidades que hicieron posible el ataque

Para comprender el verdadero alcance de este incidente, hay que analizar cómo el atacante logró ejecutar su plan. No se trató de un exploit aislado, sino de una cadena cuidadosamente construida que aprovechaba debilidades conocidas pero raramente protegidas.

1. El patrón pull_request_target

La primera vulnerabilidad reside en la configuración de GitHub Actions. TanStack utilizaba el disparador pull_request_target en su workflow de bundle-size, un patrón conocido como “Pwn Request” que permite a Pull Requests procedentes de forks ejecutar código con acceso al repositorio base. Cuando el atacante abrió un Pull Request desde su fork modificado, el workflow ejecutó código controlado por el atacante en el contexto de la organización TanStack.

Este patrón es especialmente peligroso porque pull_request_target ejecuta el código del fork con los permisos del repositorio base, incluyendo acceso al caché de GitHub Actions. Los desarrolladores a menudo creen que mitigan el riesgo usando pull_request en lugar de pull_request_target, pero en este caso, el workflow utilizaba el primero precisamente para acceder a información del repositorio base.

2. Poisoning del caché de GitHub Actions

La segunda vulnerabilidad explotaba el sistema de caché compartido de GitHub Actions. El atacante logró inyectar código malicioso en el caché de pnpm que sería restaurado posteriormente por el workflow de publicación. Este técnica, documentada por Adnan Khan en 2024, permite que código ejecutado en un contexto de Pull Request pueda persistir y ejecutarse en contextos de mayor confianza como el pipeline de release.

El atacante específicamente diseñó su payload para escribir en el directorio pnpm-store bajo una clave que el workflow legítimo de release calcularía y buscaría: Linux-pnpm-store-${hashFiles('**/pnpm-lock.yaml')}. Cuando el job de benchmark-pr terminó, actions/cache@v5 guardó el caché envenenado con esa clave exacta. Cuando release.yml se ejecutó posteriormente, restauró el caché comprometido junto con todo el código malicioso que contenía.

3. Extracción del token OIDC de la memoria del runner

La tercera vulnerabilidad fue la más sofisticada: la extracción del token OIDC directamente de la memoria del runner de GitHub Actions. El workflow de publicación de TanStack declaraba id-token: write para usar OIDC trusted publishing con npm. Este permiso permite al workflow obtener un token de acceso mediante el protocolo OIDC.

El problema es que cuando el runner de GitHub Actions levanta el proceso Worker, el token OIDC se almacena en memoria como variable de entorno. El malware del atacante podía localizar el proceso del runner mediante /proc/*/cmdline, leer su memoria a través de /proc/*/mem, y extraer el token OIDC. Con ese token, el atacante podía autenticarse directamente en registry.npmjs.org, suplantando como el repositorio TanStack sin necesidad de robar tokens npm explícitos.

Este técnica exacta fue usada previamente en la compromisión de tj-actions/changed-files en marzo de 2025, demostrando que los atacantes reutilizan técnicas probadas en lugar de desarrollar zero-days.

Qué hacía el malware publicado

Una vez publicadas las 84 versiones maliciosas, cualquier desarrollador que ejecutara npm install, pnpm install o yarn install en un proyecto que dependiera de los paquetes afectados estaba expuesto. El malware usaba optionalDependencies para ejecutar código durante la fase de instalación, específicamente un script prepare que ejecutaba un archivo JavaScript ofuscado de 2.3 MB llamado router_init.js.

Las capacidades del malware eran alarmantemente completas:

  • Recolección de credenciales: Buscaba en AWS IMDS y Secrets Manager, GCP metadata, tokens de cuentas de servicio de Kubernetes, tokens de Vault, ~/.npmrc, tokens de GitHub (variables de entorno, gh CLI, .git-credentials), y claves SSH privadas.

  • Exfiltración de datos: Enviaba toda la información recopilada a través de la red Session/Oxen messenger file-upload (filev2.getsession.org, seed3.getsession.org). Esta red proporciona cifrado de extremo a extremo sin servidor de comando y control controlable, lo que significa que bloquear por IP o dominio era la única mitigación de red disponible.

  • Auto-propagación: El malware enumeraba otros paquetes mantenidos por la víctima mediante registry.npmjs.org/-/v1/search?text=maintainer:<user> y los republicaba con la misma inyección, creando un efecto de propagación automática que podía comprometer maintainers adicionales.

La recomendación oficial de seguridad fue rotar inmediatamente todas las credenciales: tokens npm, tokens de GitHub, credenciales AWS, tokens de Vault, tokens de Kubernetes, y claves SSH.

Por qué npm requiere configuración manual de seguridad

Este incidente pone de manifiesto una diferencia fundamental entre npm y pnpm en cuanto a su postura de seguridad por defecto.

En npm, la seguridad de la cadena de suministro no viene habilitada de serie. Los desarrolladores que quieren protegerse deben configurar manualmente opciones como:

  • npm audit para detectar vulnerabilidades conocidas, aunque no detecta malware nuevo
  • --ignore-scripts para evitar la ejecución de scripts durante la instalación
  • --ignore-scripts en package.json para bloquear scripts a nivel de proyecto
  • Revisar manualmente optionalDependencies de cada paquete instalado

El problema es que ninguna de estas configuraciones es el comportamiento por defecto. Un desarrollador que instala un paquete nuevo espera que sea seguro, y la mayoría no revisa el package.json de cada dependencia transitiva. Las configuraciones de seguridad en npm son reactivas: dependen de que el desarrollador sepa qué buscar y tome medidas activas.

La realidad es que la gran mayoría de proyectos npm en producción no implementan ninguna de estas protecciones. El ecosistema ha construido una cultura de confianza implícita donde ejecutamos npm install sin pensar en las consecuencias.

pnpm: seguridad activa por defecto

pnpm toma un enfoque radicalmente diferente. En lugar de requerir configuración manual, pnpm incluye protecciones de seguridad activas que funcionan de serie, sin que el desarrollador tenga que saber que existen.

Scripts postinstall deshabilitados por defecto

Desde pnpm v10, la ejecución automática de scripts postinstall en dependencias está deshabilitada por defecto. Aunque existe una configuración dangerouslyAllowAllBuilds para re-habilitarla globalmente, la recomendación oficial es usar allowBuilds para listar explícitamente solo las dependencias de confianza. Esto significa que si una dependencia no requería build anteriormente, no va a ejecutar silenciosamente un script malicioso si una versión comprometida se publica.

Esta decisión de diseño es significativa: el vector de ataque más común en comprometimientos de npm ha sido históricamente el uso de scripts postinstall, y pnpm lo neutraliza simplemente cambiándolo del comportamiento por defecto.

Prevenir dependencias exóticas

La configuración blockExoticSubdeps permite bloquear dependencias transitivas que usen fuentes no estándar como repositorios git o URLs directas a tarballs. Esto asegura que todas las dependencias se resuelvan desde fuentes confiables, reduciendo el riesgo de que un atacante introduzca código a través de una dependencia transitiva que apunte a un repositorio controlado por él.

Retrasar actualizaciones de dependencias

Una de las protecciones más elegantes de pnpm es minimumReleaseAge, que por defecto en pnpm v11 retrasa la instalación de nuevas versiones durante 1440 minutos (un día completo). La lógica es simple: el malware suele ser detectado rápidamente, generalmente en cuestión de horas. Si retrasas las actualizaciones por 24 horas, la mayoría de versiones comprometidas serán detectadas y eliminadas del registry antes de que tu proyecto pueda instalarlas.

Esta configuración puede ajustarse: establecer en 0 para desactivar el retraso, o aumentarlo a 10080 minutos (una semana) para mayor protección en entornos de alta seguridad.

Política de confianza

La configuración trustPolicy permite establecer reglas sobre qué nivel de confianza se requiere para instalar versiones de paquetes. Cuando se establece en no-downgrade, pnpm impedirá la instalación de un paquete si su nivel de confianza ha disminuido comparado con versiones anteriores. Por ejemplo, si un paquete fue previamente publicado por un editor confiable con provenance verificado pero ahora solo tiene provenance o ningún indicador de confianza, la instalación será bloqueada.

Esto proporciona una capa adicional de protección contra versiones que podrían haber sido publicadas por actores no autorizados o en circunstancias cuestionables.

Un cambio de paradigma necesario

El ataque a TanStack no fue un evento aislado. Es parte de una tendencia más amplia de campaña activa contra el ecosistema npm, documentada por investigadores de seguridad bajo el nombre “Mini Shai-Hulud” y relacionada con el grupo conocido como TeamPCP. Los ataques a la cadena de suministro de software están siendo cada vez más sofisticados, y los atacantes están explotando la confianza implícita que el ecosistema ha construido durante años.

La diferencia fundamental entre npm y pnpm no es solo técnica: es filosófica. npm asume que los paquetes son seguros hasta que se demuestre lo contrario, requiriendo acción del desarrollador para protegerse. pnpm asume que cualquier paquete podría estar comprometido, y proporciona protecciones automáticas que funcionan sin requerir conocimiento específico del usuario.

Para equipos de desarrollo que mantienen proyectos en producción, la elección del gestor de paquetes tiene implicaciones de seguridad reales. Las configuraciones de seguridad en npm no son difíciles de implementar, pero requieren saber que existen y recordar configurarlas en cada proyecto. Las protecciones de pnpm simplemente funcionan, y el desarrollador puede enfocarse en escribir código en lugar de configurar barreras de seguridad.

Compártelo si te ha resultado útil.

Si lo necesitas a nivel profesional en tu empresa, puedo ayudarte.

Y… rota tus credenciales antes de que alguien lo haga por ti.

Artículos relacionados

Túnel de fibra óptica cifrada conectando un edificio de oficinas con un televisor mostrando catálogos de streaming

VPN: del trabajo remoto al gran negocio de vender miedo

Las VPN nacieron para conectar a los trabajadores con la red de la oficina de forma cifrada. Hoy te las venden a golpe de anuncio en YouTube para ver el catálogo de Netflix de otro país y para meterte miedo con tu propia conexión. Te cuento cómo han pasado de herramienta técnica aburrida a un negocio de miles de millones, quién está realmente detrás de marcas como CyberGhost, y cuándo necesitas una VPN de verdad y cuándo te están vendiendo humo.

08:30 10 min Marcos Ramírez Lucía
Terminal mostrando el gestor de contraseñas pass con una estructura de claves cifradas, sobre un fondo oscuro

Tu gestor de contraseñas perfecto vive en la terminal: pass

¿Y si tu terminal fuese tu gestor de contraseñas? No solo la de Instagram, también la clave de tu base de datos. Y si encima fuese gratis, de código abierto y estuviese hecho por el mismo investigador que creó WireGuard. Eso es pass, el gestor de contraseñas estándar de Unix: minimalista hasta la médula, pero con un montón de extensiones para importar desde casi cualquier servicio que usaras antes, llevar el control de cambios con git, manejar códigos de un solo uso (OTP) y sincronizar con apps de Android, iOS y cualquier escritorio. Aquí te cuento qué es pass, cómo funciona, por qué a tanta gente técnica le encanta y, con honestidad, para quién es y para quién no, porque no es para todo el mundo.

Nómina con cifras tapadas y una balanza entre transparencia salarial y privacidad de datos

Transparencia salarial: ¿la nueva ley choca con tu privacidad?

Esta semana medio internet ha entendido que tus compañeros van a poder ver lo que cobras. No es eso. La Directiva europea de transparencia retributiva llega en 2026 y cambia cosas importantes, pero el derecho que te dan es a conocer medias salariales por sexo, no la nómina de la persona de al lado. Te explico qué dice de verdad la ley, qué cambia para ti y, sobre todo, cómo encaja con el RGPD y tu derecho a la protección de datos. Porque ahí es donde está el conflicto interesante.