Sensitive Data Exposure in React.js (and How to Fix It Fast)
React Sensitive Data Exposure: Best Practices
Sensitive 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/
1) Never Ship Secrets to the Browser
Don’t do this:
// BAD: bundled into JS sent to users
export const STRIPE_SECRET = "sk_live_...";
Do this (proxy on the server):
// client
async function pay(data){
const res = await fetch("/api/pay", {method:"POST", body:JSON.stringify(data)});
return res.json();
}
// server (example express)
app.post("/api/pay", async (req,res)=>{
const stripe = new Stripe(process.env.STRIPE_SECRET);
const charge = await stripe.charges.create({...req.body});
res.json({id: charge.id});
});
2) Keep Tokens Out of localStorage
Use HTTP-only cookies so JS can’t read tokens.
// server: set cookie
res.cookie("session", token, { httpOnly:true, secure:true, sameSite:"Strict" });
// client: no manual token handling needed
fetch("/api/me", { credentials:"include" });
3) Strip Logs & Errors in Production
// Vite
export default {
define: { "process.env.NODE_ENV":"\"production\"" },
esbuild: { drop: ["console","debugger"] }
}
// Error Boundary (redact PII)
class SafeBoundary extends React.Component{
componentDidCatch(){ /* send minimal, scrubbed telemetry */ }
render(){ return this.props.children; }
}
4) Don’t Leak via Source Maps
# CRA
GENERATE_SOURCEMAP=false npm run build
// Vite
export default { build:{ sourcemap:false } }
5) Prevent Data in Client-Side Env
Remember: REACT_APP_*
/ import.meta.env.*
are PUBLIC. Keep only non-secret config there; real secrets live on the server.
# ok (non-secret)
VITE_API_BASE="https://api.example.com"
6) Content Security Policy (CSP)
<meta http-equiv="Content-Security-Policy"
content="default-src 'self'; script-src 'self'; connect-src 'self' https://api.example.com; frame-ancestors 'none'; base-uri 'self'">
7) Mask PII Before Sending Logs
const MASK=/\b(\d{4})\d{8}(\d{4})\b/g;
const scrub = s => s.replace(MASK,"$1********$2");
Screenshot of Our Website Vulnerability Scanner tool homepage
![]() |
Screenshot of the free tools webpage where you can access security assessment tools. |
Run a quick check of your public site or staging host with our free Website Security Checker: https://free.pentesttesting.com/
Sample assessment report generated by our free tool to check Website Vulnerability
![]() |
Sample vulnerability assessment report generated with our free tool, providing insights into possible vulnerabilities. |
Quick React Security Checklist
-
No secrets in client bundle
-
Tokens in HTTP-only cookies
-
console
/debugger
dropped in prod -
Source maps disabled or gated
-
Strict CSP set
-
PII scrubbing in logs
-
Public env only for non-secrets
Related Services
Managed IT Services: End-to-end ops, patching, monitoring, and response for your stack. https://www.pentesttesting.com/managed-it-services/
AI Application Cybersecurity: Threat modeling, red-teaming, and guardrails for LLM/AI apps. https://www.pentesttesting.com/ai-application-cybersecurity/
Offer Cybersecurity to Your Clients: White-label pentesting & audits for agencies/MSPs. https://www.pentesttesting.com/offer-cybersecurity-service-to-your-client/
Stay updated: Subscribe on LinkedIn https://www.linkedin.com/build-relation/newsletter-follow?entityUrn=7327563980778995713
Comments
Post a Comment