Serve everything over HTTPS
301 http to https, load nothing over http, send HSTS.
Helmethelmetjs.github.io
helmet.js
From security-best-practices (HTTPS only) and seo-audit, HTTPS.
Follow the request
Press Visit twice, then try a subdomain.
Serves http as isBad
0 requests
301 + HSTSGood
0 requests
app.set("trust proxy", 1); // so req.secure reads X-Forwarded-Proto
app.use(helmet({
hsts: { maxAge: 31536000, includeSubDomains: true, preload: true },
}));
app.use((req, res, next) => {
if (process.env.NODE_ENV === "production" && !req.secure) {
return res.redirect(301, `https://${req.headers.host}${req.url}`);
}
next();
});
Find the mixed content
Press Pay, then switch each resource to https.
shop.example.comMixed
Image failed
Trail runner$48.00
Console
<img src="https://cdn.example.com/shoe.jpg" alt="Trail runner">
<script src="https://cdn.example.com/pay.js" defer></script>
<form action="/pay" method="post">…</form>
# Safety net, not a fix:
Content-Security-Policy: upgrade-insecure-requests
Build the HSTS header
Lower max-age or untick a directive.
HSTS headerPreload-ready
- max-age at least 31536000
- includeSubDomains
- preload
Why it matters, pros and cons
Why it matters
Anything over http can be read and rewritten. HSTS removes the last plain hop.
Pros
- Cookies and payment data travel encrypted.
- Old http links never leave in plaintext.
- Unlocks HTTP/2 and secure-context APIs.
Cons
- HSTS on localhost pins your dev server to https.
- Preload is slow to undo; every subdomain needs https.
- Start with a short max-age, then raise it.