dangerouslySetInnerHTML injects a raw HTML string into the DOM without React's normal escaping. If any part of that string comes from a user, an attacker can include a script that runs in your other users' browsers with their session. The fix is to render text normally, or to sanitize the HTML before you inject it.
Why it's a problem
React escapes values by default, which is what normally protects you from cross-site scripting. dangerouslySetInnerHTML turns that off for a chunk of markup. Feed it user-controlled content, and a payload like an image tag with an onerror handler executes in the victim's browser, letting the attacker steal session tokens, act as the user, or rewrite the page.
The pattern
// user-controlled content injected as raw HTML
<div dangerouslySetInnerHTML={{ __html: comment.body }} />The fix
// render as text (React escapes it)
<div>{comment.body}</div>
// or, if you truly need HTML, sanitize first
import DOMPurify from "dompurify";
<div dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(comment.body) }} />Why AI tools write this
When the task is 'render this rich text' or 'show the HTML from the API,' dangerouslySetInnerHTML is the completion that makes it appear on screen immediately. The assistant produces working output without weighing whether the content is trusted, because trust is a fact about your data it cannot see.
The quick fix
- Render user content as text with {value} so React escapes it.
- If you must inject HTML, sanitize it first with a library like DOMPurify.
- Never pass unsanitized user input to dangerouslySetInnerHTML.