tractatus/src/middleware/security-headers.middleware.js
TheFlow 7f6192cbd6 refactor(lint): fix code style and unused variables across src/
- Fixed unused function parameters by prefixing with underscore
- Removed unused imports and variables
- Applied eslint --fix for automatic style fixes
  - Property shorthand
  - String template literals
  - Prefer const over let where appropriate
  - Spacing and formatting

Reduces lint errors from 108+ to 78 (61 unused vars, 17 other issues)

Related to CI lint failures in previous commit

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-24 20:15:26 +13:00

71 lines
2.2 KiB
JavaScript

/**
* 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' https://cdn.jsdelivr.net", // Allow Chart.js CDN
"style-src 'self' 'unsafe-inline' https://fonts.googleapis.com", // Tailwind + Google Fonts
"img-src 'self' data: https:",
"font-src 'self' https://fonts.gstatic.com https://cdnjs.cloudflare.com",
"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 };