All posts

How Frontend Hacks Drain Wallets, and How to Check a Site

The contract was fine and the site was real, yet users lost funds. How third-party scripts, CDNs and DNS turn a trusted page into a drainer, and what to check.

10 min read

The contract can be audited, the domain can be the real one, and you can still be drained by the page. Most of the money lost to frontend hacks never touched a bug in a smart contract. It left through a signature, an approval or a session that the user gave to a site they had every reason to trust.

Quick answer

A web page runs every script it loads with its own rights. If one of those scripts is swapped, by a hacked vendor, a hacked CDN, a hacked npm account or a hijacked domain, the real site starts asking you to sign the attacker’s transactions. Protect yourself by keeping little on email-login and connected wallets, reading every signature, and reloading after any incident. Ask a venue what loads next to its trade button.

A recent example

On Oct 29, 2026, the page-speed monitoring script that polymarket.com loaded from its vendor, DebugBear, was replaced with a drainer. According to defiprime’s on-chain breakdown, for about 50 minutes:

  • Email-login users had their positions sold with no prompt at all. The script used the session already in the page and Polymarket’s own order client.
  • External-wallet users were shown a signature request that moved all their outcome tokens to the attacker in one batch.
  • An hour after it started, the attacker’s address held about $2.6M in POL. Polymarket shipped a build without the script; DebugBear asked its customers to remove the tag.

No contract was touched, and polymarket.com was the real polymarket.com. It was Polymarket’s second incident of this kind in 2026: in June a compromised third-party vendor drained about $3M from fewer than 15 accounts, and Polymarket promised full refunds. The current status is on the Polymarket page.

Why can a monitoring script touch your money?

A script on a page is not a guest. It is the page.

  • Anything loaded with a <script> tag runs with the same rights as the site’s own code. It can read what the site keeps in your browser, call the site’s own functions and draw a signature request that looks exactly like the real one.
  • The browser cannot tell a page-speed tool from the trade button. Your wallet extension sees a request from the right domain and shows it.
  • There is a defence, Subresource Integrity: the site pins a hash of the file, and the browser refuses to run a changed copy. Vendors update their files on their side, so their tags are almost never pinned. A self-hosted file with a pinned version is the safe pattern; a live tag from someone else’s server is not.

Four ways the code gets in

Way in Cases What happened Lost
The project’s own hosting or CDN BadgerDAO (2021) A stolen Cloudflare API key; a script injected into the app’s HTML asked users for approvals $116M to $130M
Bybit via Safe{Wallet} (2025) JavaScript served from Safe’s AWS S3 bucket rewrote one multisig transaction at signing about $1.46B
A vendor’s script KyberSwap (2022) A malicious tag pushed through Google Tag Manager, aimed at large wallets about $265K
Polymarket (Jun and Oct 2026) A third-party script, then the DebugBear monitoring tag about $3M, about $2.6M
Polyfill.io (2024) The CDN domain changed owners and served malware to over 100,000 sites not stated
npm or a public CDN with no pinned version Ledger Connect Kit (2023) A phished former employee’s npm account; dApps loaded connect-kit@1 from a public CDN, so the bad release reached them at once about $600K
Lottie Player (2024) A stolen npm token; the animation library asked visitors to connect a wallet 10 BTC from one victim
chalk and debug (2025) A phished maintainer; 18 popular packages swapped wallet addresses in the browser small
DNS or the registrar Curve (2022, 2025), Balancer (2023), Galxe (2023) The real domain pointed to a cloned frontend tens of thousands to about $570K per case

Two of these are disputed, so read them with care:

  • Bybit: Safe says its smart contracts and the source code of its frontend were not compromised. Independent analyses, among them SlowMist’s, found the JavaScript files served from its S3 bucket had been replaced and put back about two minutes after the theft.
  • Amounts differ between sources. Where they do, the table shows a range or “about”.

The pattern repeats across all four:

  • The way in is a person, not a server. A phished maintainer, a former employee’s login, a developer’s laptop.
  • The target is often one wallet. KyberSwap’s script hunted large holders. The Bybit code woke up only for Bybit’s multisig.
  • The code cleans up after itself. It lives for minutes or hours, so a site that is clean today says little about yesterday.

Three kinds of scripts to watch

Most of what a crypto app loads is ordinary: big-platform pixels, Cloudflare, captchas, sign-in buttons. They run with full page rights too, but they come from large companies and rarely change. Three kinds carry more weight:

  1. Tools that watch everything. Session recorders and monitoring agents (Hotjar, Microsoft Clarity, FullStory, New Relic, Datadog RUM, DebugBear). They load early, read the whole page and send it out. This is the class that hit Polymarket.
  2. Code from a source that is easy to swap. A raw cloud storage bucket, a public npm CDN without a pinned version, a domain with no brand behind it. A bucket is how Bybit lost $1.46B; an unpinned CDN link is how the Ledger drainer reached many dApps in one afternoon.
  3. Ad networks and web3 tracking tags. They load code chosen by a third party, sometimes a fourth, next to the button that moves your money.

These are established products used across the web, and most sites that load them are never hit. A script of these kinds is not a sign of a hack or of bad intent. It measures how many other companies a page depends on: each one is a door that someone else holds the key to.

How to check a site yourself

You do not need to read code. In a desktop browser:

  1. Open the page where you trade or log in, then the developer tools (F12) and the Network tab. Filter by JS and reload.
  2. Look at the domains. The venue’s own domain and its CDN are expected. Note anything else.
  3. Search the names you do not know. A session recorder, an ad network or a bare storage bucket on a trade page is worth a question to the team.
  4. Fewer outside domains is better. A trade page with none is possible: several venues ship exactly that.

The check has limits. Trackers can load after you accept cookies or log in, and a tag manager can pull in new scripts at any time without a release.

The checklist for users

  • Treat email login as a hot wallet you do not control. It can sign with no prompt. Keep on it only what you trade this week.
  • Read every signature, even on a site you know. A batch transfer of your tokens or an unlimited approval is never part of a normal trade. If you cannot tell what it does, reject it.
  • Revoke approvals you do not use. Revoke.cash lists them by wallet and chain.
  • After an incident, close every tab of that site and reload. An open tab keeps the old script until it reloads. Then wait for the team’s all-clear before you sign anything.
  • Ignore “refund” and “claim” messages. A DM, an email or a link offering compensation after a hack is the second wave. Refunds are announced on the project’s own channels.
  • Split wallets. One for farming, one for holding. The farming wallet connects to new sites; the holding wallet rarely connects to anything.

The checklist for teams

  • Load no one else’s JavaScript on a page that can move user money. Host it yourself, pin the exact version with an integrity hash, or cut it.
  • Keep monitoring and session recording off the trade and signing screens. If you need them, scope them to marketing pages.
  • No unpinned CDN links. @1 means “whatever the maintainer publishes next”.
  • Lock the domain. Registrar lock, hardware keys on the registrar and DNS accounts, alerts on any record change.
  • Plan the incident. A switch that turns off signing, a status page and a refund policy written before you need them.

An example: outside scripts on 68 pages, Oct 29, 2026

This is an example of the check above, run once on the projects in our catalog. Read it with these limits:

  • It is a point in time. Sites change their scripts often; any of these pages may look different now. We do not re-run it here; corrections are added with a date.
  • It is not a security audit. We looked only at which outside domains delivered scripts to one page. We did not test the sites, their servers, their code or their contracts.
  • A listed script is not a finding of compromise. We know of no report that any vendor below, apart from DebugBear, was compromised at the time. A listing says the page depends on that company, nothing more.
  • A clean page is not a safe site. It means no outside code loaded on that page at that moment. The project’s own hosting, packages and domain are outside this check.
  • It does not change our ratings. Labels and scores on the project pages are unchanged.

How we measured: on Oct 29, 2026, between 19:00 and 19:45 UTC, we opened the working page of each project (the trade screen of a perp DEX, the market page of a prediction market, the login of a card, the main page of a tool) in a desktop browser and listed every outside domain that delivered a script. 68 pages loaded; the others were mobile-only apps, bot checks or geo-blocks. We waited about six seconds per page, never logged in and never accepted a cookie banner, so scripts that load later are missing: this is a floor, not a full count.

19 of 68 pages loaded no outside script at all: Lighter, Lighter on Robinhood, Extended, Nado, Hibachi, Katana Perps, Phoenix, Entropy, Papertrade, Predict.fun, Probable, Kairos, Metric, DeBank, DefiLlama, L2BEAT, Rabby, Deblock and Gnosis Pay.

19 of 68 pages loaded at least one script of the three kinds described above:

Outside the scan, the CoinGecko homepage also carried a DebugBear script tag at 19:13 UTC that day; its coin page, the one we measured, did not. DebugBear’s CDN was returning an error at the time, so a tag left in a page loaded nothing.

Google Tag Manager, the way the KyberSwap drainer arrived, was on 28 of the 68 pages. Google Tag Manager by itself is not one of the three kinds: it matters because whoever controls the container can add scripts without a site release. Polymarket after its fix loaded none of the three kinds, only Google Tag Manager, AppsFlyer and big-platform pixels.

If a project has changed its page since, or you see an error here, tell us: we will add a dated correction under this section.

What this means for a farmer

  • A farm is a page you visit every day. The more often you sign on a site, the more its scripts matter to you.
  • Audits cover contracts, not pages. Trust is one of the criteria in our rating method; project pages list each venue’s incidents and sources.
  • Speed beats size after an incident. Most frontend drains end within an hour. The users who lose most are the ones who keep signing in an old tab.

Frequently asked

Is a hardware wallet enough? It stops a script from signing for you, but it signs whatever you approve. On Oct 29 the fake request came from the real polymarket.com. Read what the device shows.

Is email login less safe than a wallet extension? It is more convenient and gives you less control. On Oct 29, email-login users were drained with no prompt; wallet users at least saw a request.

Does a clean scan mean a site is safe? No. It means no outside code loaded on that page at that moment. The project’s own hosting, its npm packages and its domain can still be attacked.

Projects in this guide