/** * Security Headers Middleware (inst_044 - Quick Win Version) * Implements comprehensive HTTP security headers * * QUICK WIN: Low effort, high value security improvement * - Prevents XSS, clickjacking, MIME sniffing attacks * - Enforces HTTPS, limits referrer leakage * - Restricts dangerous browser features */ /** * Apply security headers to all HTTP responses */ function securityHeadersMiddleware(req, res, next) { // Content Security Policy (enforces inst_008 at HTTP level) // Allows Tailwind inline styles, blocks inline scripts res.setHeader( 'Content-Security-Policy', [ "default-src 'self'", "script-src 'self'", // All JS self-hosted "style-src 'self' 'unsafe-inline'", // Tailwind (self-hosted fonts) "img-src 'self' data: https:", "font-src 'self'", // Self-hosted fonts only (no Google, no CDN) "connect-src 'self'", "frame-ancestors 'none'", "base-uri 'self'", "form-action 'self'", 'upgrade-insecure-requests' ].join('; ') ); // Prevent MIME type sniffing attacks res.setHeader('X-Content-Type-Options', 'nosniff'); // Prevent clickjacking via iframes res.setHeader('X-Frame-Options', 'DENY'); // Enable browser XSS filter (legacy browsers) res.setHeader('X-XSS-Protection', '1; mode=block'); // Enforce HTTPS (HSTS) - only add if HTTPS is available if (req.secure || req.get('x-forwarded-proto') === 'https') { res.setHeader( 'Strict-Transport-Security', 'max-age=31536000; includeSubDomains' // 1 year ); } // Limit referrer information leakage res.setHeader('Referrer-Policy', 'strict-origin-when-cross-origin'); // Restrict dangerous browser features res.setHeader( 'Permissions-Policy', 'geolocation=(), microphone=(), camera=(), payment=()' ); // Cache Control: NEVER cache admin files or API responses if (req.path.startsWith('/admin/') || req.path.startsWith('/js/admin/') || req.path.startsWith('/api/')) { res.setHeader('Cache-Control', 'no-store, no-cache, must-revalidate, proxy-revalidate'); res.setHeader('Pragma', 'no-cache'); res.setHeader('Expires', '0'); } next(); } module.exports = { securityHeadersMiddleware };