Remediation Guide 11 min read

Fix Missing HSTS | Add Strict-Transport-Security Guide

When a security scanner reports missing HSTS, it means your server is not sending the Strict-Transport-Security response header. Without it, browsers have no way to remember that your site must be loaded over HTTPS — even if every request redirects from HTTP. An attacker on a shared network can intercept the very first HTTP request before the redirect fires, exposing session cookies and credentials. This guide explains what HSTS is, why "missing HSTS" appears as a finding, and exactly how to add the header to Nginx, Apache, or a CDN safely without creating rollback problems.

What This Means

The Strict-Transport-Security header tells browsers to refuse plain HTTP connections to your hostname for a set period. The key directive is max-age, measured in seconds. A common production value is 31536000 (one year), but starting with a lower value such as 300 seconds lets you verify the deployment without locking users in for long. The includeSubDomains directive extends the policy to every subdomain — powerful, but dangerous if you have forgotten hosts that are not yet on valid HTTPS. The preload directive signals intent to join browser vendor preload lists, which hard-codes HSTS enforcement before any first visit; this is permanent and slow to reverse, so it should be treated as a final milestone rather than a first step. Safe rollout order: confirm HTTPS is healthy on all relevant hosts, deploy with a low max-age, raise it once confidence is established, then evaluate includeSubDomains and preload as separate decisions.

QuestionWhat to verifyWhy it matters
Is HTTPS stable?Certificates, redirects, and edge behaviorHSTS amplifies existing HTTPS problems if rollout is premature.
Are subdomains ready?Mail, support, preview, or forgotten hostnamesincludeSubDomains can break hosts you forgot to inventory.
Is max-age appropriate?Temporary smoke-test versus strong production valueThe wrong value can weaken protection or make rollback painful.
Is preload warranted?Long-term operational readinessPreload is powerful but much slower to reverse.

Common Causes

Patterns worth checking first

  • No HTTPS rollout process: The site is on HTTPS, but no one finalized browser-side enforcement.
  • Subdomain uncertainty: Teams avoided HSTS because not every host was reviewed.
  • Fear of lock-in: Preload and includeSubDomains felt risky without a staged plan.

How To Confirm It Safely

Confirmation steps

  • Confirm the final HTTPS response is healthy and stable on the public hostname.
  • Check certificates and redirects on any subdomains that matter to the business.
  • Decide whether you are testing, hardening, or pursuing preload readiness.
  • Verify that the header is absent or weaker than intended on the live response.

Fix Workflow

  1. Validate HTTPS operations first. Check certificates, redirect behavior, and important subdomains before adding HSTS.
  2. Choose the rollout stage. Start with a lower max-age if the environment still needs proof, then raise it once stable.
  3. Add stronger scope carefully. Only add includeSubDomains or preload after the broader estate is reviewed.
  4. Retest the live response. Confirm the final HTTPS response now carries the intended HSTS policy.

Implementation Examples

Nginx HSTS header (HTTPS server block)
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
Apache HSTS header (VirtualHost on :443)
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"

Rollout Risks

HSTS will not fix an unhealthy HTTPS deployment

It assumes HTTPS is already reliable.

  • Repair certificate and redirect issues before promotion.
  • Do not use HSTS to paper over transport drift.
includeSubDomains is risky if inventory is incomplete

Forgotten hosts are the classic HSTS rollout surprise.

  • Inventory mail, support, preview, and legacy hosts.
  • Use a staged approach if the estate is still messy.

Validation Checklist

Post-fix validation

  • The final HTTPS response includes the intended HSTS header.
  • Important subdomains remain healthy if includeSubDomains was used.
  • Certificates and redirects stay stable after rollout.
  • The HSTS Checker confirms the expected policy strength.

FAQ

What is HSTS and why is it missing?

HSTS is a browser security policy delivered via the Strict-Transport-Security response header. It is missing when your server never sends that header on HTTPS responses.

  • Without HSTS, browsers re-check HTTP on every visit before following a redirect.
  • An attacker on the same network can intercept the initial HTTP request before it redirects.
  • Adding the header instructs browsers to skip HTTP entirely for the duration of max-age.
How do I add HSTS to Nginx?

Add the header inside your HTTPS server block in the Nginx configuration.

  • In your ssl server block: add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
  • Run nginx -t to validate the config, then reload: systemctl reload nginx
  • Start with max-age=300 in staging to confirm no breakage before raising it in production.
What is the recommended HSTS max-age value?

The OWASP recommendation for production is at least one year (31536000 seconds), but the safest rollout starts lower.

  • Use max-age=300 for initial smoke-testing — locks browsers in for only 5 minutes.
  • Raise to max-age=86400 (one day) once HTTPS is confirmed stable across all entry points.
  • Promote to max-age=31536000 for full production hardening and preload eligibility.
What is HSTS preloading and should I use it?

Preloading submits your domain to browser vendor lists so HTTPS is enforced even before the first visit. It is powerful but effectively irreversible on short timescales.

  • Requirements: max-age of at least 31536000, includeSubDomains, and the preload directive.
  • Removal from preload lists takes months and cannot be sped up — plan accordingly.
  • Treat preload as a final milestone, not a starting point.
How do I add HSTS to Apache?

Enable mod_headers and set Strict-Transport-Security on your HTTPS VirtualHost.

  • Ensure mod_headers is enabled: a2enmod headers && systemctl reload apache2
  • Inside the SSL VirtualHost: Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
  • Start with max-age=300 in staging, then raise once HTTPS redirects and certificates are stable on all hosts.
How do I enable HSTS on Cloudflare or a CDN?

Most CDNs terminate TLS at the edge — HSTS must be set on the response users receive from the CDN, not only the origin.

  • Cloudflare: SSL/TLS → Edge Certificates → enable HTTP Strict Transport Security (HSTS) with a staged max-age.
  • Other CDNs: add the header in the CDN response-header policy or edge rule that applies to HTTPS responses.
  • Confirm the origin is not stripping or overriding the header after the CDN adds it.
How do I test whether my HSTS fix worked?

Always verify the live public hostname — not just origin config files — after publishing HSTS.

  • Run the Vulnify HSTS Checker against your production URL to confirm max-age, includeSubDomains, and preload directives.
  • Inspect the final HTTPS response in browser DevTools → Network → Response Headers.
  • Retest after CDN or load-balancer changes — edge layers often override origin headers.