Cross-site scripting (XSS) is a vulnerability where an attacker gets their own JavaScript to run in another user's browser through your site. Because the script runs in the victim's session, it can steal their tokens, act as them, or rewrite the page. It happens when your app renders user-controlled content as HTML or script without escaping it.
How it happens
If your app takes user input, a comment, a name, a URL, and puts it into the page as raw HTML, an attacker can include a script or an event handler that the browser executes. In React, this most often comes from dangerouslySetInnerHTML with unsanitized content.
How to prevent it
Render user content as text so the framework escapes it, and if you must inject HTML, sanitize it first with a library like DOMPurify. A Content-Security-Policy header adds a strong second layer by limiting which scripts the browser will run.
What this means for AI-generated code
AI-generated code introduces XSS when it renders content from an API or a user as HTML to make it display, without sanitizing it. The code works and looks correct, so the vulnerability ships unnoticed until someone sends a payload.
Common questions
What is the most common XSS mistake in React apps?
Using dangerouslySetInnerHTML with content from user input or an API response without sanitizing it first. React escapes JSX output by default, which prevents most XSS — the vulnerability requires you to explicitly opt out of that escaping with dangerouslySetInnerHTML or by using a library that does so.
Is React or Next.js automatically safe from XSS?
Mostly yes for JSX rendering — React escapes all variables inserted into JSX. But dangerouslySetInnerHTML bypasses that, and so do some href attributes if they accept javascript: URLs. The full safety also depends on your Content-Security-Policy, since a strict CSP blocks inline scripts even if an XSS lands.
What is the difference between reflected and stored XSS?
Reflected XSS puts the attack payload in a URL that the victim is tricked into visiting — the payload is never stored, just echoed in the response. Stored XSS saves the payload to the database (in a comment, a profile name, a message) and executes it for every user who views it. Stored XSS is generally more dangerous because it affects all visitors, not just ones who click a crafted link.