Blog

Web Security articles

HSTS Explained: Forcing HTTPS the Right Way

HSTS explained: how the Strict-Transport-Security header blocks downgrade attacks, safe rollout steps, preload list risks and how to undo mistakes.

4 min read Web Security

Redirecting HTTP to HTTPS is a good start, but it leaves a small gap: the very first request still goes out unencrypted, and an attacker on the same network can intercept it before the redirect happens. HSTS, short for HTTP Strict Transport Security, closes that gap. It is a single response header that tells browsers to use HTTPS for your domain automatically, every time, without ever trying plain HTTP. It is defined in RFC 6797.

The problem HSTS solves

Picture a visitor on café Wi-Fi typing example.com into their browser. Without HSTS, this happens:

  1. The browser sends http://example.com in plain text.
  2. Your server replies with a 301 redirect to https://example.com.
  3. The browser connects securely.

Step 1 is exposed. An attacker controlling the network can intercept it and keep the visitor on an HTTP version of the site, quietly proxying traffic and reading everything, including login forms. This is called an SSL stripping or downgrade attack. The visitor sees no certificate warning because no certificate was ever involved.

With HSTS, once the browser has seen the header from your site, it rewrites any http:// request for your domain to https:// internally before anything leaves the device. Step 1 never happens.

How the HSTS header works

Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
  • max-age (required): how many seconds the browser should remember to use HTTPS only. 31,536,000 is one year. Each new response refreshes the timer.
  • includeSubDomains (optional): applies the rule to every subdomain as well, such as shop.example.com and mail.example.com.
  • preload (optional): signals consent to be added to browsers' built-in preload list, covered below.

Browsers only honour the header when it arrives over a valid HTTPS connection. An HSTS header sent over plain HTTP is ignored, which prevents an attacker from injecting one.

HSTS also changes how certificate errors behave. On an HSTS domain, the browser removes the "proceed anyway" option from certificate warnings. That is good for security but means an expired certificate becomes a hard outage, so pair HSTS with reliable renewal.

Rolling out HSTS safely

The risk with HSTS is not the header itself but committing to HTTPS before you are ready. Once a browser caches the policy, you cannot take it back for that visitor until max-age runs out. Roll out in stages:

  1. Audit first. Make sure the main site, every subdomain you care about, and any embedded resources work over HTTPS with valid certificates. Check certificates with an SSL checker and list your subdomains with a DNS lookup or your DNS provider's zone file.
  2. Start short. Send max-age=300 (five minutes) without includeSubDomains. If something breaks, the policy expires almost immediately.
  3. Increase gradually. Move to a week (604800), then a month (2592000), watching for problems.
  4. Add includeSubDomains once you are confident no subdomain needs HTTP. Old intranet hosts, printers, or a forgotten staging server under your domain are the usual surprises.
  5. Settle on a long max-age, typically one or two years.

Server configuration

Nginx, inside the HTTPS server block:

add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

Apache, with mod_headers enabled, inside the <VirtualHost *:443> block:

Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"

On IIS 10 version 1709 and later, HSTS can be enabled per site in the configuration; on older versions add it as a custom response header. Keep your HTTP-to-HTTPS 301 redirect in place too. HSTS protects returning visitors; the redirect still handles first-time ones and non-browser clients.

Confirm the header is live with our HTTP header checker or curl -sI https://example.com | grep -i strict.

The HSTS preload list

Ordinary HSTS has a "trust on first use" weakness: a visitor's very first visit, before the browser has seen the header, is still unprotected. The preload list fixes this. It is a list of domains built into Chrome, Firefox, Safari and Edge that are treated as HTTPS-only from the moment the browser is installed. You submit your domain at hstspreload.org, which is run by the Chromium project.

Requirements include a valid certificate, redirecting HTTP to HTTPS on the same host, serving all subdomains over HTTPS, and sending a header on the base domain with max-age of at least one year, includeSubDomains and preload.

Think carefully before preloading. Removal is possible but slow, because it depends on browser release cycles and users updating, so it can take months to take effect. Preloading commits your entire domain and every future subdomain to HTTPS. For many small businesses a long max-age without preload is a perfectly reasonable stopping point.

Undoing HSTS

If you need to back out, serve the header with max-age=0 over HTTPS. Each browser clears the policy the next time it visits. Visitors who do not return will keep the old policy until it expires naturally. For local testing, Chrome lets you inspect and delete a domain's policy at chrome://net-internals/#hsts.

Key takeaways

  • HSTS makes browsers use HTTPS automatically, removing the unencrypted first request that downgrade attacks exploit.
  • Roll out with a short max-age, then increase it; add includeSubDomains only after checking every subdomain.
  • HSTS turns certificate problems into hard failures, so keep renewal automated.
  • Preloading gives first-visit protection but is slow to reverse; treat it as a long-term commitment.

Need help with this?

Netifi helps businesses around the world with Web Security. Tell us what you are working on.