React.js Security Misconfiguration (with Code)
Security misconfiguration is on the OWASP Top 10 for a reason. React apps often ship with dev defaults, permissive proxies, exposed source maps, or unsafe HTML rendering. Here’s a practical, code-first hardening guide—and a free scan to validate your fixes.
Read more posts at Pentest Testing Corp. ➜
1) Over-permissive CORS/proxy
Risk: Dev proxies and APIs that allow *
origins leak cookies and tokens.
Bad (src/setupProxy.js
):
const { createProxyMiddleware } = require('http-proxy-middleware');
module.exports = app => {
app.use('/api', createProxyMiddleware({
target: 'https://api.example.com',
changeOrigin: true, // ❌ allows any origin
}));
};
Safer (whitelist):
const allowed = ['https://app.example.com'];
module.exports = app => {
app.use('/api', (req, res, next) => {
if (!allowed.includes(req.headers.origin)) return res.sendStatus(403);
next();
});
};
2) Leaking env vars
Rules: Never commit .env
; only expose values meant for the client.
# .gitignore
.env
# .env.production
REACT_APP_API=https://api.example.com # ✅
# SECRET_API_KEY=... # ❌ keep on server only
Use it safely:
const api = process.env.REACT_APP_API;
3) Missing security headers (set at your web server)
Nginx example:
add_header X-Frame-Options "DENY" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "geolocation=(), camera=()" always;
add_header Content-Security-Policy "default-src 'self'; img-src 'self' data:; script-src 'self'; style-src 'self' 'unsafe-inline'" always;
If you also control the API, enable helmet
:
import helmet from "helmet";
app.use(helmet());
🖼️ Screenshot of our Free Website Vulnerability Scanner homepage showing the scan form.
Screenshot of the free tools webpage where you can access security assessment tools.
4) Publishing source maps
Source maps reveal file paths and sometimes hints to private code.
Create React App (build env):
GENERATE_SOURCEMAP=false npm run build
Vite (vite.config.js
):
export default { build: { sourcemap: false } };
5) XSS via dangerouslySetInnerHTML
Bad:
<div dangerouslySetInnerHTML={{ __html: userBio }} />
Fix with sanitization (DOMPurify):
import DOMPurify from 'dompurify';
const SafeHTML = ({ html }) => (
<div dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(html) }} />
);
6) Secure containers & static hosting
Minimal Dockerfile:
FROM node:20-alpine as build
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
FROM nginx:alpine
COPY --from=build /app/build /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
Quick Hardening Checklist
- Block
*
CORS; pin allowed origins. - Keep secrets server-side; only
REACT_APP_*
go to the client. - Add security headers (CSP, XFO, XCTO, Referrer-Policy, Permissions-Policy).
- Disable source maps in production builds.
- Sanitize any HTML before rendering.
- Review CI/CD so prod builds never use dev configs.
Scan Your Site (Free)
Run a non-intrusive scan to catch misconfigurations early: 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.
Need Hands-On Help?
Managed IT Services
We can operate and harden your stack end-to-end:
https://www.pentesttesting.com/managed-it-services/
AI Application Cybersecurity
Threat-model and secure LLM/AI apps, prompts, and data flows:
https://www.pentesttesting.com/ai-application-cybersecurity/
Offer Cybersecurity to Your Clients
Agency/MSP? White-label our security services:
https://www.pentesttesting.com/offer-cybersecurity-service-to-your-client/
Keep learning: More write-ups at https://www.pentesttesting.com/blog/
Newsletter: Subscribe on LinkedIn https://www.linkedin.com/build-relation/newsletter-follow?entityUrn=7327563980778995713
Pro tip:
Re-scan after every deployment to verify headers, CSP, and map settings haven’t regressed.
Top comments (0)