Lesser-Known React Security Risks
/ 2 min read
Table of Contents
Hidden Security Risks in React Applications
Many React security vulnerabilities go unnoticed until an exploit happens.
This guide covers:
- JSX injection risks
- Prototype pollution via user input
- Exposing sensitive state data
- Security risks from dependencies
1. JSX Injection: Cross-Site Scripting (XSS) Risks
React escapes content by default, but dangerouslySetInnerHTML can introduce XSS vulnerabilities.
Bad: Using dangerouslySetInnerHTML
with Unsanitized Input
const userInput = '<img src=x onerror=alert("XSS")>';
const UnsafeComponent = () => ( <div dangerouslySetInnerHTML={{ __html: userInput }} />);
Solution: Sanitize Input Before Rendering
Use DOMPurify to sanitize untrusted input.
import DOMPurify from "dompurify";
const SafeComponent = () => ( <div dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(userInput) }} />);
2. Prototype Pollution via User Input
Allowing untrusted data in object properties can modify the JavaScript prototype, leading to security issues.
Vulnerable Code
const userPreferences = JSON.parse('{"__proto__": {"isAdmin": true}}');
console.log({}.isAdmin); // true - Prototype pollution occurred
Fix: Use Object.create(null)
for Safe Objects
const safeObject = Object.create(null);Object.assign(safeObject, userPreferences);
3. Exposing Sensitive State in the Browser
Storing tokens, API keys, or user roles in React state makes them visible in browser dev tools.
Bad: Storing API Keys in State
const [apiKey, setApiKey] = useState("secret-key-123");
Fix: Store Sensitive Data in HTTP-Only Cookies
Use secure cookies to store sensitive data.
// Server-side (Express.js)import cookieParser from "cookie-parser";
app.use(cookieParser());app.post("/login", (req, res) => { res.cookie("auth_token", "secure-token", { httpOnly: true, secure: true }); res.send("Logged in");});
4. Security Risks from Third-Party Dependencies
Unmaintained or vulnerable dependencies can introduce security flaws.
Check for Vulnerabilities
Use npm audit
or yarn audit
to detect package issues.
npm audityarn audit
Lock Dependency Versions
Avoid automatic updates that introduce security risks.
"dependencies": { "react": "18.2.0", "react-dom": "18.2.0"}
5. Prevent Clickjacking with CSP and Frameguard
Clickjacking occurs when an attacker embeds your React app inside an <iframe>
to steal user interactions.
Fix: Prevent Embedding via HTTP Headers
// Express.js Middlewareimport helmet from "helmet";app.use(helmet.frameguard({ action: "deny" }));
Conclusion
- Sanitize user input to prevent JSX injection.
- Avoid prototype pollution by securing object assignments.
- Store sensitive data securely, not in React state.
- Audit dependencies regularly to remove vulnerabilities.
- Prevent clickjacking using security headers.
Security is proactive — implement these safeguards before vulnerabilities are exploited.