Two Joyfill npm Beta Releases Compromised to Deliver DEV#POPPER Remote Access Trojan

Two Joyfill npm Beta Releases Compromised to Deliver DEV#POPPER Remote Access Trojan

Two beta npm releases in the @joyfill namespace were found to contain an import-time JavaScript implant that uses blockchain transactions on Tron, Aptos, and BNB Smart Chain to resolve hidden payloads, with one branch leading to a 77 KB Node.js remote-access trojan. The compromised packages were @joyfill/layouts and @joyfill/components, and the recovered code overlaps with the PolinRider loader and DEV#POPPER family while also dropping related infrastructure for a Python infostealer linked to OmniStealer. #Joyfill #PolinRider #DEVPOPPER #OmniStealer

Keypoints

  • Two malicious beta releases were published in the @joyfill namespace: @joyfill/[email protected] and @joyfill/[email protected].
  • The implant executes at import time in CommonJS entrypoints, so npm install –ignore-scripts does not stop it once the package is loaded.
  • The loader uses public blockchain data from Tron, Aptos, and BNB Smart Chain to fetch encrypted next-stage code, making payload selection mutable without republishing npm packages.
  • One branch ultimately loads a 77 KB Node.js remote-access trojan with Socket.IO-based control, shell and JavaScript execution, file upload, clipboard access, and persistence features.
  • A second branch launches a detached Node.js process that requests a boot payload from 23[.]27[.]13[.]43 using the marker header Sec-V: A9-0135-3 and evaluates the decrypted response.
  • The recovered code matches PolinRider-family loader traits and DEV#POPPER operational markers, and the campaign also overlaps with infrastructure used for an OmniStealer-like Python infostealer.
  • Joyfill components’ Rollup bundle limited one artifact’s execution path, but the source-level injection still shows compromise of a second package and warrants removal from lockfiles, caches, and build systems.

MITRE Techniques

  • [T1195.002 ] Compromise Software Supply Chain – Malicious code was inserted into published npm packages in the @joyfill namespace (‘two beta releases in the @joyfill namespace contain an import-time JavaScript implant’).
  • [T1027 ] Obfuscated Files or Information – The implant used layered JavaScript obfuscation, including a seeded character shuffle, word-substitution decompression, and dynamic Function construction (‘several layers of JavaScript obfuscation’).
  • [T1027.013 ] Encrypted or Encoded File – Payloads were XOR-decrypted and retrieved in encrypted/encoded form from blockchain and boot responses (‘XOR-decrypts the response’ and ‘encrypted code through Tron, Aptos, and BNB Smart Chain transactions’).
  • [T1059.007 ] JavaScript – The malicious payloads were built and executed as JavaScript within Node.js (‘evaluates it’, ‘execute supplied JavaScript’).
  • [T1059.006 ] Python – The campaign retrieved and executed a Python follow-on infostealer (‘request a Python payload’, ‘a captured /$/1 payload decodes to an 82,457-byte Python infostealer’).
  • [T1059.004 ] Unix Shell – The final payload could execute shell commands and used shell-based collection on Unix-like systems (‘execute supplied JavaScript or shell commands’, ‘xclip or xsel on Linux’).
  • [T1071.001 ] Web Protocols – The RAT used Socket.IO and HTTP endpoints such as /$/boot and /verify-human/ for C2 and staging (‘Socket.IO command set’, ‘requests a separate boot payload from 23[.]27[.]13[.]43/$/boot’).
  • [T1105 ] Ingress Tool Transfer – Additional stages and tools were downloaded from remote infrastructure, including boot payloads, Python archives, and JavaScript modules (‘requests a separate boot payload’, ‘provision Python using /d/python.zip, /d/7zr.exe, and /d/python.7z’).
  • [T1115 ] Clipboard Data – The final payload read clipboard contents on multiple platforms (‘Reads clipboard data through PowerShell on Windows, pbpaste on macOS, and xclip or xsel on Linux’).

Indicators of Compromise

  • [npm package names and versions ] compromised releases – @joyfill/[email protected], @joyfill/[email protected]
  • [file paths ] affected bundle files – dist/index.cjs.js, dist/index.es.js, dist/index.js, dist/index.esm.js, dist/joyfill.min.js
  • [SHA-256 hashes ] package and payload hashes – adc4af90540d33cd1e98f44b51482ae9250fbeb97d6f8d7841c81b618cb2c6e6, 26351aed0397158d3a3b8cc8fd3047d4c015d264c9895f10f20f1521b974ed18, and other hashes listed for the loader and boot payloads
  • [IP addresses and ports ] command-and-control and boot infrastructure – 23[.]27[.]13[.]43/$/boot, 166[.]88[.]134[.]62:443, 198[.]105[.]127[.]210:443, and 23[.]27[.]202[.]27:27017
  • [Domains ] blockchain and staging infrastructure – api[.]trongrid[.]io, fullnode[.]mainnet[.]aptoslabs[.]com, bsc-dataseed[.]binance[.]org, bsc-rpc[.]publicnode[.]com
  • [HTTP headers ] marker used by the detached branch – Sec-V: A9-0135-3
  • [File and registry targets ] persistence and follow-on staging locations – @vscode/deviceid, Discord Desktop core module, GitHub Desktop’s resources/app/main.js, node_modules/npm/lib/cli.js, %USERPROFILE%.npm, /tmp/.npm
  • [Blockchain identifiers ] resolver addresses and transaction pointers – TMfKQEd7TJJa5xNZJZ2Lep838vrzrs7mAP, TXfxHUet9pJVU1BgVkBAbrES4YUc1nGzcG, 0x18a8420f727f2405f9d1805ad887b31029b584b2ff5a7ec0f57c72635183e99d, and 0x7ffb4efddd96e20aec90724be2ac9a71c138a9af697b9fb8224bbf80ea4f22be


Read more: https://socket.dev/blog/joyfill-npm-beta-releases-compromised