skip to content
logo
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.

Terminal window
npm audit
yarn 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 Middleware
import 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.