Helmet: Security Headers
Objectives
By the end of this lesson, you should be able to:
- Install and register Helmet to set security-related response headers
- Identify what several of Helmet’s default headers protect against
- Explain why these headers matter even for a simple application
💡 Why this matters: Express, by default, doesn’t set most security-related HTTP headers, leaving an application more exposed than necessary to a handful of well-known attack classes. Helmet fixes this with a single line.
⚠️ A note on verification: every snippet and every response shown below was actually run and tested with real HTTP requests, using Helmet 8.
Before and After Helmet
Without Helmet (Module 5’s minimal server), a response has no security-specific headers at all beyond the default X-Powered-By: Express. With Helmet:
const express = require('express');
const helmet = require('helmet');
const app = express();
app.use(helmet());
app.get('/', (req, res) => {
res.send('Homepage');
});
app.listen(4207);
curl -i http://localhost:4207/
HTTP/1.1 200 OK
Content-Security-Policy: default-src 'self';base-uri 'self';...
Cross-Origin-Opener-Policy: same-origin
Referrer-Policy: no-referrer
Strict-Transport-Security: max-age=31536000; includeSubDomains
X-Content-Type-Options: nosniff
X-DNS-Prefetch-Control: off
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 0
helmet() returns a single middleware function that sets over a dozen security-related headers at once, this is the exact same middleware pattern from Lesson 1, just bundled behavior instead of one specific job.
What a Few of These Headers Do
X-Content-Type-Options: nosniff stops a browser from guessing a response’s content type differently than declared, preventing certain attacks that rely on that guessing. X-Frame-Options: SAMEORIGIN prevents the page from being embedded in an <iframe> on another site, protecting against “clickjacking,” where a hidden iframe tricks a user into clicking something unintended. Strict-Transport-Security tells the browser to only ever connect over HTTPS in the future, once it’s seen this header, protecting against a downgrade to unencrypted HTTP. Content-Security-Policy restricts what sources scripts, styles, and other resources can load from, a strong defense against injecting malicious scripts (Module 6’s XSS mention from Lesson 2, EJS’s escaping).
Why This Matters Even for a Small App
None of these attacks require an application to be large or well-known, a small internal tool is just as exposed to clickjacking or content-type sniffing as a major site, if it doesn’t set these headers. app.use(helmet()), added once, near the top of an application’s middleware stack, is a low-cost way to close off an entire category of well-understood vulnerabilities.
Try It
- Install Helmet, register it, and use
curl -ito compare a response’s headers before and after adding it. - Look up (in Helmet’s documentation, or by inspecting the response) what
X-DNS-Prefetch-Controldoes, and explain it in your own words. - Register Helmet alongside Morgan (Lesson 4) and a custom middleware (Lesson 3) on the same app, and confirm all three work together without conflict.
- Explain, in your own words, what clickjacking is, and which Helmet-set header defends against it.
Recap
helmet()is a single middleware function setting over a dozen security-related HTTP headers at once.- These headers defend against real, well-understood attack classes: clickjacking, content-type sniffing, protocol downgrade attacks, and more.
- Adding
app.use(helmet())is a low-cost, high-value addition appropriate for essentially any Express application, regardless of size.
Next lesson: CORS, controlling which origins can call your API.