UNPKG

secure-express-setup

Version:

Military-grade one-command security setup for Express.js applications

71 lines (56 loc) 3.18 kB
// lib/headers.js /** * Sets explicit, configurable security HTTP headers. * Use in addition to helmet when you need exact header values * or want to guarantee header presence for tests. */ function setupHeaders(options = {}) { const cfg = { xFrameOptions: options.xFrameOptions || 'DENY', // X-Frame-Options xContentTypeOptions: options.xContentTypeOptions || 'nosniff', // X-Content-Type-Options referrerPolicy: options.referrerPolicy || 'strict-origin-when-cross-origin', contentSecurityPolicy: options.contentSecurityPolicy || null, // string or null strictTransportSecurity: options.strictTransportSecurity || { maxAge: 31536000, includeSubDomains: true, preload: true }, permissionsPolicy: options.permissionsPolicy || null, // e.g. "geolocation=(), microphone=()" expectCt: options.expectCt || null, // e.g. 'max-age=86400, enforce' crossOriginEmbedderPolicy: options.crossOriginEmbedderPolicy || 'require-corp', crossOriginOpenerPolicy: options.crossOriginOpenerPolicy || 'same-origin', crossOriginResourcePolicy: options.crossOriginResourcePolicy || 'same-origin' }; return (req, res, next) => { // X-Frame-Options if (cfg.xFrameOptions) res.setHeader('X-Frame-Options', cfg.xFrameOptions); // X-Content-Type-Options if (cfg.xContentTypeOptions) res.setHeader('X-Content-Type-Options', cfg.xContentTypeOptions); // Referrer-Policy if (cfg.referrerPolicy) res.setHeader('Referrer-Policy', cfg.referrerPolicy); // Strict-Transport-Security (HSTS) - only set on HTTPS in production ideally if (cfg.strictTransportSecurity) { const { maxAge = 31536000, includeSubDomains = true, preload = false } = cfg.strictTransportSecurity; let hsts = `max-age=${maxAge}`; if (includeSubDomains) hsts += '; includeSubDomains'; if (preload) hsts += '; preload'; res.setHeader('Strict-Transport-Security', hsts); } // Content-Security-Policy - remember this may need to be tailored for your app if (cfg.contentSecurityPolicy) { res.setHeader('Content-Security-Policy', cfg.contentSecurityPolicy); } // Permissions-Policy (formerly Feature-Policy) if (cfg.permissionsPolicy) { res.setHeader('Permissions-Policy', cfg.permissionsPolicy); } // Expect-CT (optional) if (cfg.expectCt) res.setHeader('Expect-CT', cfg.expectCt); // Cross-Origin-Embedder-Policy if (cfg.crossOriginEmbedderPolicy) res.setHeader('Cross-Origin-Embedder-Policy', cfg.crossOriginEmbedderPolicy); // Cross-Origin-Opener-Policy if (cfg.crossOriginOpenerPolicy) res.setHeader('Cross-Origin-Opener-Policy', cfg.crossOriginOpenerPolicy); // Cross-Origin-Resource-Policy if (cfg.crossOriginResourcePolicy) res.setHeader('Cross-Origin-Resource-Policy', cfg.crossOriginResourcePolicy); // Minimal protective header for clickjacking fallback (already set via X-Frame-Options above) // Additional custom headers can be added here if required next(); }; } module.exports = setupHeaders;