How We Protect Our JavaScript Agent, and How to Host It Yourself
Attackers hijacked DebugBear’s script to drain Polymarket wallets on October 29. Here is how we protect the Request Metrics agent, and how to host it yourself.
On October 29, a web performance script started emptying Polymarket wallets.
The script belonged to DebugBear, a performance monitoring service that works a lot like Request Metrics. Polymarket ran it to measure how fast its site loaded for real visitors. Scott Helme’s analysis shows that cdn.debugbear.com stopped serving DebugBear’s script. An nginx server answered in its place with a script built to drain Polymarket accounts.
The malicious script read each visitor’s session out of the browser, found the trading client inside the app, and used the visitor’s own signed-in session against them. It either sold their positions and sent the cash to the attacker, or transferred the positions to the attacker directly. It also tried to send each victim’s portfolio, IP address, country, and operating system to data.debugbear.com, which ohey.ca’s header analysis shows had also been replaced by the attacker’s server.
The script was live for about fifty minutes before Polymarket pulled it and paused trading. Helme traced about 28.6 million POL, roughly $2.6 million, into the attacker’s wallet. Polymarket hasn’t confirmed a total, but says it will repay everyone affected. DebugBear told its RUM customers on X to remove its embed code. It hasn’t said yet how the attackers got in, but it sounds like a DNS compromise.
Unfortunately, this isn’t the first time this has happened. In 2024, polyfill.io got a new owner and its CDN started injecting malware into more than 100,000 websites. Polymarket users lost about $3 million in June when a third-party vendor, which Polymarket never named, was compromised. Any script you load from someone else’s server runs with the same power as your own code, and you’re trusting every system that controls what that URL returns.
Our agent works the same way
Request Metrics runs as a JavaScript agent on your pages. Most of you load it from our CDN, and it sends performance data back to our servers. If someone took over our CDN’s hostname, or swapped the file behind it, their code would run on your pages just like the drainer ran on Polymarket’s.
We watch the agent files on our CDN and get alerted if their contents ever change. The Request Metrics agent hasn’t had a release since August 2024, so any change is an alarm. Since the breach, we’ve been reviewing how our agent gets published and who can touch it, and making changes to our services.
Our agent also doesn’t take instructions from our servers. It sends data to us and checks only whether the request went through, and it never downloads code or settings. So if you host our agent yourself, it can’t be changed by anything that happens on our side. It still sends data to us, so keeping our servers and domains secure is still our job.
Host the agent yourself
One of our customers emailed the day after the breach to ask whether they could host our script themselves. Yes. You always could, and for any site that handles money or sensitive data, we recommend it.
Install the agent from npm and bundle it with your code. Your lockfile decides the version, so you control exactly what your users get.
npm install @request-metrics/browser-agent
import { RM } from "@request-metrics/browser-agent";
RM.install({ token: "YOUR_TOKEN" });
If you load Request Metrics with a script tag, point it at a pinned version instead of current and add a Subresource Integrity hash. If the file ever changes, the browser refuses to run it.
<script src="https://cdn.requestmetrics.com/agent/2.4.1/rm.js"
integrity="sha384-ki4bQkJxjR7ttBbgc01hQJE8AOkrgLAzLg9rZAeagpLuBNZEAvoals2b5AoIM6o5"
crossorigin="anonymous" data-rm-token="YOUR_TOKEN"></script>
That hash is the check that would have stopped the Polymarket drainer. Helme points out that Polymarket’s Content Security Policy allowed every request the drainer made, because the URL never changed. Only the bytes did.
You can also download that same file and serve it from your own domain. The install docs cover the npm module and hosting the script yourself.
Whichever you pick, update your Content Security Policy. Once the agent comes from your own domain, you can drop cdn.requestmetrics.com from script-src. Keep in.requestmetrics.com in connect-src so the agent can still send data.
If you’re running your own security review and have questions, email hello@requestmetrics.com. It goes straight to our team.