HTTPS enforcement prevents plaintext connections, but HSTS goes further: it instructs the browser to refuse HTTP for your domain entirely for up to a year after the first visit, eliminating SSL-stripping attacks that can silently downgrade an HTTPS connection before the browser even sees it. Without a max-age of at least 31536000, an attacker who intercepts the first request can strip the redirect and operate in plaintext for every subsequent session. RFC 6797 defines the spec; OWASP A02 identifies the absence of HSTS as a cryptographic failure that enables credential theft.
High because a missing or short-lived HSTS header leaves the window open for SSL-stripping attacks that HTTPS redirects alone cannot prevent.
Configure the Strict-Transport-Security header with a full-year max-age in your framework config or middleware. A short max-age is nearly as dangerous as no HSTS — browsers forget the policy quickly.
// next.config.js
headers: [{
key: 'Strict-Transport-Security',
value: 'max-age=31536000; includeSubDomains'
}]
Verify the header is live with curl -I https://yoursite.com | grep Strict-Transport after deployment. Do not configure this only in development environments — production config is what matters.
ID: security-headers.transport.hsts-enabled
Severity: high
What to look for: Count every location where Strict-Transport-Security could be configured: framework config (next.config.* headers), middleware, deployment config (vercel.json, netlify.toml), and security middleware (helmet). Verify the max-age is at least 31536000 (1 year).
Pass criteria: HSTS header is configured with max-age of at least 31536000 seconds (1 year). includeSubDomains is recommended but not required for pass.
Fail criteria: No HSTS configuration found, or max-age is less than 31536000.
Skip (N/A) when: Never — every HTTPS site should have HSTS.
Do NOT pass when: HSTS is only configured in development/local config (e.g., next.config.dev.js or behind if (process.env.NODE_ENV === 'development')) but not in production config. Also do NOT pass when max-age is 0, which effectively disables HSTS.
Report even on pass: Report the configured max-age value and whether includeSubDomains is present: "HSTS configured with max-age=31536000, includeSubDomains present."
Note: This check fails even if https-enforced passes via platform default — HSTS must be explicitly configured with the correct max-age. https-enforced verifies transport-level HTTPS; this check verifies browser-side enforcement via the HSTS header.
Cross-reference: For HTTPS enforcement in deployment config, the Performance & Load audit covers server configuration and TLS setup.
Detail on fail: "No Strict-Transport-Security header configured in next.config.js, middleware, or deployment config" or "HSTS max-age is 3600 (1 hour) — should be at least 31536000 (1 year)"
Remediation: HSTS tells browsers to always use HTTPS for your site, even if the user types http://. Without it, the first visit to your site could be intercepted. Add the header:
// next.config.js
headers: [{
key: 'Strict-Transport-Security',
value: 'max-age=31536000; includeSubDomains'
}]
After deploying, verify with: curl -I https://yoursite.com and confirm the header appears.