JS Guide
HomeQuestionsSearchResources
Search

Built for developers preparing for JavaScript, React & TypeScript interviews.

ResourcesQuestionsSupport
HomeQuestionsSearchProgress
HomeQuestionsreact
Prev
react
senior
security

What security vulnerabilities should you address in React applications and how do you prevent them?

security
xss
csrf
authentication
sanitization
cookies
dompurify
Quick Answer

Key vulnerabilities include XSS (mitigated by React's auto-escaping, but watch dangerouslySetInnerHTML and URL injection), CSRF (use tokens in API requests, SameSite cookies), and insecure storage (avoid localStorage for sensitive data, prefer httpOnly cookies).

Detailed Explanation

XSS (Cross-Site Scripting):

  1. React's Built-in Protection:

    • JSX auto-escapes values in {} by default
    • <div>{userInput}</div> is safe
  2. XSS Vectors to Watch:

    • dangerouslySetInnerHTML - bypasses escaping, sanitize with DOMPurify
    • javascript: URLs in href/src - NOT escaped, validate URLs
    • Inline event handlers from user data

CSRF (Cross-Site Request Forgery):

  • React doesn't prevent CSRF - it's a UI library
  • Include CSRF tokens in state-changing requests
  • Use SameSite=Strict or SameSite=Lax cookies
  • Never use GET for mutations

Authentication & Storage:

  • localStorage is vulnerable to XSS (any script can read it)
  • httpOnly cookies are safer but have CSRF risk
  • Best: httpOnly cookies + CSRF tokens
  • Never store secrets in frontend code

Additional Security Measures:

  • Content Security Policy (CSP) headers
  • HTTPS everywhere, Secure cookie flag
  • Regular npm audit for vulnerable dependencies
  • Input validation on server (frontend is UX only)

Code Examples

XSS prevention patterns
// SAFE: React auto-escapes by default
function Comment({ text }) {
  return <p>{text}</p>; // <script> becomes &lt;script&gt;
}

// DANGEROUS: dangerouslySetInnerHTML bypasses escaping
function UnsafeHTML({ html }) {
  return <div dangerouslySetInnerHTML={{ __html: html }} />;
}

// SAFE: Sanitize with DOMPurify before using
import DOMPurify from 'dompurify';

function SafeHTML({ html }) {
  const sanitized = DOMPurify.sanitize(html, {
    ALLOWED_TAGS: ['b', 'i', 'em', 'strong', 'a', 'p'],
    ALLOWED_ATTR: ['href', 'target']
  });
  return <div dangerouslySetInnerHTML={{ __html: sanitized }} />;
}

// DANGEROUS: javascript: URL injection
function UnsafeLink({ href, children }) {
  // User could pass: javascript:alert('XSS')
  return <a href={href}>{children}</a>;
}

// SAFE: Validate URL protocol
function SafeLink({ href, children }) {
  const isValidUrl = (url) => {
    try {
      const parsed = new URL(url, window.location.origin);
      return ['http:', 'https:', 'mailto:'].includes(parsed.protocol);
    } catch {
      return false;
    }
  };

  if (!isValidUrl(href)) {
    return <span>{children}</span>; // Render as text
  }
  return <a href={href}>{children}</a>;
}

Resources

React Security Best Practices 2025

article

OWASP React Security Cheat Sheet

docs

DOMPurify - Sanitization Library

docs

Related Questions

What is CORS, when do CORS errors occur, and how can they be resolved?

senior
web-apis

How do Error Boundaries work in React and what are their limitations?

senior
error-handling
Previous
What is Redux and Redux Thunk, and how do they manage application state and async operations?