Building secure React applications requires more than just following best practices—it demands understanding the specific vulnerabilities that single-page applications face and implementing defensive patterns from the start.
1. Prevent Cross-Site Scripting (XSS)
By default, React escapes values in JSX. But shortcuts like dangerouslySetInnerHTML
open the door to attackers:
// Vulnerable <div dangerouslySetInnerHTML={{__html: user.bio}} />
Instead, sanitize with a trusted library:
import DOMPurify from 'dompurify'; const safeBio = DOMPurify.sanitize(user.bio); <div dangerouslySetInnerHTML={{__html: safeBio}} />
2. Treat Authentication as Sacred
Tokens in localStorage
are exposed to XSS. A safer pattern is httpOnly cookies with CSRF tokens:
await fetch('/api/login', { method: 'POST', credentials: 'include', headers: { 'Content-Type': 'application/json', 'X-CSRF-Token': await getCSRFToken() }, body: JSON.stringify(credentials) });
3. Sanitize Props and Inputs
Props aren’t immune. Always validate and sanitize before rendering:
const cleanQuery = query.replace(/[<>]/g, ''); <h2>Results for: {cleanQuery}</h2>
4. Keep State Lean
Context and Redux should not carry secrets. Expose only what the UI truly needs (permissions, IDs, roles).
5. Respect Environment Configurations
Anything prefixed with REACT_APP_
is visible to the client. Keep true secrets server-side, delivered through a secure API.
6. Secure Headers at Deployment
Defend React apps at the edge by setting strict headers:
res.setHeader('Strict-Transport-Security', 'max-age=31536000'); res.setHeader('Content-Security-Policy', "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'" );
Security isn’t a feature; it’s a foundation.
When baked into your React components and architecture, these patterns create user trust that lasts.
Looking for a partner who builds React apps with security at the core?
See how I help teams deliver resilient frontends: kodex.studio
Top comments (2)
Great breakdown of React security essentials !! I especially appreciate the emphasis on avoiding 'dangerouslySetInnerHTML' it's a common pitfall for developers new to React. One additional layer I’ve found useful is implementing a Content Security Policy (CSP) that includes a nonce for inline scripts. It’s a bit more work but can significantly reduce XSS risks.
Curious how do you approach balancing security with performance, especially when sanitizing large amounts of user-generated content?
Absolutely spot on!
I’ve faced similar challenges, especially with XSS vulnerabilities when rendering user-generated content. Using DOMPurify saved me from a lot of headaches.
Another thing I’ve found useful is keeping state minimal , never store sensitive info in Redux or Context; just the info needed for the UI. It’s crazy how many people overlook that in SPAs.
how do you handle refresh tokens securely in client-heavy React apps? Do you lean fully on httpOnly cookies or a hybrid approach?