Securing Headers with Helmet
HTTP response headers are a cheap but powerful security lever. Headers like Content-Security-Policy, X-Frame-Options, and Strict-Transport-Security tell browsers how to behave when rendering your responses — blocking inline scripts from XSS payloads, refusing to render your page in an iframe, and requiring HTTPS. Helmet is an Express middleware that sets a sensible default for all of them in one call. This page explains what each header does, how to configure Helmet, and the one that requires genuine thought: Content Security Policy.
Install and use
npm install helmet
import helmet from 'helmet' import express from 'express' const app = express() app.use(helmet()) // sets 11 security headers with safe defaults
What Helmet sets
Header | What it does |
|---|---|
| Controls which scripts/styles/frames are allowed — primary XSS mitigation |
| Blocks your page from being embedded in an iframe (clickjacking) |
| Tells browsers to always use HTTPS (HSTS) |
| Prevents MIME-type sniffing |
| Controls how much URL info is sent in the Referer header |
| Disables unused browser features (camera, geolocation, etc.) |
| Prevents DNS prefetching that leaks browsing intent |
| Isolates browsing context to prevent cross-origin info leaks |
Content Security Policy — the powerful one
app.use(helmet({
contentSecurityPolicy: {
directives: {
defaultSrc: ["'self'"], // fallback: only same origin
scriptSrc: ["'self'", 'cdn.jsdelivr.net'], // allow scripts from CDN
styleSrc: ["'self'", "'unsafe-inline'"], // inline styles (avoid if possible)
imgSrc: ["'self'", 'data:', 'https:'],
connectSrc: ["'self'", 'https://api.example.com'],
fontSrc: ["'self'", 'fonts.gstatic.com'],
frameSrc: ["'none'"],
objectSrc: ["'none'"],
upgradeInsecureRequests: [],
},
},
}))Report-only mode for tuning CSP
app.use(helmet({
contentSecurityPolicy: {
useDefaults: true,
reportOnly: true, // logs violations instead of blocking them
directives: {
reportUri: '/csp-report',
},
},
}))
// Receive reports:
app.post('/csp-report', express.json({ type: 'application/csp-report' }), (req, res) => {
console.warn('CSP violation:', req.body)
res.status(204).end()
})HSTS — Strict-Transport-Security
app.use(helmet({
strictTransportSecurity: {
maxAge: 31_536_000, // 1 year in seconds
includeSubDomains: true,
preload: true, // submit to browser preload lists
},
}))Disabling or configuring individual middleware
// Disable one: pass false for that key:
app.use(helmet({
frameguard: false, // if you legitimately need iframes
}))
// Configure one:
app.use(helmet({
referrerPolicy: { policy: 'same-origin' },
xFrameOptions: { action: 'sameorigin' }, // allow framing by same origin
}))Verifying your headers
Use securityheaders.com to grade your live site's headers.
Run
curl -I https://yourapp.comto inspect headers from the CLI.browser DevTools → Network → response headers on any request.
In CI: add a test that asserts key headers are present on responses.