| technology | React | |||||||
|---|---|---|---|---|---|---|---|---|
| domain | frontend | |||||||
| level | Senior/Architect | |||||||
| version | 19+ | |||||||
| tags |
|
|||||||
| ai_role | Senior React Security Expert | |||||||
| last_updated | 2026-04-05 |
- Primary Goal: Establish ironclad security constraints for React applications.
- Target Tooling: Cursor, Windsurf, Antigravity.
- Tech Stack Version: React 19+
Important
Strict Constraints for AI:
- Never bypass React's built-in XSS protection without rigorous justification and secondary sanitization.
- Always handle sensitive data exclusively within Server Components or Server Actions.
Note
Context: Rendering raw HTML from external or untrusted sources.
function Article({ content }: { content: string }) {
// content might be "<img src=x onerror=alert('XSS')>"
return <div dangerouslySetInnerHTML={{ __html: content }} />;
}Using dangerouslySetInnerHTML bypasses React's automatic string escaping. If the input is not sanitized, malicious scripts can execute within the user's browser, leading to session hijacking or data theft.
import DOMPurify from 'dompurify';
function Article({ content }: { content: string }) {
const sanitizedContent = DOMPurify.sanitize(content);
return <div dangerouslySetInnerHTML={{ __html: sanitizedContent }} />;
}If you must render raw HTML, strictly sanitize it using a robust library like DOMPurify before injecting it into the DOM. Whenever possible, rely on React's default text rendering, which automatically escapes embedded data.
Note
Context: Accessing environment variables and sensitive configuration.
// Inside a Client Component
export function PaymentGateway() {
const apiKey = process.env.STRIPE_SECRET_KEY;
return <button onClick={() => processPayment(apiKey)}>Pay Now</button>;
}Exposing secret keys or database credentials to the client bundle allows attackers to easily extract them, compromising the entire infrastructure.
// Server Action (actions.ts)
'use server';
export async function processPaymentAction() {
const apiKey = process.env.STRIPE_SECRET_KEY;
// securely interact with Stripe backend here
return { success: true };
}
// Client Component
'use client';
import { processPaymentAction } from './actions';
export function PaymentGateway() {
return <button onClick={() => processPaymentAction()}>Pay Now</button>;
}Leverage React Server Components and Server Actions ('use server') to keep sensitive logic, secrets, and database connections entirely on the server. The client only receives the safe, computed result.