


Perceptive Security
SOC/SIEM Consultancy

Two Joyfill npm beta releases contain an import-time implant that uses blockchain transactions to retrieve a remote-access trojan.
Published:
28 juli 2026 om 14:34:42
Alert date:
28 juli 2026 om 16:04:03
Source:
socket.dev
Supply Chain & Dependencies, Ransomware & Malware, Data Breach & Exfiltration, Web Technologies
Two npm beta releases in the @joyfill namespace (@joyfill/layouts@0.1.2-2773.beta.0 and @joyfill/components@4.0.0-rc24-2773-beta.4) were found to contain an import-time JavaScript implant that uses Tron, Aptos, and BNB Smart Chain blockchain transactions to retrieve a remote-access trojan. The implant, which activates on module load rather than install, runs two parallel delivery branches: one resolving a 77KB Node.js RAT via blockchain lookups, and another launching a detached Node.js process fetching a boot payload from a hardcoded C2 IP. The recovered RAT, identified as DEV#POPPER family, establishes a Socket.IO remote-control channel capable of arbitrary code execution, file upload, clipboard data theft, and credential collection. A Python infostealer (assessed as OmniStealer) is also delivered as a follow-on payload. The loader shares exact indicators with the PolinRider blockchain loader family. Persistence is achieved by injecting into developer tools including VS Code, GitHub Desktop, Discord, and the global npm CLI. Both malicious packages were published on July 28, 2026, using the same npm identity, suggesting a maintainer credential or build environment compromise.
Technical details
Two npm beta releases in the @joyfill namespace (@joyfill/layouts@0.1.2-2773.beta.0 and @joyfill/components@4.0.0-rc24-2773-beta.4) were compromised with a multi-stage blockchain-backed Remote Access Trojan loader. The implant is appended after legitimate package code and uses multiple layers of JavaScript obfuscation (seeded character shuffle, decoded string table, word-substitution decompressor, dynamic Function construction). Unlike install-hook attacks, the implant activates at module import time, bypassing npm install --ignore-scripts. Stage 0 sets global._V to 'A9-0135-3', establishes a 30-second process-global throttle in _p_t, and launches two payload-resolution paths: one in-process and one detached. Stage 1 uses a blockchain-backed dispatch mechanism: it queries a hard-coded Tron address for the latest outbound transaction hash, falls back to an Aptos account if needed, retrieves a BSC transaction via eth_getTransactionByHash, reverses/decodes the transaction input, XOR-decrypts a segment, and evaluates the result. This makes payload selection mutable without republishing to npm and resistant to conventional C2 domain blocking. The in-process branch ultimately delivers a 77,276-byte Node.js RAT (clientCode, versioned 260605) via a two-hop blockchain resolution chain. The RAT uses Socket.IO for C2, supports commands including ss_info, ss_ip, ss_cb, ss_upf, ss_upd, ss_dir, ss_fcd, ss_stop, ss_inz, ss_inzx, ss_connect, ss_eval, ss_eval64, ss_exit, ss_exit_f, collects host/OS details and public IP via ip-api.com, reads clipboard data (PowerShell on Windows, pbpaste on macOS, xclip/xsel on Linux), executes JavaScript/shell commands, uploads files, and persists by injecting into @vscode/deviceid module (VS Code, Cursor, Antigravity), Discord Desktop core module, GitHub Desktop resources/app/main.js, and global npm CLI node_modules/npm/lib/cli.js with injection tags like /*C250617A*/, /*C250618A*/, /*RS260605*/, etc. The detached branch spawns a separate node -e process (detached:true, stdio:ignore, windowsHide:true, unref()) that fetches a payload from 23[.]27[.]13[.]43/$/boot with the header Sec-V: A9-0135-3 and a Windows Chrome user agent, XOR-decrypts the response with key ThZG+0jfXE6VAGOJ, and evaluates it. Retrieved /$/boot responses (66,040 and 65,438 bytes) use additional Base64/RC4 obfuscation, can provision Python via /d/python.zip, /d/7zr.exe, /d/python.7z, and deliver an 82,457-byte Python infostealer (assessed with medium likelihood as OmniStealer). The Python infostealer collects environment/host info, Windows Credential Manager and Linux Secret Service data, Chromium/Firefox browser data, browser extension storage (wallets, password managers), Git credentials, GitHub CLI config, VS Code storage, GitHub Desktop logs, supports DPAPI/macOS Keychain/Linux Secret Service decryption, stages data under %USERPROFILE%\.npm or /tmp/.npm, creates an AES-encrypted ZIP using pyzipper with password ',./,./,./', and can exfiltrate via Telegram. The loader has exact PolinRider-family indicators and the recovered RAT matches DEV#POPPER family on Sec-V/$/boot endpoints, ThZG+0jfXE6VAGOJ decryptor key, Socket.IO use, ss_* command set, and developer-tool persistence. Both malicious versions use the 2773 prerelease build marker and were published 2026-07-28. Source maps confirm the implant was present at bundle time.
Mitigation steps:
For Developers: Remove both affected versions (@joyfill/layouts@0.1.2-2773.beta.0 and @joyfill/components@4.0.0-rc24-2773-beta.4) from lockfiles, caches, internal mirrors, build images, and deployment artifacts. Pin to verified safe versions (@joyfill/layouts@0.1.1, @joyfill/components@4.0.0-rc24) and prevent affected versions from being restored by automated resolution. Avoid the beta dist-tag for these packages until Joyfill confirms remediation. Note that npm install --ignore-scripts does NOT prevent this attack since the implant runs at import time, not install time. For Security Teams: Treat any machine that imported either affected version as potentially compromised with an interactive remote shell capability. Isolate the host, preserve logs and dependency artifacts, and rotate all credentials reachable from the affected Node.js process from a separate uncompromised machine. Investigate unexpected modifications to @vscode/deviceid under VS Code/Cursor/Antigravity, Discord Desktop core module, GitHub Desktop resources/app/main.js, and global npm CLI (npm root -g). Check for injection tags /*C250617A*/, /*C250618A*/, /*C250619A*/, /*C250620A*/, /*C260511A*/, /*C260512A*/, /*RS260605*/. If Python follow-on may have run, check for %USERPROFILE%\.npm or /tmp/.npm staging directories and rotate browser-saved passwords, cookies, wallet/password-manager browser extension data. Review endpoint and CI telemetry for: detached Node.js processes, outbound connections to the four C2 IPs (166[.]88[.]134[.]62, 23[.]27[.]13[.]43, 198[.]105[.]127[.]210, 23[.]27[.]202[.]27), the Sec-V HTTP header, outbound requests to api[.]trongrid[.]io or bsc-dataseed[.]binance[.]org from build agents or developer workstations (blockchain RPC traffic from CI is a high-fidelity signal). Block both package versions in your registry proxy or dependency policy tooling.
Affected products:
@joyfill/layouts@0.1.2-2773.beta.0
@joyfill/components@4.0.0-rc24-2773-beta.4
Related links:
https://socket.dev/npm/package/@joyfill/layouts/overview/0.1.2-2773.beta.0
https://socket.dev/npm/package/@joyfill/components/overview/4.0.0-rc24-2773-beta.4
https://socket.dev/blog/famous-chollima-targets-php-developers-through-compromised-packagist-package
Related CVE's:
Related threat actors:
IOC's:
@joyfill/layouts@0.1.2-2773.beta.0, @joyfill/components@4.0.0-rc24-2773-beta.4, adc4af90540d33cd1e98f44b51482ae9250fbeb97d6f8d7841c81b618cb2c6e6, 8e8b90dedd456ded0c5748119836e1ca1066112bc569c1b41ca70eb931d1d4dc, 5f6a92006ca2ea4b464d66fb41af777edce7296939a7c6ee491e2b3cbfe09848, bcc93dc55bc7daedf4ca57254f0e7a7f1c40e09851eab98fe10cde801982db17, 1352ad22c99983d91e600348b7cbf58235131b1ee34cea9f09623206d5b7dea7, 67c6ef602cc850f10d935fee53fa40440df841adf081563bf4fc2631a71249ce, c5742ea1875ecd2360022624149994909cd0546e221e4203dffd01f48de45469, cb46f12d70824ea24ed1f8bcf45bf3f86680e02a9089aafc03b27f691be57be3, f452f9cfa539f4a1fe25187a99a484391290d5dbaa422ba455edf6b04f81b7d1, 78f0de8682e0e894a5784eb7e95db4da6088f528918ca3107dd1e76f80a561d8, ae7565109fd01b88d82acf7f73ab20709cbc2c9f26fdea13e429ccc87a55d4fb, 26351aed0397158d3a3b8cc8fd3047d4c015d264c9895f10f20f1521b974ed18, 26e679eaf1e9baeb7c55eb48db482301171d4d26e1728544b23734a90dc70e1b, 2cfede38fb121a71a2f3607474aa8cd588a99f51b37e5e6f0d8cb789fa275032, 36ff00b45e67baa7e3674b0c80f48e88737264c61e5c6b3b091200972de8157c, api[.]trongrid[.]io, fullnode[.]mainnet[.]aptoslabs[.]com, bsc-dataseed[.]binance[.]org, bsc-rpc[.]publicnode[.]com, 166[.]88[.]134[.]62:443, 166[.]88[.]134[.]62:80, 23[.]27[.]13[.]43, 23[.]27[.]13[.]43/$/boot, 198[.]105[.]127[.]210:443, 198[.]105[.]127[.]210:80, 23[.]27[.]202[.]27:443, 23[.]27[.]202[.]27:27017, TMfKQEd7TJJa5xNZJZ2Lep838vrzrs7mAP, TXfxHUet9pJVU1BgVkBAbrES4YUc1nGzcG, TA48dct6rFW8BXsiLAtjFaVFoSuryMjD3v, 0xbe037400670fbf1c32364f762975908dc43eeb38759263e7dfcdabc76380811e, 0x3f0e5781d0855fb460661ac63257376db1941b2bb522499e4757ecb3ebd5dce3, 0x533b2dbcaeff19cd1f799234a27b578d713d8fcaa341b7501e4526106483e0b1, 0x18a8420f727f2405f9d1805ad887b31029b584b2ff5a7ec0f57c72635183e99d, 0x7ffb4efddd96e20aec90724be2ac9a71c138a9af697b9fb8224bbf80ea4f22be, 0xb6c725890be6890fd2c735eedc47e24b85a350301f6c19a3864e43c35e470968, 0x9bc1355344b54dedf3e44296916ed15653844509, Sec-V: A9-0135-3, ip-api[.]com, /*C250617A*/, /*C250618A*/, /*C250619A*/, /*C250620A*/, /*C260511A*/, /*C260512A*/, /*RS260605*/
This article was created with the assistance of AI technology by Perceptive.
