# Malicious @ethersphere/bee-js 13.3.0 npm Release and Swarm Desktop 0.56.2 Deliver SleepyDuck Ethereum C2 Backdoor

> On 2026-11-09 the Ethersphere release pipeline was abused to publish a malicious @ethersphere/bee-js 13.3.0 npm package (live about 75 minutes, valid SLSA provenance) and a signed, notarized Swarm Desktop 0.56.2 (public about 8.5 hours). Both ran a loader that fetched JavaScript from api.frameworkmetrics.xyz, exfiltrated Bee node config.yaml and swarm.key, and installed a stage 3 backdoor (Go implant on macOS/Linux, ScreenConnect on Windows) linked by Socket to the SleepyDuck/EtherDuck campaign.

- **Published:** 2026-11-09T16:03:00Z
- **Last reviewed:** 2026-11-09T16:03:00Z
- **Canonical:** https://intel.threadlinqs.com/threat/TL-2026-5566
- **Card image:** https://intel.threadlinqs.com/og/threat/TL-2026-5566.png
- **ID:** TL-2026-5566
- **Severity:** CRITICAL
- **Category:** SUPPLY_CHAIN
- **Status:** ACTIVE
- **Actor:** SleepyDuck
- **Detections:** 9 (1 shown free below) · **IOCs:** 26 (3 shown free below)

## Description

Socket Threat Research reports that two GitHub accounts, the maintainer account nugaon and the release automation identity bee-worker, were used to abuse the Ethersphere release pipeline. The origin of both compromises is unexplained and predates 2026-11-06. On 2026-11-06 the actor pushed workflows that dumped secrets and vars to webhook.site collectors plus a pastebin second stage; Socket assesses with moderate confidence nothing was exfiltrated. On 2026-11-08 at 23:59:54 UTC an unsigned commit (de2f74e, authored as bee-worker) turned scripts/generate-version.cjs into a remote loader and renamed the prepare script to postinstall. An unsigned annotated tag v13.3.0 and GitHub release at 00:06:01 UTC on 2026-11-09 triggered the Publish on npm workflow, which accepts release events without branch checks or required reviewers. bee-js 13.3.0 was latest on npm from 00:09:50 to 01:24:58 UTC and carried valid SLSA provenance. The loader also ran three times inside the publish job itself (npm ci postinstall, build, prepublishOnly).

About 30 minutes after the npm publish, branch emergency/0.56.2 added the same loader to src/index.ts of Swarm Desktop. A manually dispatched pre-release workflow with a free-form branch input and no environment protection was given Apple and Windows signing certificates and the notarization Apple ID, and produced signed and notarized assets for Linux (deb/rpm), macOS arm64 (dmg/zip) and Windows x64 (Setup.exe, nupkg, zip). update-electron-app served 0.56.2 to Windows x64 from 00:43:17 UTC and to Apple Silicon Macs from 00:44:49 UTC. The desktop loader runs at the top of main() on every launch in the unsandboxed Electron main process.

The loader sends an HTTPS GET to api.frameworkmetrics.xyz (/v1/analytics for npm, /v1/electron for desktop) with the User-Agent set to the OS platform and a gate header X-Ethersphere: 1; without the header the server returns a decoy. The response is compiled with new Function and run with the real require, console and process. Stage 2 JavaScript locates the Swarm Desktop data directory, POSTs config.yaml and data-dir/keys/swarm.key to /v1/swarm/report (config.yaml stores the keystore password in plaintext, exposing the node wallet), and downloads the OS-specific stage 3 implant from /v1/assets/. On macOS and Linux the stage 3 is a Go backdoor (module evjawbreaker) written to ~/.solidity/, persisted via systemd user unit solidity-langsupport-runner.service or LaunchAgent com.solidity.langsupport.runner, which exits on debugger or VM detection, resolves its hub address from an Ethereum contract via public RPC gateways, and connects over TLS without certificate validation to run operator commands in a persistent sh pseudo-terminal. On Windows an obfuscated PowerShell loader (invoke.ps1) uses UACME method 39 (COR_PROFILER against mmc.exe) for local admins or a repeated UAC prompt otherwise, adds a Defender exclusion, and silently installs a genuine ConnectWise-signed ScreenConnect 25.4.3 client configured for relay 185.232.84.169:8041 as SYSTEM service ScreenConnect Client (5cbe79c9c25524df).

Attribution to the SleepyDuck/EtherDuck campaign (documented by Pluto Security on 2026-10-01) rests on a shared Ethereum config contract (0xf8a900Db50b3331be6B768bA460BB59f3E40C344) whose write history matches Pluto's report, six of seven matching payload hashes, identical persistence names, ScreenConnect instance ID and relay. The contract hub was updated to 193.57.9.155:4912 at 23:30:47 UTC on 2026-11-08, 29 minutes before the malicious commit. The campaign targets Ethereum tooling and wallet developers and has moved from fake Open VSX extensions to compromising a real project's release pipeline. No CVE has been assigned; GitHub advisory GHSA-hh7j-5m3j-23pf (CWE-506) covers bee-js 13.3.0 with no patched version. A BeaconBeagle lookup for 193.57.9.155 returned HTTP 502 and could not be used. Pluto's report was fetched and its details (contract, hashes, persistence) are consistent with Socket's account.

## MITRE ATT&CK

- T1583.001 Domains
- T1195.002 Compromise Software Supply Chain
- T1078 Valid Accounts
- T1059.007 JavaScript
- T1059.001 PowerShell
- T1059.004 Unix Shell
- T1543.001 Launch Agent
- T1543.002 Systemd Service
- T1543.003 Windows Service
- T1548.002 Bypass User Account Control
- T1036 Masquerading
- T1553.002 Code Signing
- T1685 Disable or Modify Tools
- T1497.001 System Checks
- T1622 Debugger Evasion
- T1552.004 Private Keys
- T1102.001 Dead Drop Resolver
- T1071.001 Web Protocols
- T1219 Remote Access Tools

## Free detection (Splunk SPL, Microsoft KQL, Sigma)

**SleepyDuck Loader: frameworkmetrics.xyz Contact or generate-version.cjs Postinstall Execution** (`TL-2026-5566-SPL-001`)

Behaviour-first hunt for the first stage of the Ethersphere release-pipeline compromise: a Sysmon DNS lookup or connection to api.frameworkmetrics.xyz (the loader/stage 2/stage 3 delivery host gated by an X-Ethersphere: 1 header), or node.exe executing the trojanized scripts/generate-version.cjs postinstall loader shipped in @ethersphere/bee-js 13.3.0. A hit on a developer workstation or CI runner during or after 2026-11-09 means the host ran the loader, which exfiltrates Bee config.yaml and swarm.key and installs a SleepyDuck stage 3 backdoor.

- **Languages:** Splunk SPL, Microsoft KQL, Sigma
- **ATT&CK:** T1195.002, T1071.001, T1583.001, T1105
- **Data sources:** sysmon:EventID 1 (process creation), sysmon:EventID 3 (network connection), sysmon:EventID 22 (DNS query)
- **Severity:** critical
- **Confidence:** high

### Splunk SPL

```spl
((index=sysmon sourcetype="XmlWinEventLog:Microsoft-Windows-Sysmon/Operational") OR (index=wineventlog sourcetype="XmlWinEventLog:Microsoft-Windows-Sysmon/Operational"))
    ((EventCode=22 (QueryName="frameworkmetrics.xyz" OR QueryName="*.frameworkmetrics.xyz"))
     OR (EventCode=3 Initiated=true DestinationHostname="*frameworkmetrics.xyz")
     OR (EventCode=1 Image="*\\node.exe" CommandLine="*generate-version.cjs*"))
| eval signal=case(EventCode=22,"dns_lookup_loader_host",EventCode=3,"connect_loader_host",EventCode=1,"npm_postinstall_loader_exec")
| stats earliest(_time) as first_seen latest(_time) as last_seen values(signal) as signals values(Image) as processes values(CommandLine) as command_lines values(QueryName) as dns_queries values(DestinationHostname) as dest_hosts count by host, User
| eval first_seen=strftime(first_seen,"%Y-%m-%d %H:%M:%S"), last_seen=strftime(last_seen,"%Y-%m-%d %H:%M:%S"), threat="TL-2026-5566 bee-js 13.3.0 / Swarm Desktop 0.56.2 SleepyDuck loader"
| table first_seen last_seen host User signals processes command_lines dns_queries dest_hosts count threat
```

### Microsoft KQL

```kql
let LoaderDomains = dynamic(["api.frameworkmetrics.xyz", "frameworkmetrics.xyz"]);
union
(
    DeviceNetworkEvents
    | where Timestamp > ago(24h)
    | where RemoteUrl has_any (LoaderDomains)
    | extend Signal = "network_to_loader_host"
    | project Timestamp, DeviceName, AccountName = InitiatingProcessAccountName, Process = InitiatingProcessFileName, CommandLine = InitiatingProcessCommandLine, RemoteUrl, RemoteIP, RemotePort = tostring(RemotePort), Signal
),
(
    DeviceProcessEvents
    | where Timestamp > ago(24h)
    | where FileName in~ ("node.exe", "node") and ProcessCommandLine has "generate-version.cjs"
    | extend Signal = "npm_postinstall_loader_exec"
    | project Timestamp, DeviceName, AccountName, Process = FileName, CommandLine = ProcessCommandLine, RemoteUrl = "", RemoteIP = "", RemotePort = "", Signal
)
| order by Timestamp desc
```

### Sigma

```yaml
title: SleepyDuck Loader Host frameworkmetrics.xyz DNS Lookup
id: 7c1f4a52-3b9e-4d68-a1c7-5e2b90d4f6a1
status: experimental
description: Detects DNS resolution of frameworkmetrics.xyz and api.frameworkmetrics.xyz, the host used by the malicious @ethersphere/bee-js 13.3.0 and Swarm Desktop 0.56.2 loaders (TL-2026-5566) to deliver stage 2 and stage 3 payloads and to receive stolen Bee node keys.
references:
    - https://socket.dev/blog/bee-js-compromise
    - https://github.com/advisories/GHSA-hh7j-5m3j-23pf
    - https://pluto.security/blog/sleepyduck-malware-open-vsx-extensions/
author: Threadlinqs Team
date: 2026/11/09
tags:
    - attack.initial-access
    - attack.t1195.002
    - attack.command-and-control
    - attack.t1071.001
    - attack.t1105
    - attack.resource-development
    - attack.t1583.001
logsource:
    category: dns_query
    product: windows
detection:
    selection:
        QueryName|endswith: '.frameworkmetrics.xyz'
    selection_apex:
        QueryName: 'frameworkmetrics.xyz'
    condition: 1 of selection*
falsepositives:
    - Security researchers or analysts deliberately resolving the IOC domain from a sandbox
level: high

```

**Known false positives:**

- Security researchers or threat-intel sandboxes deliberately resolving the IOC domain
- Legitimate project with its own scripts/generate-version.cjs that runs under npm (name collision on the script file only)

**Tuning notes:** Search is Windows/Sysmon based; for macOS and Linux developer hosts and CI runners run the same domain logic against DNS resolver, proxy (Web datamodel) or EDR network telemetry. Point the index at your Sysmon index (index=sysmon or index=wineventlog). If a project legitimately ships generate-version.cjs, require the dns/connect signals or add its repo path as an exclusion. Alert at critical severity with no threshold: any hit should trigger credential rotation.

### 8 more detection rules (Splunk SPL, Microsoft KQL, Sigma), unlock with TL Creds

- Malicious bee-js 13.3.0 Postinstall: npm Lifecycle Script Running generate-version.cjs (locked: unlock with TL Creds)
- SleepyDuck Windows Stage 3: UACME 39 COR_PROFILER UAC Bypass and Microsoft Defender Exclusion (locked: unlock with TL Creds)
- SleepyDuck EtherHiding Dead Drop: eth_call to Config Contract 0xf8a900Db... / Backdoor Querying Ethereum RPC (locked: unlock with TL Creds)
- SleepyDuck Stage 2: Bee Node swarm.key and config.yaml Exfiltration via [indicator] (locked: unlock with TL Creds)
- SleepyDuck Windows Stage 3: Silent ScreenConnect 25.4.3 Install with Attacker Relay [indicator]:8041 (locked: unlock with TL Creds)
- SleepyDuck evjawbreaker Go Backdoor Execution from ~/.solidity (Linux/macOS) (locked: unlock with TL Creds)
- SleepyDuck Stage 3 Persistence: solidity-langsupport-runner systemd Unit and com.solidity.langsupport.runner LaunchAgent (locked: unlock with TL Creds)
- SleepyDuck C2: evjawbreaker Hub (TCP 4912), Payload Host (TCP 3000) and ScreenConnect Relay ([indicator]:8041) Connections (locked: unlock with TL Creds)

Sign up free to unlock the detection rules: https://threadlinqs.com/?modal=signup

## Sample indicators (3 of 26)

Defanged, TLP:CLEAR.

- IP address: `193.57.9[.]155`
- Domain: `frameworkmetrics[.]xyz`
- File hash: `d01fdf241aa9e0a1ba6ebc19f8f667af1bf652745021c5050126cb7036f7ce58`

Full set of 26 indicators unlocks with TL Creds: https://threadlinqs.com/tl-creds

## Sources

- [Malicious bee-js npm Release and Swarm Desktop Releases Deliver SleepyDuck Ethereum C2 Backdoor](https://socket.dev/blog/bee-js-compromise)
- [GHSA-hh7j-5m3j-23pf: Malware in @ethersphere/bee-js](https://github.com/advisories/GHSA-hh7j-5m3j-23pf)
- [SafeDep: Ethersphere bee-js npm compromise](https://safedep.io/blog/ethersphere-bee-js-npm-compromise)
- [Pluto Security: SleepyDuck malware in Open VSX extensions (EtherDuck)](https://pluto.security/blog/sleepyduck-malware-open-vsx-extensions/)
- [Hive Pro: SleepyDuck Trojan Nesting in the Open VSX Marketplace](https://hivepro.com/threat-advisory/sleepyduck-trojan-nesting-in-the-open-vsx-marketplace/)
- [SC World: SleepyDuck RAT deployed via bogus Solidity VSCode extension](https://www.scworld.com/brief/sleepyduck-rat-deployed-via-bogus-solidity-vscode-extension)

## Full data

The other 8 detection rules (Splunk SPL / Microsoft KQL / Sigma) unlock with TL Creds; a free account includes daily creds: https://threadlinqs.com/?modal=signup
Indicator values unlock with TL Creds, at a lower price on Red and Purple; AI agents can query rules and IOCs through the Threadlinqs MCP server (Purple): https://intel.threadlinqs.com/mcp

Canonical: https://intel.threadlinqs.com/threat/TL-2026-5566
