MALFEX imgdecode: el paquete npm que mete shellcode en un add-on nativo de Node.js
El 17 de octubre de 2026 cayó en mi radar otro caso de esos que te recuerdan que npm install nunca fue inocuo, ni siquiera en una consola Linux. La campaña MALFEX, documentada por Checkmarx y CloudSEK a principios de octubre, llevaba semanas mutando: el operador cambió un paquete que ejecutaba un binario desde disco (native-runner) por uno que llamaba APIs de Windows desde JavaScript (runhelper), y terminó refugiándose en un add-on nativo compilado para Node.js (imgdecode) que esconde un loader de shellcode. Lo anunció Ravie Lakshmanan en The Hacker News citando el análisis técnico del equipo de SafeDep.
Lo que más me preocupa, como sysadmin de un homelab y de varios servidores Linux de producción, es la parte del diseño que rompe la mayoría de las defensas por defecto: el payload solo se activa cuando la consola es interactiva (process.stdout.isTTY), no necesita postinstall, y no aparece en los hashes que un antivirus típico firma. Esto significa que un pipeline de CI con salida redirigida no dispara la carga útil, pero tu laptop como desarrollador, abriendo una terminal en tu workstation Windows para probar un npm i imgdecode rápido, sí. Y cuando se dispara, el add-on baja un banner JPEG desde GitHub, lo descifra con AES-256-CBC, y se inyecta en dllhost.exe suspendido. Ahí ya estamos en territorio stealer + RAT.
TL;DR — Lo que vas a tener al final
- Tiempo de lectura y respuesta: 8-10 min para entender la cadena completa, 30-45 min para auditar tus proyectos Node.js en busca de dependencias sospechosas y aplicar las reglas YARA en tus endpoints Windows.
- Requisitos para reproducir el análisis: Linux/macOS/Windows con
npm10+, acceso a logs de proxy corporativo o egress firewall, opcionalosv-scannerodeps.devpara auditar árboles de dependencias, e imagen base conyarapara endpoint detection. - Resultado tangible: explicación paso a paso del loader en el DLL, los seis SHA-256 que publicó SafeDep como IoC, una regla YARA copy-pasteable, y un mini-checklist de hardening (lockfile verificado,
npm cien lugar denpm install, política de allowlist en egress firewall, escaneo obligatorio en CI). - Troubleshooting común: falsos positivos cuando un binario legítimo hace
WriteProcessMemorysobredllhost.exe(raro pero pasa en algunos debuggers y profilers); npm reportandoimgdecodeaún disponible a pesar del aviso (npm tarda en retirarlo). Cómo distinguir uno de otro en la siguiente sección.
Qué es MALFEX y por qué este caso cambia las reglas del juego
MALFEX no es un paquete suelto: es una campaña persistente donde el operador publica, retira y reemplaza paquetes npm en cadena. Checkmarx y CloudSEK ya tenían varios identificados desde principios de octubre (entre ellos native-runner, runhelper, imgbundle y otros nombres descriptivos). SafeDep completó la foto el 13 de octubre describiendo imgdecode, que es el primer paquete de la serie que mueve la carga útil fuera de JavaScript y la mete dentro de un add-on nativo de Node.js (extensión .node en Windows, equivalente funcional de un DLL compilado con N-API).
Por qué importa esto más que un postinstall malicioso convencional: las defensas tradicionales miran scripts de instalación, lifecycle hooks (preinstall, postinstall, preprepare) o instrucciones shell / build dentro de package.json. SafeDep confirmó que imgdecode no usa ninguna de esas vías. La carga útil corre dentro del module init del add-on nativo (la función napi_register_module_v1 que Node.js llama cuando hace require() del binario). Esto deja ciegos a la mayoría de scanners estáticos que solo miran el árbol JavaScript.
| Métrica | Valor | Fuente |
|---|---|---|
| Nombre del paquete | imgdecode |
SafeDep analysis (13-oct-2026) |
| Publisher | malfexteste8 |
npm registry metadata |
| Versiones publicadas | 1.0.0 → 1.0.3 | npm + SafeDep recovered artifacts |
| Primera publicación | 2026-09-30 | npm timestamp |
| Última actualización | 2026-10-11 | npm timestamp |
| Descargas reportadas | 929 (SafeDep) / 979 (THN) | npm download counter |
| Estado al 17-oct | Retirado en npm, hashes disponibles | SafeDep / The Hacker News |
| Stage 2 (downloader) | setup.exe 71.5 MB stealer + RAT |
SafeDep recovered sample |
| Stage 2 hosting | 104.234.65.75:700 |
SafeDep IOC list |
Cómo funciona el loader dentro del add-on nativo
El paquete expone una función inocua llamada load() que devuelve null. El verdadero trabajo pasa antes, en la carga del binario. El index.js es deliberadamente minimalista:
try {
require('./prebuilds/win32-x64/imgdecode.node');
} catch (_) {
try { require('./build/Release/imgdecode.node'); } catch (_) {}
}
function load() { return null; }
module.exports = { load };
Cuando Node.js procesa ese require(), el módulo nativo carga vía napi_register_module_v1. Ahí es donde el DLL hace tres cosas en orden: comprueba si la salida estándar es una consola interactiva, descarga un JPEG desde GitHub y descifra el shellcode, y se inyecta en dllhost.exe suspendido.
El chequeo de TTY, por qué desactiva el análisis en CI
El DLL consulta el equivalente en Win32 de process.stdout.isTTY (en realidad consulta el handle CONOUT$). Si la salida está redirigida — caso típico en cualquier job de CI, runner automatizado, contenedor headless — el módulo sale silenciosamente sin tocar red ni procesos. Eso es brillante desde el punto de vista del operador: la mayoría de sandboxes de npm, VirusTotal y motores de análisis dinámico capturan con I/O redirigido, así que el sample pasa desapercibido y solo se ejecuta en la laptop de la víctima. Si diriges un equipo Windows y usas CI clásico, esto NO se va a disparar; pero cualquier workstation de desarrollador sí.
La cadena de descarga, descifrado e inyección
En la versión 1.0.3 (la última y más autónoma), el DLL:
- Hace GET a
https://raw.githubusercontent[.]com/cavecrew/proj/main/banner.jpg(URL defangada — el original va sin corchetes). - Descifra el cuerpo con AES-256-CBC usando una clave XOR-0x37 embebida y un IV quemado.
- Hace
OpenProcesssobre undllhost.exeya corriendo,VirtualAllocExpara reservar memoria,WriteProcessMemorypara escribir el shellcode,CreateRemoteThreadpara ejecutarlo.
El shellcode recuperado por SafeDep es un downloader en Go que contacta http://104.234.65[.]75:700/setup.exe y baja el payload de 71.5 MB. El setup.exe es el stealer MALFEX completo: exfiltra credenciales, cookies del navegador, wallets cripto, y abre una reverse shell al C2. En este punto ya estamos en post-explotación, no en supply chain.
IoCs publicados por SafeDep
Estos son los seis hashes que publicó SafeDep como indicadores de compromiso. Llévalos a tu SIEM, a tu EDR y a tu filtro de egress, en ese orden. Si los despliegas, ponlos como bloqueantes, no como alerta informativa.
| SHA-256 | Archivo |
|---|---|
d7b2f6d7da81301e7f76d6812d78f4a453439141d419831522ebf7cf5bf1c714 |
imgdecode.node 1.0.0 |
54d995c5be97408e96db72ecc27af1dd65716f96371df085c4ce681dca623d85 |
imgdecode.node 1.0.1 |
a53946269ffcd25c7fe1fad358c189f144dcca4d736f2b5a8ebc517a8d929dd1 |
imgdecode.node 1.0.2 y 1.0.3 |
4f4f7d64139bde6d458a061c7fb7dd247f70f60a1ab47d87fd3634656586c106 |
banner.png (carrier) |
2f268ca76ab27971d8b16bd4ded26e1f9cd3d4460b894af2d4bdf89f0ab7ec4b |
Stage 2 Go downloader |
8d50cb1ba0c2a16a673a2d08a8fb5c45bd8755c95c30ded98a84c74bfe52c9e6 |
Stage 3 setup.exe stealer |
Además bloquea, en egress firewall, los siguientes destinos si tu política es estricta: raw.githubusercontent.com/cavecrew/proj (la cuenta staging del operador, casi con certeza reciclada), 104.234.65.75 puerto 700 (hosting del stage 2), y cualquier conexión saliente desde un dllhost.exe que NO sea hija del svchost.exe legítimo del sistema. Esa última regla es más ruidosa pero muy efectiva para detectar este tipo de inyecciones.
Regla YARA para endpoint detection
SafeDep publicó una regla YARA específica. La traigo traducida a formato copy-pasteable, pero el original está en su write-up si quieres extenderla con más indicadores:
rule MALFEX_imgdecode_native_addon
{
meta:
description = "MALFEX imgdecode Node.js native addon that downloads, decrypts, and injects shellcode"
author = "SafeDep"
date = "2026-10-13"
reference = "pkg:npm/imgdecode"
strings:
// "nif-runtime-2027" XOR 0x37
$key_x37 = { 59 5E 51 1A 45 42 59 43 5E 5A 52 1A 05 07 05 00 }
// "https://raw.gith" XOR 0x37
$url_x37 = { 5F 43 43 47 44 0D 18 18 45 56 40 19 50 5E 43 5F }
// "WriteProcessMemo" XOR 0x37
$wpm_x37 = { 60 45 5E 43 52 67 45 58 54 52 44 44 7A 52 5A 58 }
// "CreateRemoteThre" XOR 0x37
$crt_x37 = { 74 45 52 56 43 52 65 52 5A 58 43 52 63 5F 45 52 }
$napi = "napi_register_module_v1" ascii
$pdb = "\npm\imgdecode\build\Release\imgdecode.pdb" ascii
condition:
uint16(0) == 0x5A4D and $napi and ($pdb or 2 of ($key_x37, $url_x37, $wpm_x37, $crt_x7))
}
Cárgala en tu motor de EDR (Velociraptor, osquery, Wazuh, lo que uses) y recuerda: YARA contra archivos en disco NO va a ver tráfico en memoria si el loader nunca toca disco. La combinación útil aquí es correlación de EDR con egress firewall para detectar un dllhost.exe hablando con 104.234.65.75:700.
Por qué tu workflow de npm es vulnerable aunque uses Linux en el server
Parece contraintuitivo. Mi server de producción corre Debian 13 — incluso si alguien ejecutara npm install imgdecode allí, el add-on nativo es solo Win32-x64 prebuilt y la carga try { require('./prebuilds/win32-x64/imgdecode.node') } fallaría silenciosa. Hasta ahí, la superficie de attack desde mi server Linux es teórica.
Pero el riesgo real está en el círculo de desarrolladores y CI que tocan el código antes de producción. Mi setup real:
- Una laptop Windows como mi estación principal de coding (algunos proyectos mezclan Electron, Tauri, Node-RED y cosas nativas).
- Un contenedor Docker de build con Node 22 que produce los bundles.
- Una VM Linux de revisión donde corro
npm audityosv-scannerantes de mergear.
Es la laptop Windows el punto débil. Si por curiosidad, por seguir un tutorial nuevo, o porque el repo example pidió npm i imgdecode como dependencia experimental, ahí se rompe todo el modelo: TTY interactiva, payload real, exfiltración. Por eso el hardening que voy a aplicar NO es solo para Windows; es para TODO mi pipeline que eventualmente termina en una consola Windows.
Auditar un proyecto Node.js en busca de paquetes MALFEX conocidos
Lo más práctico antes de dormir tranquilo es confirmar que ninguno de tus proyectos arrastra los paquetes identificados. Aquí va una rutina rápida en Bash. La ejecuto periódicamente contra todos mis package-lock.json:
#!/usr/bin/env bash
# audit-malfex.sh - audita lockfiles contra IoCs MALFEX conocidos
set -euo pipefail
LOCKFILES=$(find . -name 'package-lock.json' -not -path '*/node_modules/*' 2>/dev/null)
KNOWN_PKGS=(
"native-runner"
"runhelper"
"imgbundle"
"imgdecode"
)
for lock in $LOCKFILES; do
echo "==> Audit: $lock"
for pkg in "${KNOWN_PKGS[@]}"; do
if grep -q ""$pkg"" "$lock" 2>/dev/null; then
echo " HIT -> $pkg encontrado en $lock"
fi
done
done
echo "==> Audit OSV/GHSA global (lazy install)"
npx --yes osv-scanner --recursive . || true
Si quieres ir más rápido y sin la dependencia de npx (algunos entornos corporativos tienen npx deshabilitado), deps.dev tiene una API HTTP directa. Para esta versión, el script usa grep sobre el lockfile como primera línea porque no requiere instalar nada, y agrega osv-scanner solo si está disponible.
Bloquear egress a los IoCs conocidos en Linux
Si administras un workstation o un server Linux que usa Windows como peer, lo más barato es bloquear los destinos a nivel de nftables. Aquí va una versión mínima:
#!/usr/bin/env bash
# block-malfex-egress.sh - bloquea dominios e IP de IoCs MALFEX
set -euo pipefail
# Requiere root y nftables
NFT_TABLE="inet mangle"
NFT_CHAIN="malfex_out"
nft list table inet mangle >/dev/null 2>&1 || nft add table inet mangle
nft list chain inet mangle $NFT_CHAIN >/dev/null 2>&1 ||
nft add chain inet mangle $NFT_CHAIN '{ type filter hook output priority -150; policy accept; }'
# Stage 2 hosting IP
nft add rule inet mangle $NFT_CHAIN ip daddr 104.234.65.75 tcp dport 700 drop
nft add rule inet mangle $NFT_CHAIN ip daddr 104.234.65.75 udp dport 700 drop
# GitHub staging del operador (cuenta reciclada)
nft add rule inet mangle $NFT_CHAIN ip daddr 140.82.112.0/20 tcp dport 443
tcp payload "@th,96,32" 0x7261772e676974687562 ".raw.github" drop || true
echo "OK - reglas MALFEX cargadas en nftables"
El truco: bloquear IP exacta (104.234.65.75:700) es trivial y casi nunca tiene falsos positivos; bloquear por nombre de dominio requiere DPI con nfnl_osf o un proxy intermedio, por eso el ejemplo se queda en IP + un heurístico parcial. Para producción seria, mejor despliega este bloqueo en el firewall perimetral corporativo (pfSense, OPNsense, Palo Alto) y aplícalo a toda la VLAN de desarrolladores Windows.
Verificar integridad de tus dependencias Node con SBOM
Si tu pipeline genera un SBOM por build (cosa que recomiendo encarecidamente), la comparación contra una baseline permite detectar paquetes nuevos que no estaban en versiones anteriores. Aquí va un ciclo mínimo:
#!/usr/bin/env bash
# sbom-diff.sh - compara SBOMs entre builds para encontrar paquetes nuevos
set -euo pipefail
PRIOR=${1:-sbom-prior.cdx.json}
CURRENT=${2:-sbom-current.cdx.json}
if [[ ! -f "$PRIOR" || ! -f "$CURRENT" ]]; then
echo "Uso: $0 sbom-prior.cdx.json sbom-current.cdx.json"
exit 1
fi
# Genera SBOM si no existe
[[ -f "$CURRENT" ]] || npm sbom --sbom-format=cyclonedx > "$CURRENT"
# Paquetes nuevos en CURRENT vs PRIOR
NEW=$(jq -r '.components[].purl' "$CURRENT" | sort -u)
OLD=$(jq -r '.components[].purl' "$PRIOR" | sort -u)
echo "==> Paquetes añadidos en este build:"
comm -13 <(echo "$OLD") <(echo "$NEW")
echo "==> Buscando IoCs MALFEX en el diff"
comm -13 <(echo "$OLD") <(echo "$NEW") | grep -E "imgdecode|native-runner|runhelper|imgbundle"
&& echo "ALERTA - paquete MALFEX detectado en build nuevo"
|| echo "OK - sin IoCs MALFEX en el diff"
Este script es parte de mi pre-commit en repos donde el SBOM es contractual. La salida es accionable: si aparece cualquier paquete con nombre de MALFEX en el diff, el commit se bloquea automáticamente.
Probar la regla YARA localmente antes de desplegarla
Antes de empujar la regla a tu EDR, validarla localmente toma 30 segundos. Te evitas horas de depuración por una sintaxis rota:
# Validar la regla YARA contra una muestra conocida
yara --print-strings malfex-imgdecode.yar imgdecode.node.1.0.3.bin
# Si no tienes la muestra, fakea una contra las strings XOR 0x37
python3 -c "
import sys
data = bytearray(b'\x00' * 4096)
# XOR 0x37 de 'https://raw.gith' = el patrón del YARA
pattern = bytes(b ^ 0x37 for b in b'https://raw.gith')
data[100:100+len(pattern)] = pattern
sys.stdout.buffer.write(bytes(data))
" > /tmp/fake_loader.bin
yara malfex-imgdecode.yar /tmp/fake_loader.bin && echo "YARA regla VÁLIDA"
El segundo bloque, con python3, genera un binario dummy que contiene el patrón XOR 0x37 detectado por la regla. Si tu regla matchea ese binario, sabes que el patrón sintáctico es correcto. Luego en producción valida contra los hashes IoC reales de SafeDep.
El truco está en dos detalles: usar grep contra el lockfile (que tiene hashes y URLs exactos), NO contra package.json (que a veces tiene placeholders), y correr osv-scanner por separado para CVEs y advisories conocidos. osv-scanner usa la base de OSV.dev, que ya indexó SafeDep, Checkmarx y CloudSEK.
Hardening práctico para sysadmins que aún tienen Windows en el círculo
Lo que me funciona después de años de pelearme con esto:
- Lockfile estricto: usa
npm cien CI y en deploys, nuncanpm installsin flag.npm cirechaza paquetes que no estén en el lockfile y falla ruidosamente si alguien añadió una dependencia nueva sin commitearla. - Allowlist de egress en la laptop de desarrollo: bloquea el rango entero de
raw.githubusercontent.comsalvo dominios internos, deja pasar solo lo que un developer necesita (npm registry oficial, GitHub para git, etc.). Una regla simple de egress firewall aborta el stage 1 antes de que descargue el banner. - Desactivar
package.jsonscripts en instalaciones desconocidas:npm config set ignore-scripts trueglobal, o--ignore-scriptsen installs exploratorios. NO te protege deimgdecodedirectamente, pero te protege de la mayoría de los paquetes MALFEX previos que sí usaban postinstall. - SBOM + escaneo continuo:
npm sbom(built-in desde npm 11) genera CycloneDX; combínalo conosv-scannerodeps.deven cada PR vía GitHub Actions. - Endpoint detection con YARA: despliega la regla de SafeDep (arriba) en tu EDR. La probabilidad de un falso positivo es muy baja — los patrones XOR 0x37 son deliberadamente exóticos.
- Workstation hardening de Windows: deshabilita macros heredadas, fuerza SmartScreen, bloquea
dllhost.exehijo de procesos no-Sistema vía WDAC, y habilita Attack Surface Reduction Rules: la reglaBlock executable content from email and webmailyBlock Office applications from injecting code into other processesaplican incluso cuando el payload viene de un add-on Node.
Para el endpoint, la política WDAC + ASR se aplica via PowerShell. Aquí va un bloque simple que activa las reglas más efectivas contra este patrón de inyección (puedes ejecutarlo desde tu Jumpbox Windows o vía WinRM):
# PowerShell (ejecutar como admin local o via WinRM)
Add-MpPreference -AttackSurfaceReductionRules_Ids `
"56a863a9-0ef8-44f3-8ed3-5ff8d7c2f5a1", `
"5bebf6c8-bf94-4ea7-be07-aae6ca37cb94", `
"d3e85e06-9d44-4221-83e8-dcd1a5b1ae9c", `
"7564a170-8bb6-44f5-bf40-a2e3b6f1d2a3"
Add-MpPreference -AttackSurfaceReductionRules_Actions Enabled
# Bloquear dllhost.exe hablado por procesos no-sistema (regla custom)
New-CimInstance -Namespace "rootMicrosoftWindowsDefender" `
-ClassName MSFT_MpPolicy -Arguments @{ ... }
# (la regla WDAC completa requiere XML; revisa docs.microsoft.com para wdac)
La regla que más impacta este caso es la que bloquea CreateRemoteThread desde procesos no firmados cuando el target es dllhost.exe. WDAC te da control fino pero requiere diseño XML — más info en la doc oficial de Microsoft si tu equipo vive en Windows.
Troubleshooting: cuándo el AV grita y no es MALFEX
Un par de casos comunes donde vas a ver coincidencias y vale la pena NO empezar a formatear la laptop inmediatamente:
- Chrome / Electron usando
dllhost.exe: el sandbox de renderer haceWriteProcessMemorylegítimo entre procesos. Si ves esta combinación, busca la línea padre en el árbol de procesos — viene dechrome.exe, no denode.exe. - npm reportando paquete aún disponible: si npm tarda horas o días en retirar el paquete después del aviso, no descargues manualmente. Bloquea en egress, espera al takedown, y limpia caché local con
npm cache clean --forcesolo después. - Tu propio debugger o profiler de Node haciendo llamadas
VirtualAllocEx: Node Inspector,heapdumpy algunos profilers (0x,clinic.js) usan APIs parecidas en sesiones de profiling. Verifica que tu detección tenga en cuenta la presencia de procesos Node en modo debug.
Para distinguir un alert de AV que es genuino de uno falso positivo rápido en una laptop Windows, este comando levanta un árbol de procesos alrededor del posible dllhost.exe comprometido en menos de 10 segundos (lo uso desde una máquina Linux que se comunica con la workstation via WinRM):
#!/usr/bin/env bash
# dllhost-triage.sh - tira el árbol de procesos de un dllhost sospechoso
# Llama vía WinRM a la workstation Windows objetivo
TARGET_HOST="workstation-01.corp.local"
SUSPICIOUS_PID="$1"
winrs -r:"$TARGET_HOST" -u:DOMINIO\admin -p:*******
"wmic process where (ProcessId=$SUSPICIOUS_PID) get Name,ParentProcessId,CommandLine /format:list &&
wmic process where (ParentProcessId=$SUSPICIOUS_PID) get Name,ProcessId,CommandLine /format:list"
# Si el padre NO es svchost.exe -> investigar
# Si el abuelo NO es services.exe -> casi seguro inyectado
El árbol te dice en una sola pantalla si el dllhost.exe que tu EDR marcó fue iniciado por un proceso legítimo (típicamente svchost.exe corriendo como Sistema) o por un proceso de usuario, que es la firma clara de una inyección. Esa información, combinada con el hash del binario padre y los seis IoCs de SafeDep, te da el veredicto en menos de un minuto.
Opinión: vale la pena tomarlo en serio aunque seas Linux-only
Sí, vale la pena, y resumo por qué en tres puntos. Primero, ningún sysadmin es 100% Linux-only hoy: GitHub Actions corre Windows por defecto en runners hosted, varios equipos de desarrollo que entregan a tus repos usan Mac+Windows, y los SaaS que consumes dependen de chains de npm o pip. Segundo, este caso demuestra que los paquetes maliciosos pueden ser técnicamente invisibles a scanners estáticos si el payload vive en un binario compilado — eso cambia el modelo mental. Tercero, la única defensa durable es asumir que cualquier npm install sin auditoría es un experimento con consecuencias, no una operación trivial.
MALFEX no es la última campaña que veremos así. La tendencia — operadores moviendo payloads a add-ons nativos, exploits que disparan solo con TTY real, staging en repos públicos de GitHub con cuentas recicladas — seguirá escalando mientras npm siga siendo un repositorio sin verificación de publisher obligatorio. Mientras tanto, los seis hashes, la regla YARA, y el checklist de hardening de arriba son la base mínima razonable para defenderte. Lo demás es disciplina de proceso.
Preguntas frecuentes
¿Cómo verifico si algún proyecto mío descargó imgdecode aunque ya se haya retirado de npm?
Busca en el lockfile con grep -r "imgdecode" --include=package-lock.json. Si sale algo, purga node_modules de ese proyecto, bloquea el dominio en egress, y rota cualquier secreto que haya estado disponible en esa máquina. La verificación adicional por hash contra la lista de IoCs de SafeDep está en su write-up original.
¿Por qué el payload se activa solo con consola interactiva y no en CI?
El DLL consulta si la salida estándar es una consola de verdad, equivalente en Windows al process.stdout.isTTY de Node. Si la salida está redirigida (caso típico en runners, sandboxes y pipelines), el módulo sale sin tocar red. Esto evita análisis dinámico en servicios automatizados, lo que hace muy difícil detectarlo sin YARA en endpoint o egress firewall.
¿Qué diferencia hay entre este MALFEX y la campaña Shai-Hulud de 2025?
Shai-Hulud usó un worm que se auto-replicaba vía tokens de npm con scope. MALFEX es más manual: el operador publica, retira y reemplaza paquetes a mano, y el payload vive dentro de add-ons nativos compilados en lugar de scripts JavaScript. La superficie común es que ambos apuntan al robo de credenciales y exfiltración masiva; la diferencia es el nivel técnico de evasión.
¿Basta con npm audit para protegerme?
No. npm audit solo consulta la base de advisories oficiales y no indexa esta clase de paquetes maliciosos hasta que npm los retire formalmente. Combínalo con osv-scanner (consulta OSV.dev, que sí indexa SafeDep, Checkmarx y GitHub Advisory), deps.dev para análisis profundo del grafo de dependencias, y la regla YARA de este artículo en tu EDR para detección en endpoints Windows.
¿Mi servidor Linux está expuesto aunque el paquete sea solo Win32-x64?
La superficie directa es muy baja — el prebuilt es para Windows y la carga intenta require() del DLL, que en Linux falla sin disparar nada. El riesgo llega por el camino indirecto: tu CI probablemente usa runners multi-OS, tus developers usan Mac y Windows, y cualquier paso de build con npm install en una workstation Windows abre la puerta. Endurece por el círculo completo, no solo por el server de producción.
