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.
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:
- 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.
- 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.
- 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:
- Open the page where you trade or log in, then the developer tools (F12) and the Network tab. Filter by JS and reload.
- Look at the domains. The venue’s own domain and its CDN are expected. Note anything else.
- 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.
- 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.
@1means “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:
- Watching tools: GeckoTerminal (a DebugBear tag was still in the page an hour after DebugBear asked customers to remove it; New Relic; Maze), DeFi Saver (FullStory), Veranta (Avantis) (Microsoft Clarity), Ostium (Microsoft Clarity, Usersnap), Reya and VOOI (Hotjar), Tria Card (New Relic), the Bitpanda Card login (Datadog RUM), the Wirex login (Azure App Insights).
- Easy-to-swap sources: SX Bet (a raw S3 bucket, a public CDN, a public npm CDN and Vercel’s preview toolbar), Ostium (a raw S3 bucket), CoinGecko (html-load.cc, a domain with no brand behind it; we could not establish its purpose).
- Ads and web3 tracking: the Addressable tag on Jumper, Outcome, Variational, SX Bet, Azuro, Limitless, Ondo and Tria Card; Slise and Spindl on Limitless; HypeLab and MarkFi on Ostium; MarkFi on Reya; ad networks on DEXTools, CoinMarketCap, CoinGecko, GeckoTerminal and the Wirex login.
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
- Polymarket RipePeer-to-peer prediction market for real-world events, with outcome shares on Polygon; US users go to the separate, CFTC-regulated Polymarket US.
- Revoke.cash RipeningShows which contracts can spend your tokens and lets you revoke old approvals after farming, across many networks.
- GeckoTerminal RipeningReal-time DEX tracker for token prices, pools, liquidity and trades across many chains, built by the team behind CoinGecko.