Posts

Server-Side Request Forgery (SSRF) in React.js

Image
SSRF isn’t a React bug—it’s a back-end flaw your React app can accidentally trigger. When a front-end sends a URL to an API that then fetches it server-side, attackers can pivot that API to read internal services, cloud metadata, or files. Read more security posts: https://www.pentesttesting.com/blog/ How React Front-Ends Accidentally Cause SSRF React UIs often have features like “Preview URL”, “Import from RSS”, or “Fetch webhook status”. If the server blindly fetches user-supplied URLs, it might access http://169.254.169.254/ (cloud creds), http://localhost:2375/ (Docker), or internal hosts like http://intranet-db:5432 . Vulnerable Pattern (React + Node) React component (sends any URL to the API): // Danger: lets users request any URL via your server export default function Preview() { const [url, setUrl] = React.useState(""); const [data, setData] = React.useState(""); const go = async () => { const res = await fetch("/api/fetch?url=...

React.js RCE: How Exploits Happen & How to Prevent

Image
Why “RCE in React” is a Real Risk React runs in the browser, but teams often pair it with Node.js (SSR/APIs), third-party packages, and build tools. Attackers abuse these touchpoints to turn a simple bug into Remote Code Execution (RCE) on the server, the CI runner, or even in hybrid shells like Electron. This guide explains the main paths and how to stop them. For more security insights, see our blog: Pentest Testing Blog . How RCE Reaches React Projects DOM XSS → Code Execution Untrusted HTML + dangerouslySetInnerHTML lets attackers run arbitrary JS, which can pivot to RCE in Electron or backend bridges. // ❌ Vulnerable: untrusted HTML dropped into the DOM export default function Post({ html }) { return <div dangerouslySetInnerHTML={{ __html: html }} />; } // ✅ Safer: sanitize first import DOMPurify from 'dompurify'; export function SafePost({ html }) { const clean = DOMPurify.sanitize(html, { USE_PROFILES: { html: true } }); return <div dangerousl...

Sensitive Data Exposure in React.js (and How to Fix It Fast)

Image
React Sensitive Data Exposure: Best Practices S ensitive data exposure in React apps often comes from shipping secrets in the bundle, leaking tokens in storage/logs, permissive source maps, or overly chatty APIs. Below are practical, copy-paste fixes you can apply today. For more articles, visit our blog: https://www.pentesttesting.com/blog/

Broken Authentication in React.js: Fix It Fast

Image
Why Broken Authentication Happens in React.js React apps often leak auth via insecure token storage, trusting client flags, weak session handling, or missing rate-limits/MFA. Attackers turn these into account takeovers. For more security reads, explore the Pentest Testing Blog . Mistake #1: Storing JWT in localStorage Anti-pattern // DON'T: token persists, XSS = full account takeover const login = async (u, p) => { const r = await fetch('/api/login',{method:'POST',body:JSON.stringify({u,p})}); const {token} = await r.json(); localStorage.setItem('token', token); }; Secure pattern: httpOnly cookie + CSRF // DO: rely on httpOnly cookie; send CSRF from meta tag or /csrf endpoint const login = async (u, p, csrf) => { await fetch('/api/login', { method:'POST', headers:{'Content-Type':'application/json','X-CSRF-Token':csrf}, credentials:'include', body:JSON.stringify({u,p}) }); }; S ...

CSRF Prevention in React.js: A Practical Guide

Image
Why CSRF Still Breaks React Apps Cross-Site Request Forgery (CSRF) tricks a logged-in user’s browser into sending unwanted requests. In React.js, the fix is simple:  use anti-CSRF tokens + SameSite cookies + “credentialed” requests . This post shows working patterns you can paste in today. React protects the UI, not your cookies. If your session cookie is sent automatically, a malicious site can trigger state-changing requests on your behalf. Let’s fix that—with code. Core Defenses (Quick Wins) Use SameSite cookies + Secure + HttpOnly . Require an anti-CSRF token on every state-changing request. Enforce CORS and origin/referrer checks server-side. For more articles, see the Pentest Testing Corp blog: https://www.pentesttesting.com/blog/

React XSS Prevention: Safe HTML & DOMPurify

Image
Why XSS Still Happens in React React escapes strings by default, but XSS sneaks in via dangerouslySetInnerHTML , user-controlled URLs, third-party widgets, and lax CSP. Here’s a concise, copy-paste guide to XSS prevention in React.js . Quick Wins Checklist Sanitize any HTML before rendering Block javascript: / data: URLs Encode output and attributes Use Content-Security-Policy (CSP) Keep dependencies & React updated Copy-Paste React Snippets 1) Safe HTML rendering (DOMPurify) import DOMPurify from 'dompurify'; function SafeHTML({ html }) { const clean = DOMPurify.sanitize(html, { USE_PROFILES: { html: true } }); return <div dangerouslySetInnerHTML={{ __html: clean }} />; } 2) Never trust URLs (block scripts) const safeHref = (u) => /^https?:\/\//i.test(u) ? u : '#'; <a href={safeHref(userInputUrl)}>Open</a> 3) Encode text output function Text({ value }) { return <span>{String(value)}</span>; } 4) ...

SQL Injection Mitigation for React Apps (2025 Guide)

Image
  Why React apps still face SQL injection React runs in the browser; SQL injection (SQLi) happens on the server . The risk appears when your API builds SQL from untrusted input. Your React code must send data safely, but mitigation lives in your backend (Node/Express, Nest, Rails, Django, etc.). A quick mental model Never concatenate SQL strings. Always use parameterized queries or an ORM. Validate & sanitize at the API boundary. Prefer POST/JSON from React; avoid query-string stuffing. Least-privilege DB users + prepared statements everywhere. Vulnerable server (Node + Express + MySQL) // ❌ Vulnerable: string concatenation app.get('/user', async (req, res) => { const id = req.query.id; // ?id=1 OR 1=1 const rows = await db.query(`SELECT * FROM users WHERE id = ${id}`); res.json(rows); }); Fixed with parameterized queries // ✅ Safe: placeholders app.get('/user', async (req, res) => { const id = Number(req.query.id); co...