Skip to content
Compromised bee

Compromised bee

Safedep • November 9, 2026

@ethersphere/bee-js is the JavaScript client for the Swarm storage network. Version 13.3.0 runs attacker code on install. A new postinstall hook downloads a second stage that steals the Swarm node’s wallet key and installs a backdoor. On Linux and macOS, the backdoor is a Go remote shell. On Windows, it is a hidden ScreenConnect client that runs as SYSTEM.

30 minutes later, the attacker put the same malicious code in Swarm Desktop 0.56.2.

The project’s own release workflow published 13.3.0 with a valid npm provenance attestation. The project’s release bot, bee-worker , made the release commit. This points to a compromised bot account or token, not a stolen npm token.

npm removed 13.3.0. The last clean version is 13.2.0 , and latest points to it again.

bee-worker made commit de2f74e ⁠ (opens in new tab) at 23:59:54 UTC on 2026-11-08, with the message chore(upcoming): release 13.3.0 and no signature. No branch contains it. It looks like a normal release bump, but two changes in package.json make the attack work:

With postinstall , the script runs on every install. With scripts in files , the script ships in the package.

How it reached npm with provenance

The malicious code never went onto a branch. It went to npm through a GitHub release:

bee-worker made commit de2f74e , a v13.3.0 tag for it and a GitHub release for the tag, all in the same second.

The published release started the project’s npm workflow, publish_npmjs.yaml ⁠ (opens in new tab) .

The workflow built the commit and published it to npm at 00:09 UTC with provenance. It runs tests only for code pushed to a branch, so it ran none here.

Branch protection did not stop this, because the attacker did not use a branch. Anyone who can create a release in this repository can publish code to npm with provenance.

The attacker added 18 lines to the top of the script ⁠ (opens in new tab) :

The hook downloads code and runs it with Node’s real require and process , as the same user as npm install .

The User-Agent is only the OS name ( linux , darwin or win32 ), so the server can send a different payload for each OS. The X-Ethersphere: 1 header unlocks the payload. Without it, the server sends a harmless decoy.

The hook ignores all errors and timeouts, so the install never shows a problem. Its call the request an “analytics ping”.

Stage 2: wallet key theft and a backdoor

The stage-2 payload is plain JavaScript, with one file for each OS. It does two things.

It steals the Swarm node’s wallet key. It reads config.yaml and data-dir/keys/swarm.key from the Swarm Desktop data folder and sends both to /v1/swarm/report . swarm.key is an encrypted Ethereum keystore, and Swarm Desktop keeps its password in plain text in config.yaml . With both files, the attacker has the node’s private key and can take the wallet’s xDAI and xBZZ, the chequebook funds and the stake.

The macOS and Windows variants differ only in the base folder:

It installs a backdoor that survives reboots.

On Linux, each later run repairs the systemd unit if someone changed it.

Stage 3: the implants

The evjawbreaker implant on Linux and macOS

The Go implant, evjawbreaker , is a remote shell. It connects to a “hub” over TLS without checking the certificate. It runs sh in a pseudo-terminal, runs the commands the hub sends and returns the output. If it finds a debugger or a virtual machine, it exits before it connects.

The implant has no built-in server address. It reads the hub address from an Ethereum smart contract, 0xf8a900Db50b3331be6B768bA460BB59f3E40C344 , through public RPC endpoints such as rpc.ankr.com and cloudflare-eth.com . Defenders have no domain to take down, and the operator can move the hub with one transaction. The disassembly shows the contract address and the getter the implant calls:

The operator is not new. They deployed the contract on 2026-03-14, and it has pointed to seven hubs since. They set the current hub, 193.57.9.155:4912 , at 23:30 UTC on 8 Nov, 29 minutes before the malicious bee-js commit.

ScreenConnect on Windows

Windows gets two files. The first, invoke.ps1 , is an obfuscated PowerShell script that gets admin rights:

If the user is an administrator, it uses a public UAC bypass, UACME method 39. This method hijacks the .NET profiler of mmc.exe , which starts with admin rights.

If not, it shows the UAC prompt again each time the user cancels it.

With admin rights, the script adds a Defender exclusion, installs app.msi silently, then removes the exclusion and its staging files.

The second file, app.msi , is a real ScreenConnect 25.4.3 client signed by ConnectWise. The attacker changed only its settings:

It connects to a relay at 185.232.84.169:8041 .

It hides its tray icon and its connection banners.

It starts sessions without asking the user.

It runs as a SYSTEM service, so the attacker gets full remote control. Onidel in the Netherlands hosts both the relay and the current evjawbreaker hub.

The ScreenConnect program files are legitimate, so their hashes are not useful for detection. Detect the relay address, the service instance ID and the configuration file hashes instead.

Swarm Desktop 0.56.2 is also malicious

At 00:36 UTC, 30 minutes after bee-js, bee-worker published Swarm Desktop v0.56.2 as an “emergency patch release”. Its commit, 2de7270 ⁠ (opens in new tab) , has no signature and no pull request. It adds the same loader to the app’s main() function, which calls /v1/electron each time the app starts.

The amd64 .deb has the loader in its app.asar file. The other installers come from the same build and probably contain it too. At 06:58 UTC on 9 Nov, GitHub still showed v0.56.2 as the current release. The Windows auto-updater file had 17 downloads, so existing installs may have updated to it. Swarm Desktop users have the exact wallet files that stage 2 steals.

Our detection timeline

Our Automated Investigation confirmed it as malicious four minutes after publish, 70 minutes before npm removed it.

If you installed either one

Treat the machine as compromised.

Move the Swarm node’s funds and stake to a new key. Treat the old key as stolen.

Remove the backdoor: the ~/.solidity/ folder and its systemd unit or LaunchAgent, or the ScreenConnect Client (5cbe79c9c25524df) service on Windows.

Indicators of compromise

Stage 1: package and files

Stage 1: repository and CI

The CSV has 65 indicators from the payloads, the implants, the C2 contract and the Swarm Desktop release. It leaves out the wallet that funded the operator. That wallet has more than 266,000 transactions, so it is probably an exchange wallet and not attacker infrastructure.

Extracted Entities