1 puntos por GN⁺ 2025-09-09 | 2 comentarios | Compartir por WhatsApp
  • El 8 de septiembre se detectó la inyección de malware en paquetes populares de npm
  • En total, hubo 18 paquetes afectados, con más de 2 mil millones de descargas por semana a nivel mundial
  • Los atacantes incluyeron código que intercepta en secreto operaciones de criptomonedas y Web3 en el navegador de los visitantes de sitios web, y redirige las aprobaciones y el flujo de fondos de las billeteras hacia cuentas controladas por el atacante
  • Se confirmó que se agregó código JavaScript ofuscado al archivo principal del paquete (index.js)
  • El incidente comenzó al mismo tiempo que la actualización de los paquetes afectados y la comunidad está respondiendo actualmente

Resumen del incidente

  • Al 8 de septiembre a las 13:16 UTC, el feed de monitoreo de seguridad de Aikido detectó la carga en npm de varios paquetes que contenían malware
  • Estos paquetes son muy populares en npm y registran más de 2 mil millones de descargas en una semana

Método y contenido del ataque

  • Tras la actualización maliciosa, se confirmó una estructura en la que malware en JavaScript se ejecuta en secreto en el navegador de los visitantes de sitios web que usan esos paquetes
    • El objetivo de este código es vigilar actividades de criptomonedas y Web3, manipular interacciones con billeteras y cambiar sin autorización las direcciones de destino de pagos
    • Sin cambios visibles en pantalla, los fondos y permisos de aprobación del usuario pueden enviarse a direcciones de criptomonedas designadas por el atacante

Análisis detallado del código malicioso

  • Por ejemplo, en paquetes como is-arrayish, el archivo index.js fue alterado para insertar JavaScript complejo y ofuscado
  • Dentro del código, se utiliza la interfaz window.ethereum para verificar información de cuentas de billetera y pasar por un procedimiento que confirma las condiciones para activar el código atacante
  • Internamente, incluye múltiples direcciones de criptomonedas (Bitcoin, Ethereum, etc.) y lógica de funciones que reemplaza las direcciones de billetera y los detalles de transacciones por direcciones del atacante
  • Esto crea el riesgo de que los activos de criptomonedas de usuarios reales sean filtrados y transferidos sin autorización sin que se den cuenta

Situación actual y respuesta de la comunidad

  • Las versiones maliciosas de los paquetes problemáticos están siendo retiradas rápidamente de los principales repositorios de npm
  • En la comunidad de IT y open source se está avanzando activamente en guías para dejar de usar los paquetes relacionados y actualizarlos, así como en la detección de infecciones adicionales y medidas de respuesta
  • Este hackeo está sirviendo como un fuerte llamado de atención sobre la seguridad de la cadena de suministro de paquetes, la detección de código ofuscado y la protección de extensiones de navegador Web3

2 comentarios

 
crawler 2025-09-09

> 8 de septiembre de 2023,

La fecha salió mal por una alucinación. No es algo de 2023, sino de ahora mismo.
Parece que las noticias de hackeos en npm se escuchan bastante seguido. Se ve que hay un problema.

 
GN⁺ 2025-09-09
Opinión en Hacker News
  • Sí, me hackearon. De verdad me da mucha vergüenza y les pido disculpas a todos. Para más detalles, revisen aquí y aquí. Dejé publicada la lista de paquetes afectados. Parece que este fue un ataque dirigido. Voy a seguir actualizando hasta que se cierre la ventana para editar comentarios. El paquete Chalk ya fue recuperado, pero los demás siguen comprometidos (8, 17:50 CEST). NPM todavía no ha dicho nada. No puedo acceder a mi cuenta de NPM y la recuperación de contraseña tampoco funciona. En este momento no puedo hacer más que esperar. El correo del soporte llegó desde npmjs dot help y se veía muy convincente. No es una excusa, pero era una mañana pesada y, por tratar de sacar aunque fuera una tarea pendiente, cometí el error de hacer clic en el enlace en vez de entrar como siempre directamente al sitio oficial (creo que por estar en el móvil). Este ataque solo afectó a NPM, y voy a seguir publicando actualizaciones en /debug-js. De nuevo, lo siento muchísimo

    • La forma rápida y transparente en que estás respondiendo en una situación tan estresante es realmente ejemplar. Uno cree que ya no caerá en phishing, pero agregaría algunos consejos: 1) nunca inicien sesión desde enlaces en correos. Distinguir entre phishing y correos legítimos es demasiado difícil, así que la única forma de no caer es ni siquiera intentarlo. 2) Si usan una llave de seguridad U2F/Webauthn como segundo factor, la protección contra phishing es casi perfecta. TOTP no ofrece eso. Al final, cualquiera puede equivocarse cuando está cansado o con prisa. Esta vez te tocó a ti. De nuevo, admiro lo bien que lo estás manejando

    • Según indicó sindresorhus, puedes revisar si hay malware en tu árbol de dependencias con este comando: rg -u --max-columns=80 _0x112fa8 (requiere ripgrep, se instala con brew install rg). También vale la pena ver el comentario original

    • Una vez me pasó que caí en phishing cuando estaba borracho en la universidad (aunque fue hace mucho). A cualquiera le puede pasar. Pero sí me sorprende lo lenta que ha sido la respuesta de NPM. Siento que eso termina favoreciendo todavía más al atacante

    • Socket detectó este incidente de inmediato. También lo cubrieron en su blog relacionado. Es lamentable, pero sí hay que reconocer que el ecosistema open source reaccionó muy rápido. Casos así recuerdan por qué el escaneo de paquetes es tan importante

    • Gracias por avisar tan rápido. Ya envié un correo a porkbun para pedir el bloqueo del dominio

  • Hay una parte especialmente astuta de este payload malicioso que no ha recibido suficiente atención. No reemplaza direcciones de wallets al azar, sino que calcula la distancia de Levenshtein entre la dirección válida y cada una de las direcciones en su propia lista, y elige la wallet del atacante más parecida. Está diseñado precisamente para evadir el hábito de seguridad tan común de revisar solo por encima el principio y el final de una dirección. También hay un artículo detallado que analiza todo el payload tras desofuscarlo, incluida esa función tan particular. Cuídense todos

    • Hay una parte del artículo que me confunde: según yo, package-lock.json fija una versión específica de forma "exacta". package.json sí permite definir "versión x o superior", pero en el lockfile quedan grabados directamente la versión concreta de cada dependencia y la URL del tarball. Si existe el lockfile, en un entorno de CI no debería pasar que los paquetes se actualicen automáticamente, así que me pregunto si estoy entendiendo mal cómo funcionan los lockfiles de npm/yarn/pnpm. También convendría revisar esta cita de la documentación oficial de npm

    • Creo que sería mucho más fácil distinguir hashes falsificados visualmente si cada carácter se mostrara con un color distinto (color de texto/fondo) usando un esquema derivado del hash y del índice

    • Me pregunto si hay alguna información sobre si esta técnica está relacionada con algún grupo de hacking en particular

    • El código de este ataque es ingenioso, sí, pero en realidad en la web llevamos décadas peleando contra ataques de direcciones parecidas, y esto no deja de ser una versión más dinámica. No estoy de acuerdo con tratarlo como si fuera extraordinariamente brillante. Francamente, todo ese análisis me dio más la impresión de haber sido escrito por IA que de ser un análisis cuidadoso

  • Hace 12 días dejé un comentario parecido cuando le pasó exactamente lo mismo a Nx. Esto no es el fracaso de una sola persona, sino el fracaso de toda una industria. Los ataques a la cadena de suministro tienen un impacto enorme y, en realidad, creo que son problemas ya resueltos desde hace tiempo. Somos desarrolladores de software, así que bastaría con aplicar de forma general medidas de seguridad estándar como firma de código, firma de artefactos, detección de comportamiento anómalo en cuentas, 2FA, etc. Si las plataformas de empaquetado todavía no lo hacen, no es por una limitación técnica, sino porque nadie las obliga. Con los avances de la IA y el éxito repetido de ataques reales, esto se va a poner peor. Ya es hora de que estándares de seguridad fuertes sean obligatorios

    • Estas medidas de seguridad sí tienen tradeoffs. Por ejemplo, aplicar mecanismos heurísticos o basados en pruebas puede dejar fuera a bastantes sistemas automatizados o incluso a usuarios comunes. El 2FA por SMS es débil, y el correo electrónico también tiene riesgo de phishing. TOTP solo tiene sentido cuando se usa como estándar abierto, y aun así no bloquea totalmente el phishing. La autenticación basada en hardware es la única realmente efectiva, pero tiene el límite de ser difícil de aplicar de forma realista en plataformas masivas

    • No es tan simple como decir "si seguimos bien los estándares de seguridad, todo se evita". Aunque implementes medidas perfectas, si una persona se equivoca, todo el sistema queda expuesto. No existe un sistema completamente seguro. La IA está haciendo que los correos de phishing sean cada vez más indistinguibles de los reales, pero al mismo tiempo también puede ayudar a detectar mejor este tipo de ataques. Al final no va a quedar otra que defendernos con IA

    • Antes la mayoría de los ataques iban dirigidos a Windows, pero ahora hay muchísimos más desarrolladores de JavaScript y Python. Este tipo de ataques solo va a empeorar con el tiempo

  • También creo que NPM tiene parte de la responsabilidad. Diversos proveedores de seguridad y startups externas detectan rápido esta actividad maliciosa, así que cuesta entender por qué NPM, que puede ver en tiempo real todos los paquetes y eventos de seguridad, sigue siendo tan incapaz una y otra vez. Ya está cerca de parecer que se hacen los que no ven

    • NPM ahora pertenece a GitHub, o sea, a Microsoft. Parece que están demasiado ocupados metiendo IA generativa como Copilot en todas partes

    • En los paquetes mantenidos por varias personas, al menos debería existir una opción para que otro mantenedor tenga que aprobar la publicación antes de que se despliegue

    • El mismo atacante inyectó de una sola vez un payload ofuscado —y además muy sospechoso— en más de 22 paquetes que llevaban mucho tiempo inactivos, y los publicó al mismo tiempo. Me parece casi imposible esperar que NPM detecte eso. Como alguien que ha publicado apps/extensiones en otras plataformas de software, no es raro tener que esperar días o incluso semanas. Aun así, sorprende que NPM, pese a que MS y GitHub venden toda clase de soluciones de seguridad, no muestre señales de una inversión seria en el servicio

    • Tampoco creo que NPM tenga demasiados incentivos para cambiar nada. Lleva más de 10 años siendo una fuente de distribución de malware, pero como nadie deja de usarlo, al negocio no le afecta

    • Parte del problema es la expansión excesiva de los package managers. Desde el principio me ha molestado depender hasta de paquetes para cosas tan triviales. También odio esa experiencia de traer versiones recientes al azar y que el entorno se rompa. No es solo npm: en general todos los package managers me desesperan por igual

  • A estas alturas, si alguien mete directamente su contraseña en un sitio cuyo dominio no coincide con el oficial, y además no usa password manager, yo diría que no debería estar haciendo nada importante en internet

    • Un password manager o el autocompletado del navegador habrían advertido sobre este tipo de dominio falsificado, y habrían bloqueado una discrepancia como npmjs.help frente al dominio oficial en este phishing de NPM

    • Eso es cierto, pero también me ha tocado muchas veces ver apps oficiales y sitios oficiales usando dominios completamente distintos. Lo peor es cuando la app móvil y la web ni siquiera comparten dominio. No sé a quién se le ocurrió diseñar eso

  • Cada vez que pasa algo así no entiendo por qué los registros de paquetes no exigen firma criptográfica para todos los paquetes. Claro, si en CI/CD firmas de forma automatizada y también comprometen esa parte, podrían saltárselo, pero aun así se evitaría la mayoría de los problemas. Eso sí, obligaría a los desarrolladores a agregar pasos extra como descargar el artefacto manualmente, firmarlo y volverlo a subir

    • Un registro de verdad ya lo hace Debian. npm es tan amateur que en muchos entornos corporativos está prohibido

    • El enfoque que más me gusta es la verificación posterior. Después de la subida automática desde CI/CD, que una persona tenga que entrar a la web y hacer un clic adicional para que la publicación se haga efectiva. Así reduces fricción en el proceso de release, pero aun así obligas a que haya una aprobación humana final

    • Pero sigue quedando el problema difícil de "qué clave de firma hay que confiar". Cualquiera que comprometa un 2FA puede subir una clave nueva y firmar con ella, así que harían falta cosas como retrasar el registro de nuevas claves de firma cuando se detecte actividad sospechosa en una cuenta

  • He llegado a la conclusión de que sale mucho mejor evitar el registry de npm. Creo que es preferible traer los paquetes directamente desde el repositorio (git). El registry de npm es además el canal principal de estos ataques a la cadena de suministro, y también existe el problema de que el código fuente y el código distribuido están completamente separados. npm publish puede subir directamente cualquier código local, así que un actor malicioso lo tiene fácil para inyectar malware

    • En los GitHub builds sí existe una función para verificar autenticidad al publicar en npm, pero aun así parece que sigue siendo posible publicar desde otros entornos, así que no me queda del todo claro

    • Como desarrollador de C, me resulta rarísimo haber pasado años escuchando que minimizar dependencias, usar librerías de un solo header o hacer vendoring era una práctica anticuada, para que ahora todos estén volviendo a ver que sí hacía falta

    • La función reciente de provenance en npm resuelve este problema. Configurarla es bastante sencillo y ayuda a prevenir ataques como este. Me alegra ver que paquetes grandes la están adoptando uno tras otro

    • Me pregunto si esto también se usa en entornos de CI. Quisiera saber si normalmente reemplazan npm install en el servidor por git clone

    • "Traer paquetes directamente desde el repositorio git" suena bien en teoría, pero en la práctica npm tiene muchos bugs y hay varios que afectan la instalación de dependencias desde git. Como dejé en este issue, por problemas con el paso de build esto no funcionó bien hasta 2020, y sigue habiendo problemas cuando haces npm install global. Incluso aunque el script prepack esté documentado por npm, en la práctica no funciona en dependencias basadas en git. El equipo del compilador de TypeScript también tuvo que recurrir a soluciones rarísimas por este bug, y ahí están tanto el código de workaround como el bug. También es un problema que, aunque falle prepack, no se propague el exit code y npm install termine como si nada, pero roto. Viendo todo esto, siento que npm necesita con urgencia una supervisión operativa seria o directamente ser reemplazado por un package manager nuevo

  • Desde fuera del ecosistema de npm, me sorprende ver por qué demonios usan tantísimos paquetes para cosas tan pequeñas

    • La razón es que la biblioteca estándar es demasiado pobre y hasta para funciones básicas tienes que usar paquetes externos. Si lo construyes tú mismo, incluso lo trivial implica muchísimo trabajo

    • Hablando desde 15 años de experiencia, muchos desarrolladores de JavaScript en trabajos corporativos en realidad casi no saben programar. No es un tema de capacidad intelectual, sino de formación y de cultura. Tienen un miedo enorme a escribir código propio, y al final terminan dependiendo de paquetes externos incluso para cosas mínimas. Quienes hacen proyectos por hobby suelen no tener ese problema, y su código a menudo es más sólido. Si te interesa comprobarlo, pídele a alguien de tu equipo que construya algo sin un framework grande y te vas a dar cuenta enseguida

    • Importar módulos pequeños y triviales tiene el objetivo de no meter al cliente código innecesario. Las bibliotecas integrales dan una DX más limpia, sí, pero también cargan cosas que no quieres incluir (aunque exista tree-shaking, no es una solución mágica)

    • Desde el caso de leftpad esta discusión no ha parado. Puede que el problema sea que la biblioteca estándar de JS es demasiado reducida

    • Para quien revisa un PR, ver un import de una línea a un módulo que parece "de confianza" puede resultar mucho más fácil que revisar un cambio grande de código. En realidad no es más seguro, pero cuando uno está cansado sí puede parecerlo

  • Ya lo dije también durante el incidente de nx: creo que los package managers deberían tener un "periodo de gracia" para paquetes nuevos, saltándoselos durante un tiempo fijo (por ejemplo, 24 horas). La mayoría de estos ataques se detectan y bloquean poco después del lanzamiento, así que si durante ese periodo los usuarios no instalaran automáticamente la versión más nueva, el daño real podría reducirse bastante

  • Me imagino el dolor y el estrés que debe haber vivido el autor. Debe ser durísimo tener que seguir dando explicaciones por un solo error. También deja claro hasta qué punto el ecosistema open source depende fuertemente de paquetes que en la práctica pertenecen a una sola persona. Hay que aceptar que cualquiera puede ser hackeado por un error. Desde el lado técnico, ahora que la IA se usa tanto, parece necesario un cambio cultural: que deno/node/bun muestren alertas ante código sospechoso, que exista algo tipo @verified basado en la confianza de autenticación al estilo Debian para reforzar la fiabilidad de las publicaciones, y que se usen versiones verificadas en lugar de perseguir siempre la más reciente. El autor también es humano y todos deberíamos tratarlo con amabilidad. Cuando la situación se estabilice, también me gustaría ver un análisis técnico más detallado o un postmortem