XSS Playground

Cross-Site Scripting — inject HTML/JavaScript and see the difference between unsafe innerHTML and sanitized rendering.

Try this:Click a quick payload button, then hit "Render" to inject it

Quick Payloads — click to load

⚠ Unsafe Output (innerHTML)
Rendered output appears here...
JavaScript executes — scripts run in the browser context
Safe Output (textContent / escaped)
Sanitized output appears here...
HTML entities escaped — browser renders as plain text
Code Comparisonattack mode

✗ Vulnerable

// Directly sets HTML — dangerous!
element.innerHTML = userInput;

// Any <script> or onerror=
// will execute immediately

✓ Fixed

// Treats input as text only
element.textContent = userInput;

// Or with DOMPurify for rich text:
element.innerHTML =
  DOMPurify.sanitize(userInput);
What's happening

XSS occurs when user input is rendered as HTML instead of text. The browser parses embedded scripts and executes them — giving attackers full JavaScript access to the page.

Why it's vulnerable

innerHTML tells the browser to parse the string as HTML — including <script> tags and event handlers like onerror. Any injected JS runs with full access to your cookies, localStorage, and DOM.

How it's fixed

Use textContent instead of innerHTML for user input. For rich text, use DOMPurify to sanitize. Add a Content-Security-Policy header to restrict which scripts can execute.

Real-world context

XSS caused the 2005 MySpace Samy worm (1M accounts in 20h), the 2018 British Airways breach (500K payment cards stolen), and is listed in the OWASP Top 10 every year since 2003.

Security Log(0)

Monitoring runtime activity… waiting for events

Stream will begin shortly