On Thursday, October 29, 2026, Polymarket halted trading on its international exchange for about an hour. At the center of it was a script Polymarket loaded from DebugBear, a UK website performance monitoring company. According to two independent teardowns, the file served from DebugBear’s CDN had become a wallet drainer: it looked for signed-in traders, tried to sell their positions and sent the proceeds to an attacker’s wallet. On-chain analysts put the theft at roughly $2.7 million across about 700 accounts. Polymarket says it is fully reimbursing every affected trader.
Below is what is confirmed, what is only reported, how the code worked, and what any team that loads third-party JavaScript into a signed-in app should change.
Status as of October 29, 2026, 22:00 UTC. Neither Polymarket nor DebugBear has published a post-mortem. Polymarket has not named the provider or confirmed a loss figure. The technical detail below comes from researchers who analyzed the file, not from either company.
What we know
- Polymarket confirmed a third-party compromise. “One of our 3rd party providers was compromised, and we have referred this to relevant law enforcement,” it posted on X, adding that “out of an abundance of caution, we have temporarily halted trading.” After trading resumed it said it is “fully reimbursing all affected traders” (NBC News). It referred the case to UK law enforcement.
- The provider was DebugBear. A source familiar with the matter named DebugBear to Reuters and CNBC. DebugBear said on X that it was “affected by an ongoing security incident” and asked customers of its real user monitoring (RUM) product to remove its embed code. Polymarket’s own production build carries a commit titled “remove debugbear rum script” (Hudson Rock).
- The malicious file came from DebugBear’s CDN. Hudson Rock downloaded
cdn.debugbear.com/C7xcKKrjUnXK.jstwice, at 18:12 and 18:13 UTC, and got the same 15,187-byte drainer both times. - Losses are about $2.7 million, not yet confirmed. Bubblemaps estimated about 700 affected users and $2.7 million stolen, as reported by WIRED. Betting Intelligence and Polysights told CNBC that an account withdrew at least $2.7 million across 710 wallets. Arkham data showed the suspected attacker’s wallet holding about $2.65 million in POL (RG.org, Decrypt). Polymarket declined to give a figure.
- Polymarket US was not compromised, a person familiar with the matter told CNBC. The halt covered the international platform, Polymarket.com.
- Still unknown: how DebugBear was compromised, when the malicious version first went live, and whether any other DebugBear customer received it. Hudson Rock lists all three as unresolved.
Timeline
All times October 29, 2026. Eastern Time was UTC−4.
| UTC | ET | Event | Source |
|---|---|---|---|
| 17:59 | 1:59 p.m. | Timestamp of a Polymarket production build whose commit reads “chore(polymarket): remove debugbear rum script”. A build time, not proof of when it was deployed. | Hudson Rock |
| ~18:00 | ~2:00 p.m. | DebugBear posts that it is affected by an ongoing security incident and asks RUM customers to remove its embed code. | NBC News, RG.org |
| 18:05 | 2:05 p.m. | Polymarket’s status page puts the exchange in cancel-only mode and pauses relayer actions. | Unchained |
| 18:12 | 2:12 p.m. | Hudson Rock downloads the drainer from cdn.debugbear.com, twice, with identical bytes. | Hudson Rock |
| 18:28–18:38 | 2:28–2:38 p.m. | The suspected attacker wallet sends out about 28.6 million POL in three transfers. | RG.org, from Polygonscan |
| 18:33 | 2:33 p.m. | Polymarket confirms a third-party provider was compromised and says anyone affected “will be made whole”. | Unchained |
| ~19:00 | ~3:00 p.m. | Trading resumes. Polymarket says it is fully reimbursing all affected traders. | NBC News, Unchained |
| 19:05 | 3:05 p.m. | The status page marks the incident resolved. | Unchained |
| 21:50 | 5:50 p.m. | cdn.debugbear.com and data.debugbear.com no longer resolve (NXDOMAIN from both Cloudflare and Google public DNS). | Our own check |
What the script did
Two researchers published teardowns of the file: Hudson Rock and Dancho Danchev. Neither ran it against a live account, so this is what the code was written to do, not proof that every step worked.
- Decide whether to run. It fetched settings from
data.debugbear.com, with hard-coded fallbacks: a recipient wallet, a $10 minimum portfolio and a $10 minimum position. It also called Polymarket’s own geoblock endpoint and quit for visitors Polymarket blocks from trading. - Read the session. It read three Polymarket entries from the browser’s localStorage (
polymarket.auth.params,polymarket.auth.proxyWalletandpoly_clob_api_key_map) to learn the trader’s wallet and account type. - Find the trading client inside React. It walked React’s internal component tree and hook state until it found an object with
postOrder,createOrderandcreateMarketOrdermethods, then used that object and its signer. - Take inventory and report it. It read up to 200 positions and the account’s pUSD and USDC.e balances, then posted the wallet address, IP address, country, operating system, account type and portfolio value to
data.debugbear.com/metrics/submit. - Move the cash. It built an EIP-712 signed batch for the trader’s Polymarket deposit wallet and submitted it through Polymarket’s own relayer: unwrap pUSD to USDC.e, then swap it to the recipient through a third-party route. If no route answered, it fell back to a plain USDC.e transfer.
- Liquidate positions. For traders using their own external wallet, it batch-transferred the outcome tokens straight to the recipient. For email-login accounts, it placed fill-and-kill sell orders at about 97% of the price, then 50%, then the minimum tick, and then tried to withdraw the proceeds.
Two details matter more than the rest.
It did not need passwords or keys. Neither analyst found code that exfiltrates credentials, seed phrases or private keys. The trader was already signed in, and a script running in the page has the same authority as the page’s own code. Every order and transfer was signed by the page’s own signer and sent to Polymarket’s own trading API or relayer.
Its traffic looked like monitoring traffic. Settings and reports went to DebugBear’s own data host under /metrics/ paths: the same kind of request a RUM script sends on every page view.
Both analysts also found bugs. The code counts “submitted” and “pending” relayer states as success, and one balance check compares a value with itself. The attacker’s own reports may overstate what happened; the on-chain totals are the better measure.
Why the usual defenses did not stop it
Content Security Policy decides which origins may run code and receive requests. cdn.debugbear.com was allowed because Polymarket chose to load it, the data host was allowed because a RUM script has to send its data somewhere, and the money moved through Polymarket’s own relayer. A strict connect-src could have blocked the third-party swap request, but the code had a fallback that needed no outside service. CSP controls where code comes from, not what allowed code does.
Subresource Integrity pins a script to a hash, and the browser refuses a file that changed. It only works for a file that never changes. Most analytics and RUM snippets load a file the vendor updates in place, so the vendor can ship fixes without waiting for your deploy. That design is convenient, and it means the vendor, or whoever controls the vendor’s CDN, can change the code running on your page at any time.
Vendor review would have passed. DebugBear is a legitimate, widely used performance tool. The risk was never the vendor’s intent. It was that anyone who controls the file controls your page, with your user’s session.
Polymarket has been here before
On June 25, 2026, Polymarket said a third-party vendor had been compromised and malicious code injected into its front end. About $3 million was taken; Bubblemaps concluded that fewer than 15 accounts were affected, and Polymarket said it was refunding them in full (Decrypt). Polymarket did not name that vendor, and nothing published links it to DebugBear. In May, a separate incident drained an internal rewards wallet through a compromised private key.
That makes two front-end vendor compromises at Polymarket in four months. In an app where a signed-in page can sign transactions, every script on that page is effectively a co-signer.
What to change in your own app
- List every third-party script on your signed-in pages. Open the network panel on your most sensitive page (checkout, payouts, account settings) and filter for JavaScript from other domains, including everything a tag manager pulls in. A Content Security Policy in report-only mode with a reporting endpoint gives you the same list from real traffic.
- Take them off pages that can move money or data. Analytics, RUM, chat and A/B testing earn their place on marketing pages and most of a product. They do not need to run where a session signs a transfer, changes a payout account or exports customer data. Put that step on a separate origin, or in an iframe that loads no third-party code.
- Bundle what you keep. A vendor SDK installed from npm and built into your own bundle runs the version in your lockfile, not whatever the vendor’s CDN serves today. A compromised package can still reach you, but only through an upgrade you choose and can diff.
- Pin and hash what you cannot bundle. Load a versioned URL with an
integrityhash andcrossorigin="anonymous". If a vendor only offers a moving “latest” URL, treat it as code that vendor can change on your page whenever it likes, because it can. - Make high-risk actions prove intent. The drainer needed no new permission; it used the session the trader had already opened. Step-up confirmation for withdrawals, transfers to new addresses and bulk sells at far below market raises the bar for any script running in the page.
- Know how fast you can pull a tag. Time the path from “vendor compromised” to “tag gone from production”, including CDN and HTML caches. Removing the tag is the one fix you control: Hudson Rock could still download the drainer from DebugBear’s CDN about 12 minutes after DebugBear’s notice.
- Follow your vendors’ incident channels. DebugBear’s notice went out on X. If no one on your team follows each script vendor’s status page or account, you hear about their incident from the news, or from your users.
If you use DebugBear RUM
- Remove the embed code, as DebugBear asked. At 21:50 UTC on October 29,
cdn.debugbear.comdid not resolve, so the script could not load from it at that time. A tag left in place will load whatever that hostname serves once it resolves again. - Review signed-in activity for the period the tag was live. When the malicious version first appeared is not yet known, so do not assume the exposure started on October 29.
- Block or alert on these indicators, published by Hudson Rock and Dancho Danchev:
| Type | Indicator |
|---|---|
| Script | cdn.debugbear.com/C7xcKKrjUnXK.js |
| SHA-256 of the script | 0755e767504d8103f6c27b9e765a1026507a17c04513242adb503df7777879e5 |
| Settings and reporting | data.debugbear.com/metrics/initdata.debugbear.com/metrics/submitdata.debugbear.com/metrics/updatedata.debugbear.com/metrics/handle |
| Fallback recipient (Polygon) | 0x3F99139F1C5854bb628c2e576Aaf638e99dFfc18 |
| Tracking ID | 4c6b64a0-a7ef-4c0f-9c70-3a4e6f89065c |
We ship a RUM script too
Site Qwality sells real user monitoring, and our CDN snippet loads a file from cdn.siteqwality.com that we update to ship fixes. That is the same trust Polymarket placed in DebugBear, and the same trust you place in every vendor tag on your site. If you would rather not extend it on your most sensitive pages, you do not have to:
- Install from npm.
@siteqwality/rumbuilds the SDK, session replay recorder included, into your own bundle at the version in your lockfile. Our CDN then serves your application’s settings as data, never code. See the RUM quickstart. - Leave it out where it does not belong. If your payment or signing step lives on its own origin or iframe, do not load the SDK there. The rest of your app still gets page views, Web Vitals, errors and replays.
- Lock down where it can talk. Our CSP guide lists every host the SDK uses, so your policy can allow exactly those and nothing else.
Sources
- NBC News: Polymarket halts trading for an hour after vendor compromise (October 29, 2026)
- Reuters: Polymarket resumes trading after third-party security breach, to reimburse users (October 29, 2026)
- Hudson Rock: Wallet-draining code found in a third-party script (October 29, 2026)
- Dancho Danchev: Dissecting the Polymarket malicious JavaScript compromise (October 29, 2026)
- Decrypt: Polymarket pauses trading as it investigates a security incident (October 29, 2026)
- Unchained: Polymarket resumes trading, vows to reimburse traders (October 29, 2026)
- RG.org: Polymarket pauses trading after third-party provider breach, citing WIRED, CNBC and Polygonscan (October 29, 2026)
- Decrypt: Polymarket to refund users after website exploit (June 25, 2026)
