Cross-Site Scripting (XSS) is one of the most common web security vulnerabilities, consistently appearing in the OWASP Top 10. It occurs when an attacker manages to inject malicious scripts into web pages that other users view. Despite being well-documented, XSS remains prevalent because developers often underestimate just how many injection points exist in modern applications.
Reflected XSS happens when user input is immediately returned by the server without sanitization. A classic example is a search page that displays your query back to you — if the query contains <script> tags, the browser executes them. The payload lives in the URL, making it easy to distribute via phishing links.
Stored XSS is more dangerous because the malicious script is permanently saved on the target server — typically in a database, comment field, or forum post. Every user who views the affected page becomes a victim. This is the type that leads to large-scale session hijacking and data theft.
DOM-based XSS occurs entirely on the client side. The vulnerability exists in JavaScript code that reads from a controllable source (like window.location) and writes to a dangerous sink (like innerHTML). The server never sees the payload, making it harder to detect with traditional WAFs.
XSS can be leveraged to steal session cookies, redirect users to phishing sites, deface pages, or even perform actions on behalf of authenticated users. In 2018, a stored XSS vulnerability in a major airline's frequent-flyer portal allowed attackers to steal loyalty points from thousands of accounts. The fix was a single line of output encoding.
The most effective defense is output encoding — converting special characters like<, >, and & to their HTML entity equivalents before rendering. Modern frameworks like React handle this automatically through JSX, which escapes values by default. However, using dangerouslySetInnerHTML bypasses this protection entirely.
Implement a strong Content Security Policy (CSP) header to restrict which scripts can execute. Validate and sanitize all user input on both client and server sides. Use HttpOnly andSecure flags on cookies to limit what XSS can access. Finally, adopt a security-first mindset — treat every piece of user input as potentially malicious until proven otherwise.