October 26, 2026
What Real HackerOne XSS Reports Teach You That Tutorials Don’t
I went through publicly disclosed XSS reports from HackerOne, GitLab, LinkedIn, Apple and more — here’s the pattern behind every single one

By Monika
5 min read
- 1 Pattern 1: Third-party embeds reflecting into the DOM
- 2 Pattern 2: postMessage handlers that trust their origin blindly
- 3 Pattern 3: Stale infrastructure references (deleted buckets, old widgets)
- 4 Pattern 4: Browser-specific sanitization gaps
- 5 Pattern 5: Client-side storage used as an unsanitized data source
So far in this series, we've covered recon, IDOR, Business Logic bugs, Subdomain Takeovers, Rate Limiting, and File Uploads. This article is a bit different — instead of a pure methodology, we're going to pull apart real, publicly disclosed XSS reports and extract the exact pattern each one relied on. Tutorials teach you <script>alert(1)</script>. Real bugs rarely look like that.
Cross-site Scripting is still, by a huge margin, the most commonly reported bug class on HackerOne — ahead of CSRF, SQLi, IDOR, and SSRF combined, according to public disclosure data. But most of the still-unpatched, bounty-eligible XSS today isn't the obvious kind. It's hiding in the gaps between "the input is sanitized" and "the output is actually safe."
Pattern 1: Third-party embeds reflecting into the DOM
One of HackerOne's own disclosed reports describes a reflected XSS on www.hackerone.com and resources.hackerone.com, found through a Wistia embed code. The vulnerability wasn't in HackerOne's own code — it was in how a third-party video embed's parameters got reflected into the page without proper encoding.
What this teaches you: Every third-party widget — chat bots, video embeds, analytics scripts, payment iframes — accepts some kind of configuration via URL parameters or postMessage. Test these the same way you'd test any input field.
https://target.com/embed?widget_config=<script>alert(document.domain)</script>https://target.com/embed?widget_config=<script>alert(document.domain)</script>Check the embed's documentation for configurable parameters, then throw your payload into each one.
Pattern 2: postMessage handlers that trust their origin blindly
HackerOne has had two separate disclosed DOM-based XSS reports tied to postMessage handling — one of which was specifically noted as a bypass of an earlier, already-patched postMessage XSS. This is a common theme: the first fix is incomplete, and a second report finds the gap.
What this teaches you: Search the page source for window.addEventListener("message" or 'onmessage'. If the handler doesn't strictly verify 'event.origin', and uses the message data to write to the DOM ('innerHTML', 'document.write', etc.), you likely have a bypass.
// Test payload to send from an attacker-controlled page
window.opener.postMessage('<img src=x onerror=alert(document.domain)>', '*');// Test payload to send from an attacker-controlled page
window.opener.postMessage('<img src=x onerror=alert(document.domain)>', '*');Also worth remembering: when a program has a disclosed, patched XSS report, check if the fix was actually complete — "bypass of XXXXXX"-style reports are extremely common and often pay out again on the same root cause.
Pattern 3: Stale infrastructure references (deleted buckets, old widgets)
One disclosed HackerOne report described a stored XSS on www.hackerone.com caused by a deleted S3 bucket that an old page widget still referenced. When the bucket was deleted, anyone could register a bucket with the same name and serve attacker-controlled JavaScript from it.
What this teaches you: This is essentially a JS-level version of subdomain takeover (which we covered earlier in this series). Look for '
curl -s https://target.com | grep -oE 'src="https://[^"]\.s3[^"]"'curl -s https://target.com | grep -oE 'src="https://[^"]\.s3[^"]"'If the bucket returns a "NoSuchBucket" style error, you may be able to claim it.
Pattern 4: Browser-specific sanitization gaps
Multiple disclosed reports including a stored XSS affecting only Internet Explorer through a Program Asset identifier and another stored XSS in IE11 via custom fields only triggered in specific, older browsers. Modern sanitization libraries are usually tested against Chrome/Firefox, and edge-case browsers get skipped.
What this teaches you: Don't give up on a payload just because it doesn't fire in Chrome. If a program's scope allows it, test the same stored payload in Firefox, Safari, and older browser engines (or their compatibility modes) — sanitization bypasses that only affect one rendering engine are still valid, reportable bugs.
Pattern 5: Client-side storage used as an unsanitized data source
A disclosed GitLab report found a stored DOM XSS where an emoji-picker list stored in the browser's local storage was injected into the DOM without sanitization. The twist: this required a prior XSS to actually plant the malicious data into local storage — making it a second-stage vulnerability that let an initial XSS persist and spread across sessions, even bypassing CSP on the page.
What this teaches you: Don't just look at server-rendered data. Check localStorage, sessionStorage, IndexedDB, and cookies for values the app reads back and renders into the DOM. Even "theoretical, requires another bug" findings like this one get accepted and paid, because they describe realistic attack chains, not just isolated payloads.
// In browser DevTools console, check what gets rendered unsanitized
localStorage.setItem('some_key', '<img src=x onerror=alert(1)>');
// Then trigger whatever feature reads that key back into the page// In browser DevTools console, check what gets rendered unsanitized
localStorage.setItem('some_key', '<img src=x onerror=alert(1)>');
// Then trigger whatever feature reads that key back into the pagePattern 6: Rich text / embed tags inside user content
A disclosed, critical-severity LinkedIn report found a stored XSS triggered through an iframe tag embedded inside an Article. Rich-text editors (articles, comments, chat messages, bios) are a classic source of stored XSS because they intentionally allow some HTML — and the allowlist of tags/attributes is often incomplete.
What this teaches you: When testing a rich-text field, don't just try '
<iframe src="javascript:alert(document.domain)"></iframe>
<svg onload=alert(document.domain)>
<math><mtext><table><mglyph><style><img src=x onerror=alert(1)></mglyph></mtext></math><iframe src="javascript:alert(document.domain)"></iframe>
<svg onload=alert(document.domain)>
<math><mtext><table><mglyph><style><img src=x onerror=alert(1)></mglyph></mtext></math>Rich text editors are also a hotspot for mutation XSS (mXSS) — payloads that look safe to the sanitizer but get mutated into something dangerous once the browser re-parses the DOM. A disclosed 2025 critical-severity report on the Trix editor (used by several major platforms) was exactly this kind of mutation-based stored XSS.
Pattern 7: Validation feedback that doesn't match actual risk
Not every disclosed report results in a bounty, and that's a useful lesson too. A report on a donation platform's subscribe page described a script tag entered into an email field that triggered an alert after a delay. The triage response correctly pointed out this was a DOM XSS requiring the user to interactively trigger their own validation feedback, not a classic reflected XSS exploitable by sending someone a link — so it was accepted as a real flaw but ruled out for a bounty.
What this teaches you: Before reporting, actually try to build a realistic attack: can you trigger this by sending someone a link, or does it require the victim to manually type something into their own browser? Programs pay based on exploitability, not just "I got an alert box to pop." Framing your report around a realistic attack scenario (not just a PoC alert) makes the difference between a paid report and an informational one.
Pattern 8: Partial fixes that get re-enabled elsewhere
A disclosed 2025 Apple Security Bounty report described a stored XSS on Apple's developer discussions platform that was partially fixed, then bypassed, then found to still be live on mirrored instances of the same forum software, earning a $5,000 bounty.
What this teaches you: When a large company runs the same platform across multiple subdomains or regional mirrors (developer.apple.com/forums, discussions.apple.com, etc.), a fix deployed to one instance doesn't always reach the others. If you find a patched XSS on one subdomain, go check every other subdomain running the same underlying software.
How to apply this as a methodology
Pulling these patterns together, here's a practical checklist for your next XSS hunt:
- Identify every third-party embed/widget and test its configurable parameters
- Search page source for
postMessagelisteners and check origin validation - Look for script/resource tags pointing at third-party storage — check if they're claimable
- Re-test old, publicly disclosed XSS fixes in non-Chrome browsers
- Check
localStorage/sessionStoragefor unsanitized data flowing back into the DOM - Throw non-
<script>tags (<iframe>,<svg onload>, mXSS payloads) at every rich-text field - Before reporting, build the realistic attack scenario — not just a popup
- If you find a patched XSS, check sibling subdomains running the same software
Where to find more real reports to learn from
Public disclosure archives are one of the best free resources in bug bounty — reading through them teaches you more about real-world edge cases than any course. Search HackerOne's Hacktivity feed filtered by "Cross-site Scripting," and look specifically at reports from programs that run their own product on hackerone.com itself (like HackerOne's own program) — these tend to be unusually detailed and well-documented.
Final Thoughts
Every XSS pattern above came from a real, disclosed, bounty-eligible report — not a tutorial payload list. The lesson across all of them is the same: XSS today lives in the places automated scanners and basic <script>alert(1)</script> tests don't reach — third-party integrations, postMessage handlers, client-side storage, and incomplete fixes. Read disclosed reports regularly; they're free training data for exactly the kind of bugs still paying out today.
If this guide helped you, consider buying me a coffee ☕ — it keeps me motivated to dig up and write more bugs like this. Buy me a coffee
Monika Hi, I'm Monika ✨I break down real-world bug bounty reports into simple, practical write-ups.If my articles help you…