Skip to main content

HSTS.

Security Headers & TLS Config

Forces HTTPS-only connections — prevents protocol downgrade attacks

What does this check test?

HTTP Strict Transport Security (HSTS) is a response header (`Strict-Transport-Security`) that instructs browsers to only communicate with your site over HTTPS for a specified duration. Once a browser sees this header, it will automatically convert any HTTP request to HTTPS before it ever leaves the client. The header accepts a `max-age` directive (in seconds), an optional `includeSubDomains` directive, and an optional `preload` directive for inclusion in browser preload lists.

Why does it matter?

Without HSTS, users who type your domain without `https://` or follow an HTTP link are vulnerable to SSL stripping attacks, where an attacker on the same network intercepts the initial plaintext request and proxies the connection. HSTS eliminates this window of vulnerability after the first visit. For maximum protection, sites should be submitted to the HSTS preload list, which hardcodes HTTPS enforcement into browsers so even the very first visit is protected.

Who is affected?

HSTS is critical for any site that handles user authentication, personal data, or financial transactions. It is equally important for marketing sites that set cookies or embed third-party scripts, since session cookies sent over HTTP can be intercepted. Every production website should set HSTS — there is no legitimate reason to allow HTTP connections to a site that supports HTTPS.

Where does this apply?

The `Strict-Transport-Security` header must be set on HTTPS responses from your server or CDN. It is typically configured at the web server level (Nginx, Apache, Caddy), in your CDN dashboard (Cloudflare, AWS CloudFront), or via middleware in your application framework. The header is ignored by browsers when served over HTTP, so your site must already support HTTPS for it to take effect.

How to fix it

Add the header to your server configuration.

Nginx

nginx
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;

Node.js / Express

js
const helmet = require('helmet');
app.use(helmet.hsts({ maxAge: 63072000, includeSubDomains: true, preload: true }));

Django

python
SECURE_HSTS_SECONDS = 63072000
SECURE_HSTS_INCLUDE_SUBDOMAINS = True
SECURE_HSTS_PRELOAD = True

Flask

python
from flask_talisman import Talisman
Talisman(app, strict_transport_security=True,
         strict_transport_security_max_age=63072000,
         strict_transport_security_include_subdomains=True,
         strict_transport_security_preload=True)

Next.js

js
module.exports = {
  async headers() {
    return [{
      source: '/(.*)',
      headers: [{
        key: 'Strict-Transport-Security',
        value: 'max-age=63072000; includeSubDomains; preload'
      }]
    }];
  }
};

Spring Boot

java
server.servlet.session.cookie.secure=true
// In a WebSecurityConfigurerAdapter or SecurityFilterChain:
http.headers().httpStrictTransportSecurity()
    .includeSubDomains(true)
    .maxAgeInSeconds(63072000)
    .preload(true);
Start with a short `max-age` (e.g., 300 seconds) to test, then increase to at least 1 year (31536000) before submitting to the preload list at hstspreload.org. Verify the header is present using `curl -sI https://yoursite.com | grep -i strict`.

References

AppVet checks HSTS automatically

Run a free security scan and get a full report with actionable fixes, including a Fix with AI prompt you can paste into any coding tool.

Run Audit