September 12, 2026
CVE-2026โ82019: How a Random Ad Led to DOM XSS While Testing chess.com
Introduction

By Hussein Mahmoud
4 min read
Introduction
I play a lot of chess on Chess.com, with a rating around 2000, so I already spend a lot of time on the website. At that time, I had just finished studying postMessage vulnerabilities on PortSwigger Web Security Academy, and I wanted to practice what I learned on a real target.
I was using this regex to quickly find message handlers inside JavaScript files:
While testing Chess.com, an advertisement loaded and one script appeared: video-bundle.js
The script belonged to TripleLift.
I was not hunting the vendor. The ad simply appeared while I was testing postMessage.
I searched the script for message handlers, found an interesting one, and started following the data. That was the beginning of the bug.
The interesting part was that this advertisement had to win the ad auction first. On another page load, the script might never have appeared.
Chapter 1: Finding the Vulnerable Handler
Inside the vendor script, I found this:
The first thing I checked was event.origin. There was no validation.
The handler checked what the message contained, but not where the message came from. So an attacker-controlled page could send a message to it.
Then I followed e.data and reached the important sink:
The message data was placed directly inside a script element and appended to the document. So the flow was simple:
Attacker page -> postMessage() -> No origin validation -> event.data -> script.textContent -> JavaScript execution.
The handler required one of a few expected strings, so a harmless PoC was enough (using the string get_ext). Finding the XSS was simple. Making it reliable was harder.
Chapter 2: Why the PoC Worked Randomly
At first, sometimes the PoC worked and sometimes nothing happened. The problem was not the payload. It was the ad lifecycle. The vulnerable environment was only available after the affected ad won the auction:
Chess.com loads -> Ad auction starts -> Affected ad wins -> Frame is created -> Message listener becomes active.
I also noticed that using a US IP made the required advertisement appear more often during my testing. There was another important condition where only the first matching message would be processed.
I could not know exactly when the vulnerable frame and listener were ready. So instead of trying to guess the timing, I repeatedly sent the same harmless message:
This was not a bypass for thirdPartyMessage. I was simply keeping the payload ready until the correct frame existed and the listener became active. Once that happened, one of the messages reached the handler.
Chapter 3: The Same XSS, Different Impact
After confirming the issue, I started checking the same script on other publisher integrations. One of the affected places I observed was the Yahoo homepage. This was interesting because the same vulnerable script did not always have the same impact. Some publishers isolated advertisements using SafeFrame or sandboxed iframes. In those cases, the JavaScript execution stays isolated.
The environment I observed while testing Chess.com behaved differently. The JavaScript execution could reach the publisher page context instead of staying only inside an isolated advertisement environment. The bug was inside a third-party advertising script, not Chess.com's own code, but the way each publisher integrated the script affected the final impact. That was a good example of defense in depth.
Chapter 4: The Root Cause
There were two problems. The first was trusting postMessage without validating the sender. A message handler should validate the expected origin.
But origin validation was only part of the problem. The more dangerous design was turning trusted message data directly into executable JavaScript. So the fix needed both: Validate the sender and never directly execute message-controlled data.
Chapter 5: Reporting It Without a Bug Bounty Program
Finding the vulnerability was only one problem. I also had no idea where to report it. The company did not have a public Bug Bounty program, and I could not find a security contact or a clear security email. So I went to LinkedIn, searched for the company, and contacted three employees. One of them replied and gave me the correct security email.
I sent the vulnerability details to the security team. Even though they did not operate a Bug Bounty program, they appreciated the research and decided to reward the report. On April 14, 2026, I received a $500 bounty. It became my first paid bug bounty. The fix was deployed to production on April 28, 2026. Then, a few months later, on August 28, 2026, the vulnerability was assigned: CVE-2026โ82019.
The issue was classified as:
- DOM-based Cross-Site Scripting โ CWE-79
- CVSS 3.1: 4.2 โ Medium
Conclusion
What I like most about this bug is how it started. I had just studied postMessage on PortSwigger, and instead of moving immediately to another topic, I spent time applying what I learned on real websites. That is probably the biggest lesson I took from it: After studying a vulnerability, apply it immediately. Don't study XSS today, move to CSRF tomorrow, then SSRF the day after.
Spend a week or two on one vulnerability. Learn different techniques, hunt for it on real targets, read JavaScript, build PoCs, and keep testing until the idea becomes natural. That is how the things you study actually stay in your head. And sometimes, a random advertisement is enough to turn that practice into your first bounty and a CVE..
Researcher: Hussein-Mahmoud7 CVE: CVE-2026โ82019