DEV Community

Maxim Logunov
Maxim Logunov

Posted on

How to Safely Use `dangerouslySetInnerHTML` in React Applications

React is designed to protect against Cross-Site Scripting (XSS) attacks by automatically escaping HTML content. However, there are cases where you need to render raw HTML, such as when working with rich text from a CMS or third-party API. React provides dangerouslySetInnerHTML for this purpose—but as the name suggests, it must be used with caution.

In this article, we’ll explore best practices for using dangerouslySetInnerHTML safely in React applications.

What is dangerouslySetInnerHTML?

dangerouslySetInnerHTML is a React prop that allows you to inject raw HTML into a component. It bypasses React’s default escaping mechanism, making it potentially dangerous if misused.

Basic Usage:

function MyComponent({ htmlContent }) {
  return <div dangerouslySetInnerHTML={{ __html: htmlContent }} />;
}
Enter fullscreen mode Exit fullscreen mode

Risks of Using dangerouslySetInnerHTML

Since this prop directly injects HTML, it can expose your application to:

  • XSS Attacks: Malicious scripts can execute if the HTML contains untrusted content.
  • Data Leakage: Injected scripts can steal sensitive user data.
  • Broken UI: Invalid or poorly formatted HTML can break your layout.

Best Practices for Safe Usage

1. Sanitize HTML Before Rendering

Always sanitize HTML content to remove dangerous scripts, event handlers, and unwanted tags. Use libraries like:

  • DOMPurify (Recommended)
  • sanitize-html

Example with DOMPurify:

import DOMPurify from 'dompurify';

function SafeHTMLRenderer({ html }) {
  const cleanHTML = DOMPurify.sanitize(html);
  return <div dangerouslySetInnerHTML={{ __html: cleanHTML }} />;
}
Enter fullscreen mode Exit fullscreen mode

2. Use a Trusted Source

Only use dangerouslySetInnerHTML with content from trusted sources (e.g., your backend with proper sanitization). Never render user-generated content without validation.

3. Limit Scope with Custom Elements

Instead of rendering large chunks of HTML, isolate dynamic content in specific components:

function TrustedContent({ content }) {
  return <div className="trusted-content" dangerouslySetInnerHTML={{ __html: content }} />;
}
Enter fullscreen mode Exit fullscreen mode

4. Avoid Inline Event Handlers

Even if sanitized, avoid allowing onclick, onload, or other inline JavaScript handlers.

5. Implement CSP (Content Security Policy)

A strong CSP can mitigate risks by restricting script execution:

<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">
Enter fullscreen mode Exit fullscreen mode

6. Use TypeScript for Additional Safety

Enforce type checks to ensure only valid HTML strings are passed:

interface SafeHTMLProps {
  html: string;
}

const SafeHTML: React.FC<SafeHTMLProps> = ({ html }) => {
  const clean = DOMPurify.sanitize(html);
  return <div dangerouslySetInnerHTML={{ __html: clean }} />;
};
Enter fullscreen mode Exit fullscreen mode

When to Avoid dangerouslySetInnerHTML

  • User-generated content (comments, forms) unless strictly sanitized.
  • Dynamic script injection – use React components instead.
  • Unverified third-party data – prefer APIs that return structured data.

Conclusion

While dangerouslySetInnerHTML is a powerful tool, it should be used sparingly and with extreme caution. Always sanitize content, trust your sources, and enforce security policies like CSP. By following these best practices, you can minimize risks while leveraging dynamic HTML rendering in React.

Stay safe and happy coding! 🚀

Top comments (0)