
About a week ago (report sent on February 10, 2026), I found a vulnerability in WP and O2 mail (O2 uses the same web interface and infrastructure as WP - Wirtualna Polska).
The last public mentions of XSS bugs in WP mail were in 2012 on the Niebezpiecznik website. Interestingly, that vulnerability was found by Jakub Zoczek, who now works at Securitum. However, it is important to realize that WP mail worked very differently back then compared to today.
Today, WP is built on a modern frontend stack: Chakra UI + Radix UI + React. Back in 2012, it was mostly custom CSS and jQuery, which shows the big difference between modern and past technologies. I was curious if I could find such a bug myself—even if it was a minor one, it is a nice “gem” to add to my portfolio.
Before testing for vulnerabilities, you should check if a company has official contact info for their security department. I created a simple Google Dork for this, which you can use for any company (just replace the domain): inurl:"/.well-known/security.txt" inurl:wp.pl
Unfortunately, there is often a lack of clear info on how to look for bugs or if a company even allows it. It is often a “grey area.” The key rule is ethics: as long as you report the bug, do not use it for bad purposes, and do not test it on third-party accounts, you usually will not have problems. I did exactly that and created a test account for my research.
Searching for vulnerabilities on the frontend was made much easier by publicly available source maps (from Webpack). For an attacker, these are a treasure because they allow for restoring the original TypeScript code (with author comments!) from the minified JavaScript. In the case of WP Mail, it allowed me to precisely locate where values were rendered.
I found a classic problem in the code: developers used dangerouslySetInnerHTML in React to render HTML content directly from the API, completely skipping the sanitization step. Interestingly, even if sanitization had been in place, the default configuration of popular libraries (like DOMPurify) without a strict FORBID_TAGS list (e.g., for iframe, object, embed tags) would still have allowed the payload to pass. Only the combination of correct frontend (and backend) sanitization along with an updated tag blocking policy effectively fixed the bug.
The most interesting part of the bug was its persistence. By using a classic XSS payload with an <iframe> tag and the srcdoc attribute, I could inject code into the database. This type of Stored XSS has one key advantage for an attacker: it survives session termination and password changes by the victim.
A single POST request to the /api/v1/signatures endpoint was enough to add a malicious payload to a user’s signature. Interestingly, this endpoint did not verify the XSRF-TOKEN header (though the SameSite=Lax attribute on the session cookie provided some protection against external CSRF attacks).
Every time a user opened the signature selection modal (“More” -> “Choose signature”) in the message composer, the malicious code executed in their session context (same-origin). The attack was completely invisible to the user—the payload generated no visual artifacts in the DOM (like broken images).
The SOC (Security Operations Center) team at Wirtualna Polska reacted very quickly. I received a response immediately, and the bug has already been fixed (in version 8.199.4). Despite not having an official “Bug Bounty” program, they even sent me a small gift as a thank you.
This is a great example for me that it is worth reporting such findings professionally, even if a company does not have a public reward list.
(This is a responsible disclosure article written after the bug was fixed. I am not revealing sensitive technical details that could harm the company).