XSS in React: dangerouslySetInnerHTML and Third-Party Scripts
Understand how React's default escaping prevents XSS, when dangerouslySetInnerHTML is dangerous, and how third-party scripts introduce risk.
XSS in React: dangerouslySetInnerHTML and Third-Party Scripts is a free React Academy lesson on CoddyKit — lesson 1 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the React Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.
React's Built-In XSS Protection
React automatically escapes all values rendered via JSX before inserting them into the DOM. When you write {userInput} in JSX, React calls the equivalent of textContent assignment — the value is treated as text, never as HTML. This prevents the majority of XSS attacks in React applications by default.
What dangerouslySetInnerHTML Does
dangerouslySetInnerHTML={{ __html: htmlString }} is React's escape hatch that bypasses the automatic escaping. The name is intentionally alarming: it tells you that you are taking responsibility for the safety of the HTML string. React sets innerHTML directly, executing any HTML including scripts and event handlers.
Legitimate Uses
You genuinely need dangerouslySetInnerHTML when rendering HTML that comes from a rich text editor (like TipTap or Quill), a CMS that stores HTML, or a Markdown-to-HTML converter. These sources produce real HTML markup that must be rendered as HTML, not as escaped text.
The Attack Vector
If the HTML string contains <script>stealCookies()</script> or <img src=x onerror="stealData()">, setting it as innerHTML executes the attacker's code. Any user-supplied content passed directly to dangerouslySetInnerHTML without sanitization is a critical XSS vulnerability.
DOMPurify: The Standard Sanitizer
DOMPurify is the industry-standard HTML sanitizer for browsers. It parses the HTML string in a sandboxed context, removes dangerous elements and attributes (script tags, on-event handlers, javascript: URLs), and returns a safe HTML string. Usage: DOMPurify.sanitize(dirtyHtml) before passing to dangerouslySetInnerHTML.
Third-Party Script Risks
Third-party scripts (analytics, chat widgets, ad networks) run with the same permissions as your application JavaScript. A compromised or malicious third-party script can read document.cookie, access localStorage, read form inputs, and make requests to external servers — all without any indication to the user.
Content Security Policy as Defense Layer
Content Security Policy is an HTTP header that declares which scripts are allowed to execute. Even if XSS payload is injected into the DOM, a properly configured CSP can block its execution by restricting inline scripts and allowing only whitelisted script sources. CSP is the second line of defense after input sanitization.
Supply Chain Attacks via npm
npm packages are a real XSS attack vector. A dependency can include malicious code that exfiltrates environment variables or user data. The 2022 node-ipc incident and the 2021 ua-parser-js compromise demonstrated that widely used packages can be taken over and poisoned. Audit dependencies with npm audit and use lockfiles.
What Attackers Do with XSS
A successful XSS attack enables an attacker to steal the user's sessionStorage JWT token (sending it to an attacker-controlled server), perform actions as the authenticated user (API calls using the user's session), modify the DOM to display phishing content, or log every keystroke the user makes in the application.
Trusted Types API
The Trusted Types browser API requires all DOM sinks (innerHTML, eval, script.src) to receive special typed objects rather than raw strings. This prevents string-based XSS payloads from reaching the DOM at the platform level. React is working toward Trusted Types compatibility, and CSP can enforce it.
Safe Patterns for CMS Content
The safe pattern for rendering CMS HTML: fetch the HTML, pass it through DOMPurify.sanitize() with an allowlist of safe tags and attributes, then render with dangerouslySetInnerHTML={{ __html: cleanHtml }}. Never skip the sanitization step, even if you trust the CMS, because the CMS database itself could be compromised.
DOMPurify Purpose
What does DOMPurify do when you call DOMPurify.sanitize(htmlString)?
Lesson Recap
React automatically escapes JSX values, preventing most XSS. dangerouslySetInnerHTML bypasses this for legitimate HTML rendering — always sanitize the input with DOMPurify first. Third-party scripts and compromised npm packages are supply chain XSS vectors. Content Security Policy provides a second defense layer. Successful XSS enables token theft, impersonation, and phishing.
Frequently asked questions
Is the “XSS in React: dangerouslySetInnerHTML and Third-Party Scripts” lesson free?
Yes — the full text of “XSS in React: dangerouslySetInnerHTML and Third-Party Scripts” is free to read here on the web, and the React Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the React Academy course, upgrade to CoddyKit PRO.
What will I learn in “XSS in React: dangerouslySetInnerHTML and Third-Party Scripts”?
Understand how React's default escaping prevents XSS, when dangerouslySetInnerHTML is dangerous, and how third-party scripts introduce risk. You practise React Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start React Academy?
No prior experience is required. React Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 1 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “XSS in React: dangerouslySetInnerHTML and Third-Party Scripts” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this React Academy lesson?
Yes. Every React Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- XSS in React: dangerouslySetInnerHTML and Third-Party Scripts
- CSRF Protection in React and API Setups
- Content Security Policy for React Apps
- Secrets Management and Environment Variables