NEW

Panther joins Databricks to build the future of the security lakehouse. Read more →

close

Panther joins Databricks to build the future of the security lakehouse. Read more →

close

Panther joins Databricks to build the future of the security lakehouse. Read more →

close

BLOG

A Patient Trojan Dropper: polymarket-stake-math Steals Wallet Keys, Browser Sessions, and Telegram from Crypto Developers

Ariel

Ropek

TL;DR: polymarket-stake-math is a two-stage npm supply chain attack against cryptocurrency and prediction-market developers. It poses as a Kelly criterion stake-sizing helper for Polymarket and was published by the throwaway npm account haha1999. Over roughly 12 hours on 2026-06-23 the attacker escalated through six versions, shipping a clean, working math library first, then injecting a 2,255-line infostealer (collector.js) in a later version that harvests browser passwords and cookies, crypto wallets, Telegram sessions, shell history, and cloud/dev credentials. A postinstall dropper pulls the payload after the fact, and within 12 hours the attacker pivoted delivery from npm to a Vercel-hosted C2 it can hot-swap at will. A sibling package, decimal-format-utils, carries the identical stealer code, confirming an active campaign. This is the latest entry in a sustained 2026 wave of Polymarket-themed npm malware.

What happened

On 2026-06-23, an npm account named haha1999 (sahautpol33@gmail[.]com) published polymarket-stake-math, a package presenting itself as a stake-sizing utility built on the Kelly criterion, exactly the kind of helper a developer writing Polymarket trading logic would search for. Panther Threat Research identified it during routine supply chain monitoring.

The package did not start out malicious, and that is the point. Its first two versions were clean, functional Kelly math with no install hooks. The payload arrived only in later versions, published minutes apart, before delivery pivoted to attacker-controlled infrastructure the following morning. The staging is deliberate: a reviewer who glances at an early release sees a legitimate library.

The lure goes back further than the package itself. The attacker's GitHub repository, FrondEnt/PolymarketBTC15mAssistant, was created on 2026-01-29 nearly five months before the npm packages appeared. It is a credible-looking Polymarket trading terminal with a detailed README, proxy documentation, and a real commit history, and the malicious packages cite it as their source. A developer who finds the repo first sees social proof, not a fresh throwaway account.

Date / time (UTC)

Version

Event

2026-01-29

Lure repo FrondEnt/PolymarketBTC15mAssistant created on GitHub

2026-06-22

Sibling package decimal-format-utils published with identical stealer code

2026-06-23 19:58

v3.1.0

Pure Kelly math, no postinstallbenign bait

2026-06-23 19:58

v3.3.0

Refactored to kelly.js, still clean — benign bait

2026-06-23 19:58

v3.4.0

collector.js infostealer injected (2,255 LOC) — malicious

2026-06-23 19:58

v3.5.0

postinstall dropper pulls v3.4.0 from npm — malicious

2026-06-24 08:04

v3.5.1

Dropper pivots to Vercel-hosted C2 — malicious

Who is targeted

The direct targets are developers building on Polymarket and adjacent crypto tooling. These are the people most likely to search npm for a Kelly stake-sizer or a decimal-math helper, and the people most likely to keep wallet keys, exchange sessions, and exchange API credentials on the same machine they develop on. The stealer's own source makes the targeting explicit: a code comment notes that traders keep exchange sessions in secondary browser profiles, and the collection logic walks all browser profiles rather than just the default.

The indirect targets are everyone whose funds those developers can move. A stolen wallet seed phrase or private key is a direct path to draining an account; a stolen exchange or Polymarket session is a path to hijacking trades. Because the payload also sweeps cloud and CI credentials (AWS secrets, npm _authToken, GitHub ghp_ tokens, PyPI tokens) a single compromised developer can become a pivot into the organizations and pipelines they have access to.

How it works

The attack separates the installer from the payload using a classic two-stage trojan dropper. That separation is what lets the early versions stay clean and the later ones stay quiet.

Stage 1: the dropper. A postinstall hook ("postinstall": "node scripts/sync-peer.cjs") fires on install. In v3.5.0 (sync-peer.cjs) the dropper downloads a pinned version of the same package from the npm registry, extracts it to a temporary directory, and overwrites the installed package files with the payload version, defaulting to the infostealer build v3.4.0. Critically, every parameter of that fetch is controllable through environment variables (BACKUP_PACKAGE_NAME, BACKUP_TARGET_VERSION, TARGET_VERSION, BACKUP_PAYLOAD_SPEC, BACKUP_INSTALL_FAST), so the operator can redirect any victim to any payload at any time without republishing.

Stage 1: evolved. Within 12 hours, v3.5.1 (verify-peer.cjs) abandoned npm as the delivery channel and began fetching the payload tarball directly from hxxps://vercel-backend-myapp[.]vercel[.]app/releases/psm-peer.tgz, with the C2 URL itself overridable via PSM_API_URL / PSM_PEER_URL. Moving off npm reduces the attacker's exposure to registry takedowns and gives them a persistent, hot-swappable payload server. The speed of the pivot (roughly half a day) suggests operational awareness of supply chain scanning.

Stage 2: the infostealer. The payload, collector.js, is 2,255 lines and, notably, unobfuscated, a sign of confidence that the package will execute before anyone inspects it. It is a comprehensive, professionally built stealer. What it collects:

  • Browser credentials and sessions. Chromium Login Data, Cookies, Web Data, and Local State (which holds the DPAPI-wrapped AES key used to decrypt Chrome v80+ cookies) across all profiles; Firefox logins.json, key4.db, and cert9.db.

  • Crypto wallets. Desktop wallets including Ledger, Trezor, Exodus, MetaMask, Phantom, and Solflare, plus the MetaMask browser extension targeted directly by extension ID (nkbihfbeogaeaoehlefnkodbefgpgknn).

  • Crypto keys by pattern. A regex sweep for EVM private keys (0x + 64 hex), Solana 64-element secret arrays, and BIP39 12/24-word mnemonics, including Hardhat/Foundry mnemonics.

  • Telegram. The full tdata directory (sessions, contacts, encrypted messages) on Windows and macOS.

  • Shell history. Bash, Zsh, sh, Fish, and PowerShell history across Linux, macOS, and Windows.

  • Cloud and developer secrets. AWS_SECRET_ACCESS_KEY, generic API_KEY / API_SECRET / ACCESS_TOKEN, npm _authToken, GitHub ghp_ tokens, and PyPI tokens, plus .env and config files in the current project (with .git, coverage, terraform, and similar directories excluded to cut noise).

  • Clipboard. Periodic clipboard capture governed by CLIPBOARD_MONITOR_MS.

Exfiltration. Collected files are chunked by size and POSTed as HTTP multipart form-data to the C2. The package's only two real runtime dependencies, axios and form-data (both added in v3.4.0), exist solely to support this. A marker file (TDATA_SENT_MARKER) tracks what has already been sent to avoid duplicate uploads, and a BACKUP_TDATA_FORCE=1 switch forces re-exfiltration.

Key finding: a benign-first staging pattern that defeats snapshot review

Most supply chain detection and human review looks at a package as it exists at a single point in time. This campaign is built to beat exactly that. The first published versions are genuinely clean and functional; the payload is introduced in a later version, and the dropper can swap it again post-install. A developer who audits the version they think they installed may be looking at code the dropper has already replaced.

Why this matters: Verifying a package once, at install time or in a one-shot scan, is not sufficient. Detection has to account for what a package does after install (network egress, file overwrites in node_modules, child processes spawned by install hooks) not just what its published source looks like.

Key finding: environment-variable indirection turns one package into a delivery platform

The dropper hardcodes nothing it doesn't have to. Package name, target version, payload spec, and C2 URL are all overridable at runtime through environment variables. That design lets the same published artifact serve different payloads to different victims and lets the operator move infrastructure without touching the registry.

Why this matters: IOC-only defenses that pin to a single C2 domain or a single payload hash will age out fast against an actor who has engineered for hot-swapping. Behavioral signals (install-time network activity, post-install file rewrites) are more durable than any single indicator here.

Campaign scope: decimal-format-utils

The same collector.js stealer appeared one day earlier, on 2026-06-22, in decimal-format-utils, published under the same haha1999 account. That package impersonates the widely-used big.js decimal-math library: it lists the legitimate big.js maintainer in its author field and points its repository URL at the real MikeMcl/big.js project. This is a package-identity spoof aimed at developers who pull in decimal-math utilities.

Package

First seen

Versions

Technique

Impersonation target

polymarket-stake-math

2026-06-23

6 (3.1.0–3.5.1)

Trojan dropper + infostealer

Polymarket / Kelly criterion utility

decimal-format-utils

2026-06-22

2 (1.0.0–1.0.1)

Infostealer + postinstall dropper

big.js / decimal-math utility

Shared stealer code plus a shared publisher account ties these two packages to one operator. The broader pattern of Polymarket-themed lures, throwaway publisher accounts, wallet-and-credential theft, and a pivot to Vercel-hosted exfiltration also echoes other Polymarket-targeting npm campaigns documented across 2026, including a hijacked-GitHub-org campaign that likewise exfiltrated to Vercel endpoints. We are not asserting a single shared operator across those campaigns; we note the convergence in tradecraft and the clear, sustained focus on this developer population.

Who is behind this

We attribute both packages to a single financially motivated actor operating under the npm handle haha1999 and the GitHub identities FrondEnt and Krajekis. The two GitHub display names share one email (sixhotcats@gmail[.]com) and alternate across the same commit history, indicating one identity. We are not attributing this actor to a named APT or nation-state group; the targeting (crypto wallets, exchange sessions, Telegram) and the absence of persistence or espionage tooling are consistent with direct financial theft.

The five-month gap between the GitHub lure repo (2026-01-29) and the npm publication (2026-06-23) indicates premeditation rather than opportunism: the credibility scaffolding was built and aged before the payload shipped.

Detection

Panther Threat Research recommends the following detection and hunting approaches. These favor behavior over single indicators, given the actor's demonstrated hot-swapping:

  • node spawned by an npm install hook making outbound network connections. Flag node processes whose parent is an npm/yarn/pnpm install lifecycle and that make outbound HTTP/S or DNS requests to novel domains. Covers MITRE ATT&CK T1195.002 (Compromise Software Supply Chain) and T1105 (Ingress Tool Transfer). (Panther rule: npm_install_hook_network_egress.)

  • Post-install file rewrites inside node_modules. Alert when a package's own files are overwritten shortly after install by a process extracting from a temp path (e.g. /tmp/psm-sync-*) — the dropper's signature behavior.

  • node reading browser credential and wallet stores. Alert on node accessing Login Data, Cookies, Local State, Firefox key4.db/logins.json, or wallet directories (MetaMask, Ledger, Exodus, Phantom) and Telegram tdata. Covers T1555.003 (Credentials from Web Browsers), T1539 (Steal Web Session Cookie), and T1005 (Data from Local System).

  • node reading shell history or .env outside the project root. Covers T1552.001 (Credentials in Files) and T1552.003 (Bash History).

  • Outbound multipart POST to the known C2. Block or alert on traffic to vercel-backend-myapp[.]vercel[.]app, and more durably, flag large multipart uploads to newly-seen domains immediately following an install event. Covers T1567 (Exfiltration Over Web Service). (Panther rule: npm_c2_vercel_backend_myapp.)

Indicators of Compromise

IOC

Type

Notes

polymarket-stake-math

npm package

Malicious — all versions 3.1.0–3.5.1

decimal-format-utils

npm package

Malicious — all versions 1.0.0–1.0.1

haha1999

npm publisher account

Throwaway publisher of both packages

sahautpol33@gmail[.]com

Email

npm account email

sixhotcats@gmail[.]com

Email

GitHub account email (FrondEnt / Krajekis)

FrondEnt (GitHub ID 109918389)

GitHub account

Lure-repo owner

Krajekis

GitHub persona

Same actor; shares email with FrondEnt

FrondEnt/PolymarketBTC15mAssistant

GitHub repo

Social-proof lure, created 2026-01-29

vercel-backend-myapp[.]vercel[.]app

Domain

C2 (introduced v3.5.1)

hxxps://vercel-backend-myapp[.]vercel[.]app/releases/psm-peer.tgz

URL

Payload tarball

scripts/sync-peer.cjs

File

Dropper (v3.5.0)

scripts/verify-peer.cjs

File

Dropper + C2 fetch (v3.5.1)

collector.js

File

Infostealer payload (2,255 LOC)

/tmp/psm-sync-*

Path

Dropper staging directory

TDATA_SENT_MARKER

File

Exfiltration state tracker

PSM_PEER_URL, PSM_API_URL

Env var

C2 override

BACKUP_PACKAGE_NAME, BACKUP_TARGET_VERSION, TARGET_VERSION, BACKUP_PAYLOAD_SPEC, BACKUP_INSTALL_FAST, BACKUP_TDATA_FORCE

Env vars

Dropper / exfil overrides

If you have installed either package: Remove it immediately, but treat removal as insufficient. Assume everything the stealer targets has been exfiltrated and rotate accordingly: browser-saved passwords and active sessions (force log-outs), every credential in your .env and project config files, npm/GitHub/PyPI tokens, and AWS keys. Move any crypto holdings to a new wallet generated on a clean machine: any seed phrase, private key, or wallet file present on the affected host must be considered compromised. Clear and re-authenticate Telegram sessions. Because the dropper can replace the on-disk package after install, inspect the actual contents of the installed package directory rather than trusting the version number.

Stay in the Loop

Read the latest from Panther's Threat Research Team

Share:

Threat Research

Bolt-on AI closes alerts. Panther closes the loop.

See how Panther compounds intelligence across the SOC.

Bolt-on AI closes alerts. Panther closes the loop.

See how Panther compounds intelligence across the SOC.

Bolt-on AI closes alerts. Panther closes the loop.

See how Panther compounds intelligence across the SOC.

Bolt-on AI closes alerts. Panther closes the loop.

See how Panther compounds intelligence across the SOC.

Get product updates, webinars, and news

By submitting this form, you acknowledge and agree that Panther will process your personal information in accordance with the Privacy Policy.

Get product updates, webinars, and news

By submitting this form, you acknowledge and agree that Panther will process your personal information in accordance with the Privacy Policy.

Get product updates, webinars, and news

By submitting this form, you acknowledge and agree that Panther will process your personal information in accordance with the Privacy Policy.