Tres crates de Rust llevaron malware al proceso de compilación

Tres versiones maliciosas de crates legítimos de Rust llegaron a crates.io el 20 de agosto de 2026: arrayref 0.3.10, internment 0.8.7 y append-only-vec 0.1.9. La respuesta de seguridad de Rust verificó que dependían de un paquete con un script de compilación que descargaba una carga maliciosa; las publicaciones fueron eliminadas después de permanecer disponibles durante 86, 90 y 107 minutos, respectivamente.
El punto decisivo para evaluar la exposición es saber si Cargo llegó a compilar la dependencia afectada. Encontrar una versión en Cargo.lock prueba que el proyecto la resolvió, y hallarla en la caché prueba que fue descargada; si además hubo un cargo build, cargo check u otra operación que compilara el paquete, el equipo o runner debe tratarse como posiblemente comprometido aunque ninguna función del crate se haya invocado.
Las versiones afectadas y su ventana de exposición

El incidente quedó limitado a tres publicaciones concretas, no a todas las versiones históricas de las bibliotecas. Arrayref 0.3.10 estuvo disponible entre las 07:15:00 y las 08:41:40 UTC; internment 0.8.7, entre las 07:34:07 y las 09:04:11; y append-only-vec 0.1.9, entre las 07:37:49 y las 09:25:24.
- arrayref: versión afectada 0.3.10; última versión limpia anterior, 0.3.9.
- internment: versión afectada 0.8.7; última versión limpia anterior, 0.8.6.
- append-only-vec: versión afectada 0.1.9; última versión limpia anterior, 0.1.8.
- Paquetes relacionados que requieren revisión: proc-macro1, proc-macro-en, aovine, arone, aronenao y tinymember.
El equipo de Rust eliminó las publicaciones maliciosas y los paquetes relacionados, restauró las versiones legítimas que habían sido retiradas y bloqueó preventivamente la cuenta del mantenedor. No atribuyó la operación al autor legítimo de arrayref: indicó que su equipo o sus credenciales probablemente habían sido comprometidos.
El malware se activaba antes de usar la biblioteca

Las versiones alteradas añadían proc-macro1, un nombre parecido al crate legítimo proc-macro2. La versión proc-macro1 1.0.107 conservaba una copia renombrada del código de proc-macro2, pero incorporaba la actividad maliciosa en build.rs, un script que Cargo compila y ejecuta automáticamente cuando procesa una dependencia.
El análisis técnico de JFrog documentó que build.rs reconstruía la dirección 23.254.165[.]112, desactivaba la validación de certificados TLS y descargaba una carga adaptada al sistema operativo. En Linux y macOS la guardaba como /tmp/rust-setup; en Windows creaba %TEMP%\rust-setup.ps1 y el lanzador %TEMP%\rust-setup-launch.vbs. La conexión de descarga usaba el puerto 9089 y la carga recibía como argumento la misma dirección en el puerto 443.
Por eso no hacía falta importar una macro ni llamar a una función de arrayref, internment o append-only-vec. Un cargo build, cargo check, una compilación de CI o una operación de rust-analyzer que compilara la dependencia podía ejecutar build.rs durante la preparación del proyecto.
Cargo.lock, caché y ejecución no prueban lo mismo

Una coincidencia en Cargo.lock demuestra una resolución afectada, pero no prueba por sí sola que el malware se ejecutara. La búsqueda debe abarcar repositorios, ramas de lanzamiento, lockfiles archivados, árboles creados con cargo vendor e imágenes de compilación conservadas durante la ventana del incidente.
Una coincidencia en la caché demuestra que el crate fue descargado, no que build.rs llegara a ejecutarse. Deben revisarse ~/.cargo/registry/cache y las cachés externas o snapshots de runners efímeros para localizar arrayref-0.3.10.crate, internment-0.8.7.crate, append-only-vec-0.1.9.crate y archivos cuyos nombres comiencen por proc-macro1.
Los registros de una compilación con esas versiones elevan el caso a posible compromiso del host. Conviene correlacionar el lockfile con trabajos de CI, historiales de build y check, marcas de tiempo de los archivos rust-setup y conexiones a la infraestructura indicada. No encontrar actualmente el archivo descargado descarta ese indicador, pero no una ejecución anterior: el archivo pudo eliminarse o desaparecer junto con un runner efímero.
Contención cuando Cargo compiló la dependencia
Si solo aparece el lockfile, debe corregirse la resolución y comprobarse si después hubo descarga o compilación. Si existe una copia en caché, conviene preservar los registros antes de limpiarla. Cuando los registros muestran que Cargo compiló la dependencia, borrar el crate o regenerar Cargo.lock no basta para sanear el sistema.
- Aislar las estaciones y los runners implicados, conservando registros, snapshots y artefactos necesarios para investigar.
- Buscar /tmp/rust-setup en Linux y macOS, y rust-setup.ps1 y rust-setup-launch.vbs en %TEMP% en Windows; revisar también conexiones con 23.254.165[.]112 en los puertos 9089 y 443.
- Sustituir las versiones afectadas por arrayref 0.3.9, internment 0.8.6 y append-only-vec 0.1.8, regenerar Cargo.lock con los metadatos actuales de crates.io y verificar que no permanezca proc-macro1.
- Revocar y reemplazar tokens de CI, credenciales de repositorios y registros, claves de nube, claves de firma y otros secretos accesibles para el usuario o servicio que ejecutó la compilación.
- Reconstruir runners e imágenes desde una base conocida como limpia y volver a generar los artefactos producidos por el entorno afectado.
La segunda etapa amplía lo que debe investigarse
JFrog no pudo recuperar la segunda etapa porque el servidor de descarga ya no respondía durante su análisis. Sin embargo, la investigación de Wiz obtuvo muestras mediante Google Threat Intelligence y observó persistencia mediante una clave Run de Windows, LaunchAgent en macOS o un servicio de usuario de systemd en Linux. También encontró consultas a los perfiles de Chrome, Brave y Edge que enumeraban inicios de sesión guardados y ajustes de extensiones; Wiz corrigió expresamente una afirmación inicial y aclaró que esas consultas no recuperaban el material cifrado de las credenciales.
Las tres versiones maliciosas y los paquetes asociados ya fueron retirados, pero esa eliminación no borra lockfiles, cachés, imágenes o artefactos conservados por cada organización. Tampoco se ha publicado un recuento completo de los entornos alcanzados: el alcance debe establecerse cruzando la resolución de dependencias, la descarga y la ejecución real de una compilación durante el incidente.
Lee también:
Suscríbete a nuestro boletín
Reciba las últimas noticias sobre Web3, IA y criptomonedas directamente en su bandeja de entrada.