Skip to main content

Front-End OWASP Top 10: React Security Checklist

The OWASP Top 10 is a ranking of the most critical web application vulnerabilities. While the list has evolved (the 2025 edition includes Broken Access Control, Cryptographic Failures, Injection, Insecure Design, and others), many apply directly to React applications. This guide translates OWASP risks into React-specific checks: broken authentication, sensitive data exposure, injection attacks, insecure deserialization, and business logic flaws. Use this as a pre-deployment security audit checklist for your React app.

1. Broken Authentication and Session Management

OWASP Risk: Attackers can compromise user accounts, bypass login, or hijack sessions.

React Checklist:

  • Do you store authentication tokens in httpOnly cookies (not localStorage)?
  • Do you validate session tokens on the backend for every protected request?
  • Do you implement account lockout after failed login attempts (e.g., 5 attempts in 15 minutes)?
  • Do you force password reset after successful login from a new device/location (anomaly detection)?
  • Do you log all authentication events (logins, logouts, password resets)?
// Example: Validate backend session before trusting frontend state
app.get("/api/profile", (req, res) => {
const token = req.cookies.sessionToken;
if (!token || !isValidToken(token)) {
return res.status(401).json({ error: "Not authenticated" });
}
// Proceed only if token is valid server-side
res.json(user);
});

2. Cryptographic Failures (formerly "Sensitive Data Exposure")

OWASP Risk: Sensitive data is transmitted or stored unencrypted, exposing it to attackers.

React Checklist:

  • Are all API calls made over HTTPS (never HTTP)?
  • Do you use secure cookies with httpOnly, secure, and sameSite flags?
  • Are API keys kept out of the React bundle (stored only on backend)?
  • Do you avoid logging secrets (tokens, passwords, credit card numbers)?
  • Is sensitive data in transit encrypted and signed (TLS 1.2+)?
  • Do you avoid storing sensitive data in localStorage (use httpOnly cookies instead)?
// Verify your site uses HTTPS
console.assert(window.location.protocol === "https:", "Site must use HTTPS");

// Verify secure cookie setup
document.cookie; // Try to access cookies—should fail for httpOnly cookies

3. Injection (XSS, SQL Injection)

OWASP Risk: Malicious code or queries are injected through unsanitized input.

React Checklist:

  • Do you render user input as text (not HTML)? ({userInput} not dangerouslySetInnerHTML)?
  • If you must render HTML, do you use DOMPurify to sanitize?
  • Do you avoid eval(), Function(), setTimeout(userInput), or setInterval(userInput)?
  • Do you escape special characters in URLs and attributes?
  • Do you validate all user input on the backend (never trust client-side validation)?
  • Do you implement Content Security Policy (CSP) headers?
// Safe: React auto-escapes
<div>{userInput}</div>

// Unsafe: Manual HTML rendering
<div dangerouslySetInnerHTML={{ __html: userInput }} />

// Safe: Use DOMPurify
import DOMPurify from "dompurify";
<div dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(userInput) }} />

4. Insecure Design (Business Logic Flaws)

OWASP Risk: The application logic is flawed, allowing attackers to bypass intended controls.

React Checklist:

  • Can users access resources they should not (no authorization checks)?
  • Can users modify URLs or form fields to escalate privileges?
  • Are numeric IDs sequential? If so, can attackers enumerate resources by changing the ID?
  • Is the discount or promotion logic enforceable server-side, or can users modify prices client-side?
  • Can users complete workflows out of order (e.g., skip payment and go to confirmation)?
  • Is sensitive business logic duplicated on the frontend? (It should only be on the backend.)
// Vulnerable: Client-side price modification
const [price, setPrice] = useState(100);

function handleDiscountChange(discount) {
setPrice(100 - discount); // User can set any price!
}

// Safe: Prices and discounts calculated server-side
async function applyDiscount(discountCode) {
const response = await fetch("/api/apply-discount", {
method: "POST",
body: JSON.stringify({ discountCode })
});
const { finalPrice } = await response.json(); // Server calculated
setPrice(finalPrice);
}

5. Broken Access Control (formerly "Security Misconfiguration")

OWASP Risk: Users can access data or functions they should not.

React Checklist:

  • Are all API endpoints protected by role-based or attribute-based access control (RBAC/ABAC)?
  • Do you return only data the authenticated user is authorized to see?
  • Do you verify permissions on the backend (never trust role claims from React state)?
  • Can an attacker change their user ID in the URL and access another user's data?
  • Can an admin endpoint be called by regular users?
  • Are you using object references that are hard to guess (not sequential IDs)?
// Vulnerable: Backend trusts userId from URL
app.get("/api/users/:userId", (req, res) => {
const user = User.findById(req.params.userId); // Anyone can guess IDs!
res.json(user);
});

// Safe: Backend verifies the authenticated user owns the resource
app.get("/api/users/:userId", authenticateUser, (req, res) => {
if (req.params.userId !== req.user.id) {
return res.status(403).json({ error: "Forbidden" });
}
res.json(user);
});

6. Vulnerability and Outdated Components

OWASP Risk: Dependencies have known security flaws.

React Checklist:

  • Do you run npm audit regularly and fix vulnerabilities?
  • Are you on the latest stable version of React?
  • Do you audit your npm dependencies with tools like Snyk or Dependabot?
  • Do you remove unused dependencies (reduce attack surface)?
  • Do you pin dependency versions to avoid surprise breaking changes?
  • Do you review dependency licenses for compliance?
# Audit dependencies
npm audit

# Fix vulnerabilities
npm audit fix

# Check with Snyk
npx snyk test

# Update all dependencies safely
npm outdated # See what's outdated
npm update # Update within semver ranges

7. Insufficient Logging and Monitoring

OWASP Risk: Attackers hide their tracks; you don't detect breaches.

React Checklist:

  • Do you log all authentication attempts (successful and failed)?
  • Do you log sensitive operations (payment, data deletion, role changes)?
  • Are logs stored securely and not accessible to attackers?
  • Do you monitor for suspicious patterns (e.g., repeated 401 errors, rapid requests)?
  • Do you alert on security events in real time?
  • Are logs retained long enough for forensics (typically 90+ days)?
// Log authentication events
app.post("/api/login", async (req, res) => {
const success = await authenticate(req.body.email, req.body.password);
auditLog({
event: "login_attempt",
email: req.body.email,
success,
ip: req.ip,
timestamp: new Date()
});
// ...
});

// Log suspicious activity
if (failedLogins > 5) {
alertSecurityTeam(`Brute force attempt: ${email} from ${ip}`);
}

8. Software and Data Integrity Failures

OWASP Risk: Untrusted code or data updates introduce vulnerabilities.

React Checklist:

  • Do you verify CDN and npm package integrity (use Subresource Integrity, npm lockfiles)?
  • Do you use a build process that does not trust untrusted data?
  • Do you pin npm package versions and review updates before installing?
  • Do you verify code integrity before running (e.g., signed commits, code review)?
  • Is your CI/CD pipeline secure (protected secrets, limited access)?
<!-- Use Subresource Integrity for CDN scripts -->
<script
src="https://cdn.example.com/library.js"
integrity="sha384-abcd1234..."
crossorigin="anonymous"
></script>

9. Using Components with Known Vulnerabilities

OWASP Risk: Dependencies have exploitable flaws.

React Checklist:

  • Does your React version have known CVEs? Check CVE Details.
  • Do you use old or unmaintained React libraries?
  • Have you tested your app against known exploits in your dependencies?
  • Do you have a process to update dependencies within 30 days of security patches?
# Check for vulnerable React version
npm install [email protected] # Use latest stable

# Check all dependencies
npm audit --production # Production dependencies only

10. Insufficient Rate Limiting and Brute Force Protection

OWASP Risk: Attackers abuse endpoints with unlimited requests (login brute force, credential stuffing, DoS).

React Checklist:

  • Do you rate-limit login attempts (e.g., 5 attempts per 15 minutes)?
  • Do you rate-limit API endpoints (e.g., 100 requests per minute per user)?
  • Do you use CAPTCHA on repeated failed attempts?
  • Do you implement exponential backoff (increasing delays between failed attempts)?
  • Do you block IPs that make excessive requests?
// Backend rate limiting
import rateLimit from "express-rate-limit";

const loginLimiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 5, // 5 requests per windowMs
message: "Too many login attempts, please try again later."
});

app.post("/api/login", loginLimiter, async (req, res) => {
// Process login
});

Pre-Deployment Security Checklist

Before deploying your React app to production, run through this checklist:

  • All secrets are kept out of the bundle (no API keys, tokens, or passwords in .env or code)
  • Environment variables are configured correctly (VITE_, REACT_APP_)
  • HTTPS is enforced (redirect HTTP to HTTPS)
  • Security headers are set (CSP, X-Frame-Options, X-Content-Type-Options)
  • Authentication is session-based with httpOnly cookies
  • CSRF tokens are implemented on all state-changing forms
  • User input is sanitized and escaped
  • API responses are limited to authorized data
  • Error messages do not leak sensitive information
  • Logging does not expose secrets or PII
  • Dependencies are audited and up-to-date
  • Rate limiting is configured on the backend
  • Monitoring and alerting are configured
  • Privacy policy and consent mechanisms are implemented
  • Code review and security testing have been completed

Key Takeaways

  • The OWASP Top 10 provides a framework for identifying critical vulnerabilities.
  • Many OWASP risks apply to React: broken auth, injection, CSRF, broken access control.
  • Security is a shared responsibility between frontend and backend; most checks require backend validation.
  • Use this checklist before deploying every major release.
  • Security is not a one-time effort; audit regularly and monitor in production.

Frequently Asked Questions

Should I implement all OWASP recommendations, or are some optional?

Prioritize based on your application's risk profile. A financial app needs all checks; a personal blog might skip some. Start with the Top 10 and add more as needed.

Who should perform security audits?

Ideally, a dedicated security engineer or a third-party penetration tester. For smaller teams, have a developer (not the original author) review the code against the OWASP checklist.

How often should I audit my React app for OWASP compliance?

Audit before every production deployment and annually for ongoing monitoring. Audit immediately when a new critical vulnerability is discovered in your dependencies.

Are OWASP checks enough, or should I do additional security testing?

OWASP is a good foundation, but consider adding: penetration testing, dependency scanning (Snyk), static code analysis (SonarQube), and dynamic scanning (DAST tools).

Further Reading