test-brotli-testmetest@1.0.0
Malicious code in test-brotli-testmetest (npm)
Analysis
test-brotli-testmetest@1.0.0 is an encrypted dropper that executes a hidden second stage at install time. The package declares `"install": "node-gyp rebuild"` and ships a binding.gyp whose only source entry is `"<!(env node index.js >/dev/null 2>&1; echo stub.c)"`. node-gyp evaluates `<!(...)` command substitutions during configure, so `node index.js` is executed on every install with stdout/stderr discarded to hide the activity. index.js (586 KB, one line) is a hand-written loader. It decodes a 586 KB array of character codes with a Caesar shift of +1 and passes the result to `eval`. The decoded code imports node:crypto and defines an AES-128-GCM decryptor (`createDecipheriv("aes-128-gcm", ...)`, `setAuthTag`, `concat([update, final])`) plus a base64 variant. It then decrypts an embedded blob using a hardcoded 32-hex-character key, 24-hex-character IV and 32-hex-character auth tag, and `eval`s the resulting plaintext. The decrypted stage is written to a file named `a<timestamp>.js` in the OS temp directory (`os.tmpdir()`) and launched with `child_process.spawn(process.execPath, [file], {stdio:"ignore", detached:true})`, followed by `unref()` so the parent install process exits immediately while the payload keeps running. The second-stage payload is stored only as AES-GCM ciphertext, so no plaintext command-and-control host, IP or URL appears anywhere in the package; the destination and capabilities of the dropped stage are determined by the decrypted blob.
- analyzed by
- Leitwacht
- first seen
- Oct 21, 2026, 02:34 PM
- analyzed
- Oct 21, 2026, 02:35 PM
Related advisories
- test-brotli2-testmetest@1.0.0
- event-emitter-testmetest@4.1.0
- event-emitter-testmetest@1.0.7
- event-emitter-testmetest@1.0.6
- data-pipeline-testmetest@2.0.0
- stream-utils-testmetest@1.0.0
- data-pipeline-testmetest@2.0.1
- casamare@1.0.0
Independently detected by the Leitwacht supply-chain probe. IOCs are defanged. Published CC0. Think this is a mistake? See the dispute policy.