LWA-2026-13260 confirmed malware

mocha-ui-themes@1.0.0

Malicious code in mocha-ui-themes (npm)

T1195.002 · Compromise Software Supply ChainT1059.007 · JavaScriptT1059 · Command and Scripting InterpreterT1027 · Obfuscated Files or InformationT1497.001 · System ChecksT1082 · System Information DiscoveryT1552.001 · Credentials In FilesT1552.005 · Cloud Instance Metadata APIT1071.001 · Web ProtocolsT1102 · Web ServiceT1105 · Ingress Tool TransferT1041 · Exfiltration Over C2 Channel

Analysis

mocha-ui-themes@1.0.0 is a trojanized clone of tailwindcss 4.3.3 (the upstream tree is vendored verbatim under vendor/tailwindcss with UPSTREAM.json and NOTICE.md) carrying an injected credential-stealing loader. The package has no install hook; the payload is reached through the documented entry point instead: tokens.mjs imports cache-warm.mjs, and lib.mjs/lib.cjs call getTheme() from the PostCSS plugin's Once hook, so the obfuscated code runs whenever the package is used as a Tailwind/PostCSS plugin. Four files — cache-warm.mjs, cache-sweep.mjs, build-cache.mjs and workspaces.js — are obfuscated with base64 string arrays XOR-decoded with single-byte keys (0xfc, 0xf6, 0xf9), _0x identifier renaming and String.fromCharCode arithmetic. cache-sweep.mjs harvests: the contents of .env files found in up to 16 repository directories (truncated to 4096 bytes each), secret-scanner hits (path, line, matched text, up to 400 results), repository paths, and environment variables selected by name prefix, assembling them into out.code_secrets, out.dotenv and out.aws_env. build-cache.mjs resolves its command-and-control endpoint from the Ethereum blockchain: it POSTs JSON-RPC 2.0 requests over HTTP, reads the latest block number, walks back 30 blocks, matches transaction input data against a selector prefix, and XOR-decrypts 8-byte and 6-byte fields with a key to reconstruct a host, port and path. That reconstructed string is passed to eval() and then executed via child_process.spawn(process.execPath, [...], {detached: true, windowsHide: true}) with a modified environment; cache-warm.mjs and cache-sweep.mjs perform the same detached, window-hidden spawn. The package also ships native/cache-probe.node for win32, linux and darwin on x64 and arm64, a compiled node-vm-detect addon whose symbols include VM::qemu_fw_cfg, VM::systemd_virt, VM::chassis_type, VM::mac_address_check, VM::container_proc_id, VM::podman_file, VM::wsl_proc_subdir, VM::cpu_brand and VM::hw_memsize, used to detect virtualized and containerized environments. There is no static C2 host or IP in the package: the destination is resolved at runtime from a smart contract, so the only network indicator is outbound EVM JSON-RPC traffic.

analyzed by
Leitwacht
first seen
Oct 25, 2026, 02:07 PM
analyzed
Oct 25, 2026, 02:14 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.