fix(security): enhance security headers and tighten CORS configuration
- Configure custom Content Security Policy for React app compatibility - Add Permissions-Policy header to disable unnecessary browser features - Set HSTS to 1 year with preload flag for better transport security - Update referrer policy to strict-origin-when-cross-origin - Restrict CORS localhost origins to development environment only - Production deployments now only allow configured FRONTEND_URL and ADMIN_URL - Addresses security headers configuration issues from security scan 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
This commit is contained in:
+41
-7
@@ -28,21 +28,55 @@ const adminAuthRoutes = require('./src/routes/adminAuth');
|
|||||||
const app = express();
|
const app = express();
|
||||||
const PORT = process.env.PORT || 3000;
|
const PORT = process.env.PORT || 3000;
|
||||||
|
|
||||||
// Security middleware
|
// Security middleware with custom CSP
|
||||||
app.use(helmet());
|
app.use(helmet({
|
||||||
|
contentSecurityPolicy: {
|
||||||
|
directives: {
|
||||||
|
defaultSrc: ["'self'"],
|
||||||
|
scriptSrc: ["'self'", "'unsafe-inline'"], // Required for React
|
||||||
|
styleSrc: ["'self'", "'unsafe-inline'", "https:"], // Required for styled components
|
||||||
|
imgSrc: ["'self'", "data:", "https:", "blob:"], // Allow data URLs and external images
|
||||||
|
connectSrc: ["'self'"], // API connections
|
||||||
|
fontSrc: ["'self'", "https:", "data:"], // Web fonts
|
||||||
|
objectSrc: ["'none'"], // Disable plugins
|
||||||
|
mediaSrc: ["'self'"], // Audio/video
|
||||||
|
frameSrc: ["'none'"], // Disable iframes
|
||||||
|
},
|
||||||
|
},
|
||||||
|
hsts: {
|
||||||
|
maxAge: 31536000, // 1 year
|
||||||
|
includeSubDomains: true,
|
||||||
|
preload: true
|
||||||
|
},
|
||||||
|
permittedCrossDomainPolicies: false,
|
||||||
|
referrerPolicy: { policy: "strict-origin-when-cross-origin" }
|
||||||
|
}));
|
||||||
|
|
||||||
|
// Additional security headers
|
||||||
|
app.use((req, res, next) => {
|
||||||
|
// Permissions Policy (controls browser features)
|
||||||
|
res.setHeader('Permissions-Policy', 'camera=(), microphone=(), geolocation=(), payment=()');
|
||||||
|
next();
|
||||||
|
});
|
||||||
|
|
||||||
// CORS configuration
|
// CORS configuration
|
||||||
const corsOptions = {
|
const corsOptions = {
|
||||||
origin: function (origin, callback) {
|
origin: function (origin, callback) {
|
||||||
const allowedOrigins = [
|
const allowedOrigins = [
|
||||||
process.env.FRONTEND_URL || 'http://localhost:3005',
|
process.env.FRONTEND_URL || 'http://localhost:3005',
|
||||||
process.env.ADMIN_URL || 'http://localhost:3005',
|
process.env.ADMIN_URL || 'http://localhost:3005'
|
||||||
'http://localhost:5173', // Vite dev server
|
|
||||||
'http://localhost:3002', // Backend server
|
|
||||||
'http://localhost:3001', // For API testing
|
|
||||||
'http://localhost:3000' // Direct backend access
|
|
||||||
];
|
];
|
||||||
|
|
||||||
|
// In development, also allow localhost origins
|
||||||
|
if (process.env.NODE_ENV === 'development') {
|
||||||
|
allowedOrigins.push(
|
||||||
|
'http://localhost:5173', // Vite dev server
|
||||||
|
'http://localhost:3002', // Backend server
|
||||||
|
'http://localhost:3001', // For API testing
|
||||||
|
'http://localhost:3000' // Direct backend access
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// Allow requests with no origin (like mobile apps or curl)
|
// Allow requests with no origin (like mobile apps or curl)
|
||||||
if (!origin || allowedOrigins.indexOf(origin) !== -1) {
|
if (!origin || allowedOrigins.indexOf(origin) !== -1) {
|
||||||
callback(null, true);
|
callback(null, true);
|
||||||
|
|||||||
Reference in New Issue
Block a user