Resumen de la publicación
En diez días se acumularon un gusano que infectó más de 1.300 paquetes de npm, 77 extensiones maliciosas en Open VSX, dos extensiones de VS Code que vaciaban billeteras de criptomonedas, proyectos de Xcode que infectan al compilar y un feed de actualizaciones envenenado que creó administradores ocultos en sitios WordPress.
El patrón no es «hay muchos ataques a la cadena de suministro». Es que todos entraron por cosas que instalamos sin mirar y que corren con nuestros permisos. Acá va qué cambiaría yo, ordenado por esfuerzo.
Vengo diciendo hace rato que la conversación sobre seguridad en desarrollo está mal encuadrada, y esta quincena me dio material de sobra para insistir.
Hablamos de revisión de código, de linters, de análisis estático. Todo eso está bien y hay que hacerlo, pero mira una superficie que, en proporción, es chiquita: el código que efectivamente escribimos nosotros.
La superficie grande es la otra. Es todo lo que tu proceso de compilación descarga y ejecuta sin que ninguna persona lo lea nunca.
Cinco casos en diez días
1. ChainDrop: un gusano dentro de npm
ChainDrop se propagó a más de 1.300 paquetes de npm que suman unos 2.000 millones de descargas mensuales combinadas.
Lo que lo convierte en un gusano y no en un incidente puntual es el mecanismo: una vez instalado busca credenciales para entrar a otros repositorios y paquetes, y con eso infecta paquetes de otros autores que hayan usado alguno ya comprometido. Se propaga solo, sin que nadie lo maneje.
Lo que se lleva es un listado largo:
- Tokens de GitHub y de npm.
- Credenciales de AWS y secretos de Kubernetes.
- Credenciales de bases de datos.
- Claves de servicios como Stripe y Twilio.
Cayeron utilitarios de uso muy amplio como Keyv, Cacheable, flat-cache y file-entry-cache. El indicador más práctico para saber si te tocó es el dominio npm-cache[.]com: si aparece en tus registros de red, ya sabés por dónde empezar.
2. Setenta y siete extensiones que mapeaban tu entorno
Manifold Security encontró 77 extensiones en Open VSX que se hacían pasar por herramientas asociadas a AMD, Azure, Salesforce, Hyperledger, LEGO Education, IOTA y hasta una agencia gubernamental estadounidense.
Estas no robaban contraseñas: mapeaban entornos. Se llevaban el nombre de usuario del sistema, el identificador de la máquina, la arquitectura, la zona horaria, la ruta del proyecto, el repositorio, la rama actual, el identificador del último cambio, la lista de hasta 60 extensiones instaladas y los datos del pipeline de compilación.
Eso es reconocimiento, y es exactamente lo que necesitás tener antes de elegir a quién atacar en serio.
3. «Solidity Pro»: la versión sin sutilezas
Yeeth Security documentó dos extensiones llamadas «Solidity Pro» (helper-beeps.solidity-pro y web3devtoolsx.solidity-pro) que a partir de la versión 3.0.0 se llevaban tokens de GitHub, GitLab, AWS y Cloudflare, claves de OpenAI, frases semilla, billeteras de MetaMask, Phantom, Rabby, Coinbase, Trust y Keplr, claves SSH privadas y códigos de segundo factor de 1Password.
Hay un detalle de oficio que me parece clave: las primeras versiones eran limpias. El código malicioso llegó después, con ofuscación pesada y activación demorada al azar para dificultar la detección.
O sea que revisar una extensión el día que la instalás no te dice nada sobre lo que va a hacer dentro de tres meses.
4. XCSSET: infectarse con solo compilar
Unit 42 analizó una nueva variante de XCSSET que compromete repositorios e inyecta scripts de descarga dentro de archivos aparentemente inofensivos de proyectos Xcode.
El desarrollador que se baja el proyecto se infecta al compilarlo, sin necesidad de ejecutar la aplicación. El malware despliega 17 módulos, entre ellos uno que intercepta transacciones de MetaMask en Chrome y otro que reemplaza Telegram por una versión con puerta trasera.
5. BdThemes: administradores invisibles en WordPress
Este es el que le pega de lleno a este mismo sitio y a la mitad de la web argentina. El ataque fue contra BdThemes, proveedor de plugins premium para Elementor con más de 350.000 instalaciones activas.
El atacante envenenó un archivo remoto que el plugin consulta para mostrar avisos dentro del panel de administración. Aprovechando una falla en el código que interpreta esa respuesta, inyectó JavaScript que manipulaba las consultas a la base de datos para esconder cuentas de administrador del listado de usuarios.
Lo peor es que no hacía falta actualizar nada: el código corría cada vez que un administrador abría wp-admin. Arrancó el 23 de junio y se detectó recién el 7 de agosto.
Lo que estos cinco tienen en común
Si los ponés uno al lado del otro, aparece algo que me parece más útil que la suma de las noticias. Ninguno explotó una vulnerabilidad en el código de la víctima: todos abusaron de un canal de confianza que la víctima había abierto a propósito y que consideraba parte de la infraestructura, no parte de la superficie de ataque.
- La dependencia que instalaste sin saber que traía otras cuarenta atrás.
- El catálogo de extensiones de tu editor.
- El repositorio del que clonás un proyecto de ejemplo.
- El canal por el que un plugin recibe sus actualizaciones.
Cuatro canales que nadie audita porque, técnicamente, no son «tu código».
Y hay algo peor, que se ve en el caso de Hugging Face Diffusers: a veces el control existe y simplemente no alcanza. Ahí investigadores de Zafran Labs encontraron tres fallas (CVE-2026-44827 y CVE-2026-44513, ambas 8.8, y CVE-2026-45804, 7.5) que permiten ejecutar código pese a tener activada la opción que justamente sirve para impedirlo (trust_remote_code=False).
La explicación de los investigadores es una frase que debería estar colgada en la pared de cualquiera que diseñe estos sistemas: «la verificación de confianza vive enteramente en la primera fase».
La descarga usa dos pedidos separados en lugar de una operación única, así que se puede meter el código malicioso después de que pasó el control. Es una carrera entre el momento de la verificación y el momento del uso, de las que estudiábamos en sistemas operativos, aplicada ahora a la cadena de suministro de modelos de IA. Está corregido en la versión 0.38.0.
Qué cambiaría yo, en orden de esfuerzo
No me gustan las listas de buenas prácticas que nadie va a implementar, así que las ordeno de lo que se hace hoy a la tarde a lo que requiere una decisión de equipo.
Hoy a la tarde
- Buscar
npm-cache[.]comen los registros de red y del proxy. Es gratis y te sacás la duda de ChainDrop. - Listar las extensiones instaladas en los editores del equipo (en VS Code,
code --list-extensions). Si aparece algo que nadie recuerda haber instalado, ya tenés una conversación pendiente. - Si administrás WordPress, revisar los usuarios administradores contra la base de datos (
wp_usersywp_usermeta), no desde el panel. El panel es justamente lo que el ataque de BdThemes manipulaba.
Esta semana
- Que la compilación automática instale siempre las versiones exactas ya fijadas y nunca resuelva versiones nuevas por su cuenta. En npm eso es
npm ci, nonpm install. - Desactivar los scripts que los paquetes ejecutan solos al instalarse (
--ignore-scripts) y habilitarlos únicamente donde hagan falta de verdad. - Rotar las credenciales que un ladrón de credenciales se llevaría: npm, GitHub, nube. Si nunca las rotaste, la fecha de la última rotación es tu ventana de exposición.
- Apagar la actualización automática de plugins de terceros en los sitios que te importan, y actualizar a mano después de mirar qué cambió.
Este trimestre
- Un repositorio interno de paquetes que haga de intermediario, para poder fijar versiones y conservarlas, en vez de pegarle directo al repositorio público desde cada compilación.
- Limitar a dónde puede salir la máquina que compila. Si no necesita llegar a internet más allá del repositorio de paquetes, que no pueda.
- Una política escrita sobre extensiones del editor: lista de permitidas, o al menos revisión de quién las publica.
Nada de esto es novedoso ni particularmente brillante. Es higiene, y lo que cambió es que el costo de no hacerla se volvió medible.
La confianza también es una decisión de arquitectura
Lo que más me quedó dando vueltas de esta quincena no es ninguno de los cinco ataques en particular. Es que en todos los casos la organización había decidido confiar, sin darse cuenta de que estaba decidiendo.
- Nadie se sentó a evaluar si convenía que un archivo remoto de un proveedor ejecutara JavaScript en el panel de administración. Simplemente se instaló un plugin.
- Nadie evaluó si el editor debía poder leer el identificador del último cambio y mandarlo afuera. Simplemente se instaló una extensión que resaltaba sintaxis.
- Nadie evaluó si compilar un proyecto ajeno debía poder tocar el navegador. Simplemente se clonó un repositorio para probar algo.
Esto se enlaza directo con lo que planteé sobre atarse a un solo proveedor de modelos: en los dos casos la decisión importante se toma sin que nadie la registre como decisión, y el costo aparece meses después, cuando revertirla es caro.
Mi propuesta es simple. Cada vez que un sistema tuyo ejecuta código que bajó de algún lado, eso es una decisión de arquitectura y merece quedar escrita en alguna parte: quién lo publica, qué permisos tiene, cada cuánto se revisa y qué pasa si ese proveedor es comprometido.
Empezar por contar
Ya elegí mi ejercicio para hacer con mis equipos esta semana: contar cuántas fuentes distintas de código ejecutable entran a producción sin que ninguna persona las haya leído.
No hace falta arreglarlas todas. Con tener el número ya cambia la conversación, porque deja de ser una discusión abstracta sobre cadena de suministro y pasa a ser una lista con nombres propios.
En la mayoría de los equipos con los que trabajé, ese número sorprende. Y sorprende para arriba.


