HTTP Strict Transport Security (HSTS) Middleware
The `hsts` package provides HTTP Strict Transport Security (HSTS) middleware for Node.js applications, primarily for use with Express or Connect. It adds the `Strict-Transport-Security` header to HTTP responses, instructing browsers to interact with the site exclusively over HTTPS for a specified duration. Key features include configurable `maxAge` (in seconds), `includeSubDomains`, and `preload` directives for HSTS preloading services. This package is part of the Helmet.js suite, a collection of security middleware. The current stable version is 2.2.0, which has been stable for some time, indicating a mature, maintenance-oriented release cadence rather than frequent updates unless security vulnerabilities or major breaking changes in web standards require it. Its primary differentiator is its simplicity and integration within the widely adopted Helmet.js ecosystem, ensuring robust and standard-compliant HSTS implementation.
Common errors
-
Strict-Transport-Security header not appearing on my site.
cause The HSTS header is only sent and processed by browsers when the connection is secure (HTTPS). If you're testing on HTTP, the browser will ignore it.fixEnsure your application is served over HTTPS. Use a tool like `ngrok` or a local proxy for development, or deploy to an environment with SSL/TLS enabled for testing. -
HSTS maxAge seems too short or incorrect.
cause The `maxAge` value must be specified in seconds. Incorrect conversion from days/weeks/years to seconds is a common mistake.fixDouble-check your `maxAge` calculation. For example, 180 days is 180 * 24 * 60 * 60 = 15,552,000 seconds. A common long-term value is 31,536,000 for one year. -
Cannot submit my site to hstspreload.org.
cause HSTS preload services have strict requirements for the header, including a minimum `maxAge` and the presence of `includeSubDomains` and `preload` directives.fixEnsure your HSTS middleware is configured with `maxAge: 31536000` (at least 1 year), `includeSubDomains: true`, and `preload: true`. Verify the header is correctly served via HTTPS.
Warnings
- breaking The `maxAge` option in `hsts` middleware now requires the value to be specified in seconds. In previous versions, different units might have been accepted.
- gotcha The `Strict-Transport-Security` header is ignored by browsers when served over insecure HTTP connections (e.g., `http://`). It will only be processed if the initial request is HTTPS.
- gotcha To be eligible for HSTS preloading services (e.g., `hstspreload.org`), specific criteria must be met, including `maxAge` being at least one year (31536000 seconds) and `includeSubDomains` being enabled.
- gotcha HSTS only tells browsers to *stick* to HTTPS after an initial secure connection. It does not enforce a switch from HTTP to HTTPS for initial unsecure requests. Browsers will simply ignore the header on HTTP.
Install
-
npm install hsts -
yarn add hsts -
pnpm add hsts
Imports
- hsts
const hsts = require('hsts')import hsts from 'hsts'
- hstsMiddleware
import hsts from 'hsts'; const hstsMiddleware = hsts({...});
Quickstart
import express from 'express';
import hsts from 'hsts';
const app = express();
const port = process.env.PORT || 3000;
// Basic HSTS configuration for 180 days, including subdomains
app.use(hsts({
maxAge: 15552000, // 180 days in seconds
includeSubDomains: true
}));
// Advanced configuration with preload for HSTS preloading services
// Requires maxAge to be at least 1 year (31536000 seconds) and includeSubDomains to be true.
const preloadHstsMiddleware = hsts({
maxAge: 31536000, // 1 year
includeSubDomains: true,
preload: true
});
// Conditionally apply HSTS middleware only on secure requests
app.use((req, res, next) => {
if (req.secure) {
preloadHstsMiddleware(req, res, next);
} else {
next();
}
});
app.get('/', (req, res) => {
res.send('Hello HSTS World!');
});
app.listen(port, () => {
console.log(`Server listening on port ${port}. Ensure you access via HTTPS to see HSTS headers.`);
});