Threat reportSupply ChainTL-2026-1771

Joyfill npm Packages Compromised with Blockchain C2 Loader

mediumACTIVE

Joyfill npm Packages Compromised with Blockchain C2 Loader (TL-2026-1771), also tracked as ChainVeil, is a medium-severity supply-chain compromise, first published 2026-07-30 and last reviewed 2026-08-13. It is attributed to PolinRider (North Korea) with medium confidence, affects Joyfill @joyfill/components, maps to 23 MITRE ATT&CK techniques (T1005, T1027, T1027.010), and is covered by 9 detection rules and 28 indicators of compromise.

Severity
MEDIUMAssessed severity
CVEs
0None referenced
Techniques
23MITRE ATT&CK
Actors
1PolinRider
Detection rules
9SPL · KQL · Sigma
IOCs
28Indicators of compromise

Key facts for TL-2026-1771

Threat ID
TL-2026-1771
Also known as
ChainVeil
Severity
MEDIUM
Status
ACTIVE
Category
SUPPLY_CHAIN
First published
Last reviewed
Attribution
PolinRider
Attribution confidence
MEDIUM
Nation-state nexus
North Korea
Motivation
FINANCIAL
Target sectors
technology, software-development
Target regions
Global
Detection rules
9
Indicators of compromise
28
Updates
2026-08-13 · 2 updates

Malware and tooling in Joyfill npm Packages Compromised with Blockchain C2 Loader

Malware and tooling: JADESNOW, PolinRider

How Joyfill npm Packages Compromised with Blockchain C2 Loader works

Two @joyfill npm packages (@joyfill/components and @joyfill/layouts) were published on 2026-07-28 with 62 lines of obfuscated JavaScript injected directly into production dist bundles, executing at require()/import time with no install script. The payload uses a three-chain blockchain dead-drop (Tron -> BSC -> Aptos fallback) to relay an encrypted 77KB RAT client matching the PolinRider bot structure, with a detached node -e child-process fallback for persistence. Dead-drop and relay infrastructure is shared with the prior astro.config.mjs supply-chain campaign, tying this incident to the DPRK-attributed PolinRider/JADESNOW cluster.

On 2026-07-28, threat actors published malicious versions of two legitimate npm packages, @joyfill/components and @joyfill/layouts, at 10:54 UTC and 11:03 UTC respectively. Unlike typical npm supply-chain attacks that rely on postinstall scripts, the compromise here was injected directly into the packages' already-built production bundles (dist/index.cjs.js and dist/index.es.js): 62 lines of obfuscated code were spliced between the last legitimate utility function (sortLayoutItemsByColRow) and the FieldLayoutTypes constant, and the layouts bundle itself was swapped from a clean 37,318-line file for a 1,271-line malicious replacement built with vite-plugin-css-injected-by-js. Because the payload runs as a side effect of require()/import, any application pulling these versions executed attacker code automatically with no install-time trigger to detect.

The loader implements a three-stage, cross-chain dead-drop C2. Stage 1 sets a campaign marker in global scope (global["!"] = "9-0135-3") and exposes require/module globally, then queries the Tron blockchain (api.trongrid.io) for the latest transaction on a hardcoded address to obtain routing data, falling back to a Binance Smart Chain lookup (bsc-dataseed.binance.org, with bsc-rpc.publicnode.com as a secondary RPC) and decrypting the result with a hardcoded XOR key. Stage 2 reads the campaign marker to select one of three hardcoded HTTP C2 endpoints (166.88.134.62:443, 198.105.127.210:443, or a fallback at 23.27.202.27:27017 deliberately using the MongoDB port to blend in) while independently resolving a second Tron dead-drop address for command routing. If the primary path fails, the malware spawns a detached `node -e` child process with `windowsHide: true` and `stdio: "ignore"`, allowing the payload to persist after the parent process (and even the host application) exits. Decryption of the relayed blockchain transaction yields a 77KB LZ-compressed RAT client whose structure matches the PolinRider bot family, providing reverse-shell, credential-harvesting, file-exfiltration, and persistent-backdoor capability consistent with public reporting on PolinRider/DEV#POPPER-linked payloads.

Both malicious versions were unpublished by roughly 21:00 UTC the same day (~10 hours of exposure), but remained available on registry mirrors such as registry.npmmirror.com after the upstream takedown. Critically, the primary Tron dead-drop address (TMfKQEd7TJJa5xNZJZ2Lep838vrzrs7mAP) and the Aptos fallback hash pattern are identical to those used in the prior astro.config.mjs supply-chain campaign (a malicious pull request against the Egonex-AI/Understand-Anything repository, disclosed 2026-06-12), which used the same decoder function, shuffle marker, and dead-drop pattern documented by OpenSourceMalware as PolinRider-attributed. That campaign, in turn, sits inside a much larger 2026 wave of DPRK-linked npm/GitHub/Go/Composer/Chrome-extension compromises (ChainVeil, ViteVenom/SuccessKey, the mgc RAT package, and the 108-package PolinRider campaign) all sharing blockchain dead-drop infrastructure across Tron, BSC, and Aptos. The underlying technique -- storing and resolving C2 commands via public blockchain transactions instead of seizable domains/IPs (EtherHiding) -- was first documented by Mandiant in October 2025 as a DPRK tradecraft shift, and is formalized in Malpedia as the js.jadesnow (aka ChainedDown) downloader family, attributed to the WageMole/Famous Chollima/UNC5342/PurpleBravo cluster (a Lazarus Group / Contagious Interview offshoot) that typically delivers INVISIBLEFERRET as a follow-on persistent backdoor.

Because command resolution depends on public, unseizable blockchain RPC infrastructure rather than attacker-controlled domains, blocking the observed HTTP C2 IPs alone does not stop the second-stage compromise -- the Tron/BSC/Aptos dead-drop can still deliver a new payload pointer to any already-infected host. Defenders should treat outbound calls to Tron/BSC/Aptos public RPC endpoints from Node.js application processes, and detached `node -e` child-process spawns with `windowsHide`, as high-fidelity detection opportunities independent of any single IP or domain blocklist.

MITRE ATT&CK techniques used in TL-2026-1771

Collection

T1005 Data from Local System

Defense Evasion

T1027 Obfuscated Files or Information; T1027.010 Command Obfuscation; T1140 Deobfuscate/Decode Files or Information; T1564.003 Hidden Window

Exfiltration

T1041 Exfiltration Over C2 Channel

Execution

T1059.007 JavaScript; T1129 Shared Modules

Command and Control

T1071.001 Web Protocols; T1102.001 Dead Drop Resolver; T1105 Ingress Tool Transfer; T1132.002 Non-Standard Encoding; T1571 Non-Standard Port

Initial Access

T1195.001 Compromise Software Dependencies and Development Tools; T1195.002 Compromise Software Supply Chain; T1199 Trusted Relationship

Credential Access

T1552.001 Credentials In Files; T1555 Credentials from Password Stores

Persistence

T1554 Compromise Host Software Binary

Resource Development

T1583.006 Web Services; T1587.001 Malware; T1588.001 Malware; T1608.001 Upload Malware

Affected products and versions in Joyfill npm Packages Compromised with Blockchain C2 Loader

  • Joyfill — @joyfill/components
    Vulnerable versions: version published 2026-07-28T10:54:00Z (unpublished ~2026-07-28T21:00:00Z)
    Fixed in: any version prior to or after the malicious 2026-07-28 publish window
  • Joyfill — @joyfill/layouts
    Vulnerable versions: version published 2026-07-28T11:03:00Z (unpublished ~2026-07-28T21:00:00Z)
    Fixed in: any version prior to or after the malicious 2026-07-28 publish window

Remediation for Joyfill npm Packages Compromised with Blockchain C2 Loader

Patches

  • No vendor patch applicable -- remediation is package version pinning/removal, not a CVE fix (no CVE assigned)

Immediate actions

  • Remove @joyfill/components and @joyfill/layouts if a version published on or after 2026-07-28 10:54 UTC was installed; pin to a known-clean pre-compromise version
  • Purge npm/CI caches and registry mirrors (e.g. registry.npmmirror.com) that may still serve the malicious tarballs after upstream removal
  • Block outbound traffic to 166.88.134.62:443, 198.105.127.210:443, 23.27.202.27:27017, and the related 166.88.54.158:443 from build/CI and application hosts
  • Hunt for detached `node -e` child processes spawned with `windowsHide: true` and `stdio: "ignore"` on developer workstations and CI runners
  • Rotate any credentials or tokens present on machines that resolved the packages during the ~10-hour exposure window

Workarounds

  • Use a private npm proxy/registry with allow-listed package versions to prevent automatic pickup of newly-published malicious versions
  • Enforce lockfile-pinned exact versions with integrity hashes (npm `integrity` / `package-lock.json`) so a hijacked publish cannot be silently pulled in on next install

Longer-term hardening

  • Deploy egress monitoring/alerting for Node.js processes calling Tron (api.trongrid.io), BSC (bsc-dataseed.binance.org, bsc-rpc.publicnode.com), or Aptos (fullnode.mainnet.aptoslabs.com) public RPC endpoints, since this dead-drop C2 pattern is reused across the PolinRider/ChainVeil/ViteVenom campaign family
  • Adopt build-provenance verification (npm provenance, Sigstore, or SLSA attestation) so published bundle contents can be diffed against source-controlled build output
  • Require code review of dist/build artifacts for internally-consumed packages rather than trusting registry-published bundles implicitly
  • Subscribe to SafeDep/OpenSourceMalware/Socket npm-supply-chain advisories for continued PolinRider/JADESNOW infrastructure updates

Weaknesses (CWE) in Joyfill npm Packages Compromised with Blockchain C2 Loader

CWE-506

Timeline of Joyfill npm Packages Compromised with Blockchain C2 Loader

  • Mandiant publishes 'DPRK Adopts EtherHiding: Nation-State Malware Hiding on Blockchains', the first public documentation of the blockchain dead-drop C2 technique underlying the JADESNOW family used in this incident.
  • Cryptocurrency wallet later linked to the ViteVenom/PolinRider campaign family is first activated, per Checkmarx first-observed dating.
  • Compromised npm package 'mgc' deploys a multi-platform RAT, an earlier related incident in the same DPRK npm-supply-chain wave.
  • Sonatype reports a hijacked npm package attempting to deliver a PolinRider-linked RAT payload.
  • astro.config.mjs supply-chain attack disclosed: a malicious pull request against Egonex-AI/Understand-Anything embeds a blockchain dead-drop loader sharing the same primary Tron address and Aptos fallback pattern later reused in the Joyfill compromise.
  • First of seven ViteVenom-branded malicious npm packages (e.g. @uw010010/vite-tree) published, part of the wider PolinRider/SuccessKey npm campaign.
  • Both malicious Joyfill package versions unpublished by approximately 21:00 UTC (~10 hours of live exposure); tarballs remain retrievable via registry mirrors such as registry.npmmirror.com.
  • @joyfill/layouts published at 11:03 UTC with its dist bundle swapped for a 1,271-line malicious replacement of the clean 37,318-line file.
  • @joyfill/components published at 10:54 UTC with 62 lines of obfuscated blockchain-C2 loader code injected into dist/index.cjs.js and dist/index.es.js.
  • The Hacker News, Sonatype, and OpenSourceMalware report the broader PolinRider campaign (108 malicious packages/extensions across npm, Go, Composer, and Chrome), providing further attribution context for the Joyfill incident's operator.
  • SafeDep publishes technical analysis of the Joyfill compromise; Malpedia indexes the incident and formally links it to the js.jadesnow (JADESNOW) malware family.

Update history for TL-2026-1771

  • 2026-08-13 — tweetfeed.live community intel: New TL_OSINT_Scan community intel: 1 newly-corroborated indicator(s), 67 community-related indicator(s).
  • 2026-08-04 — tweetfeed.live community intel: New TL_OSINT_Scan community intel: 1 newly-corroborated indicator(s), 117 community-related indicator(s).

Sources cited for Joyfill npm Packages Compromised with Blockchain C2 Loader

Detection coverage for TL-2026-1771

As of 2026-08-13, Threadlinqs Intelligence publishes 9 detection rule(s) for TL-2026-1771 across Splunk SPL, Microsoft KQL and Sigma, covering 28 indicator(s) of compromise. The whole corpus is readable without an account; a free account unlocks full detection query text in Splunk SPL, Microsoft KQL and Sigma; paid tiers add raw indicator values, correlation and the MCP server. Threadlinqs MCP server · View plans.

9 detection rules (Splunk SPL, Microsoft KQL, Sigma) · Blue and above. Compare plans
28 indicators of compromise · Red and above. Compare plans

Community OSINT corroboration for TL-2026-1771

2 of this threat's indicators have also been reported by the open-source security community, which observed at least one of them before this report was published. Community sightings are unverified and are kept separate from Threadlinqs' curated indicators. Indicator values, reporters and campaign linkage are available to authenticated Red-tier users.

Further reading

Threadlinqs Intelligence — Real-Time Threat Detection Platform

[ 0 threats ] [ 0 det ] [ CRIT: 0 ] [ HIGH: 0 ]
// threat_feed
$ sort --newest
Showing all threats

Live intelligence console

Threat level
Fig. 01 · Threat weatherIndexing the archive…
1 square = 1 threat · click to open

Latest Threats