LWA-2026-13136 confirmed malware

event-emitter-testmetest@4.1.0

Malicious code in event-emitter-testmetest (npm)

T1195.002 · Compromise Software Supply ChainT1059.007 · JavaScriptT1027 · Obfuscated Files or InformationT1140 · Deobfuscate/Decode Files or InformationT1105 · Ingress Tool Transfer

Analysis

This package executes an obfuscated dropper at install time without declaring any lifecycle script. Its package.json has no preinstall/postinstall hook; instead binding.gyp contains a node-gyp command substitution — "sources":["<!(env node index.js >/dev/null 2>&1; echo stub.c)"] — which runs index.js during the install/rebuild step. index.js (1.67MB, single line) is wrapped in a Caesar-shift-2 decoder: eval((function(d,k){...})([char codes],2)). The decoded source imports node:zlib, gunzips a base64/hex-encoded second stage embedded in the file, imports node:child_process, and pipes that stage into a Bun interpreter: spawn([process.execPath,"run","-"],{stdio:"pipe"}) when a bun global is present, otherwise spawn(getBunPath(),["run","-"],{stdio:"pipe"}) after obtaining Bun, with a plain eval() of the decoded blob as fallback. The second stage is never shipped as a file — it is assembled in memory at install time, so the package's real payload is not visible in the tarball. The package name is a combosquat of the widely used `event-emitter` package (real name intact plus a "-testmetest" suffix), ships no README and no repository, and its only other file is the binding.gyp stub. No network endpoint is hardcoded in the decoded first stage; the C2/payload is delivered through the runtime-assembled second stage.

analyzed by
Leitwacht
first seen
Oct 21, 2026, 02:04 PM
analyzed
Oct 21, 2026, 02:07 PM

Related advisories

browse all confirmed advisories →

Independently detected by the Leitwacht supply-chain probe. IOCs are defanged. Published CC0. Think this is a mistake? See the dispute policy.