Check specification

hsts 1.0.0

HSTS header

Validates Strict-Transport-Security on HTTPS responses, including syntax, max-age strength, subdomain scope, and preload opt-in requirements.

Assessment Suite
2026.06.10
Maturity
Established
Category
Security & Trust
Subcategory
Browser Trust

1. Abstract

Require HTTPS for repeat browser visits with a valid Strict-Transport-Security policy.

HSTS tells browsers to keep using HTTPS after the first secure visit, reducing downgrade, SSL-stripping, and mixed-transport risk for repeat users.

2. Classification

Check ID
hsts
Check version
1.0.0
Package path
lib/checks/hsts/versions/1.0.0
Category
Security & Trust
Subcategory
Security & Trust
Check group
Browser Trust
Check group ID
browser-trust
Maturity
Established
Scope
site
Check weight
1

3. Input And Output Contracts

Resources inspected
Strict-Transport-Security, max-age, includeSubDomains, preload

4. Scoring Semantics

Step IDTitleWeightDescription
applicabilityValidate HSTS applicability0.1Confirm the final URL is an HTTPS DNS hostname where HSTS can protect browser traffic.
header-presenceFind Strict-Transport-Security0.2Check the relevant HTTPS response for a Strict-Transport-Security header.
syntaxParse HSTS directives0.2Parse RFC 6797-style directives, duplicate directive names, malformed values, and unknown extension directives.
max-ageValidate max-age0.2Validate required max-age, explicit removal, deployment minimum, and one-year strength.
subdomainsReview subdomain scope0.1Record includeSubDomains and the operational scope of subdomain enforcement.
preloadReview preload opt-in0.1When preload is present, validate header-level preload requirements without requiring preload for ordinary HSTS.
http-transportReview HTTP transport0.1Fail plain HTTP final URLs and record that STS sent over HTTP is not effective.

5. Package Documentation

HSTS Header Check v1.0.0

Status

Abstract

This check validates the Strict-Transport-Security response header on the scanned page. It checks whether the final URL is eligible for HSTS, whether the header is present on HTTPS, whether the directives are parseable, whether max-age is strong enough for this assessment, and whether optional includeSubDomains and preload signals are used safely.

Plain HTTP final URLs fail this check because browsers ignore HSTS received over insecure HTTP.

Motivation

HSTS reduces downgrade and SSL-stripping risk for repeat browser visits. After a browser observes a valid HSTS policy over HTTPS, future HTTP requests to that host are upgraded to HTTPS before loading, and certificate errors become non-bypassable for that known HSTS host.

HSTS is effective only when the policy is delivered over a secure HTTPS connection. Sending Strict-Transport-Security on HTTP does not protect users.

Normative Model

RFC 6797 defines HTTP Strict Transport Security.

The Strict-Transport-Security header uses semicolon-separated directives. The required directive is max-age, a non-negative integer number of seconds. Directive names are case-insensitive and directive order is not significant.

Important RFC behavior:

  • browsers process HSTS only when received over secure transport
  • max-age=0 removes the HSTS policy
  • includeSubDomains extends the policy to subdomains
  • directives must not appear more than once in one header field
  • servers should emit only one Strict-Transport-Security header field; when a

runtime folds multiple observed fields into one comma-separated value, this check evaluates the first field value and warns about the duplicate emission

  • unknown directives are ignored when the rest of the header is valid
  • servers must not emit STS over insecure HTTP
  • IP literals are not noted as HSTS hosts

The preload directive is not part of RFC 6797. It is an ecosystem opt-in used by hstspreload.org.

Applicability

The check applies to the scanned final URL and expects a public HTTPS DNS hostname.

The check fails when the final URL is HTTP, non-HTTPS, localhost, private/internal, or an IP literal, because the scanned page is not delivering an effective public-site HSTS policy.

Pass Criteria

The check passes baseline HSTS validation when:

  • the final URL is HTTPS
  • the host is a DNS hostname
  • Strict-Transport-Security is present
  • the header is syntactically parseable
  • max-age appears exactly once
  • max-age is a non-negative integer
  • max-age is at least 15552000 seconds
  • no duplicate directives are present
  • no malformed directives or malformed directive values are present
  • includeSubDomains is present for the strongest baseline posture

If preload is present, the header-level preload requirements must also be satisfied: max-age of at least 31536000, includeSubDomains, and preload.

Warning Criteria

Warnings include:

  • multiple Strict-Transport-Security header fields appear to have been

observed; the first value is evaluated and duplicate emission is reported

  • HSTS is syntactically valid but max-age is below 15552000 seconds and above zero
  • HSTS is valid and strong enough, but includeSubDomains is absent
  • max-age is quoted but otherwise parseable
  • unknown extension directives are present
  • preload is present but header-level preload requirements are incomplete
  • preload is present and appears header-eligible, because domain-wide preload readiness still requires operational verification outside this single-response check

Failure Criteria

Failures include:

  • final URL is HTTP
  • final URL is not HTTPS
  • final URL is localhost, private/internal, or an IP literal
  • HTTPS public DNS hostname omits Strict-Transport-Security
  • header lacks max-age
  • max-age appears more than once
  • max-age is not an integer
  • max-age=0
  • directives are malformed enough that browsers must ignore the STS header
  • a directive appears more than once in one header field
  • Strict-Transport-Security is emitted on HTTP

Duplicate header fields are not treated the same as duplicate directives inside the first effective field value. The check evaluates the first observed STS field value for policy strength and reports the additional folded values as a warning so operators can remove duplicate emission at the application, proxy, or hosting layer.

Evidence Model

The check emits step-level evidence for:

  • final URL, scheme, hostname, and host classification
  • header presence
  • summarized header value
  • first effective header value when duplicate fields were folded together
  • duplicate folded header values, when observed
  • parsed directive names
  • duplicate directives
  • unknown directives
  • malformed directive summaries
  • parsed max-age seconds
  • whether max-age meets 15552000 and 31536000 thresholds
  • includeSubDomains presence
  • preload presence and header-level preload eligibility
  • whether the final URL was HTTP

Evidence must not include cookies, authorization headers, full response header dumps, request credentials, or unrelated sensitive values.

Validation/Scoring Steps

  • applicability (0.10): validate final URL scheme and host eligibility. HTTP final URLs fail.
  • header-presence (0.20): check for Strict-Transport-Security.
  • syntax (0.20): parse directives, duplicate names, malformed values, and unknown extension directives.
  • max-age (0.20): validate required max-age, max-age=0, deployment minimum, and one-year strength.
  • subdomains (0.10): evaluate includeSubDomains.
  • preload (0.10): if preload is present, validate header-level preload requirements and warn about unverifiable operational requirements.
  • http-transport (0.10): fail plain HTTP final URLs and record that STS over HTTP is ineffective.

Standard Behavior

If the final URL is HTTP, the result is fail.

If the final URL is HTTPS for a public DNS hostname and the HSTS header is missing or malformed, the result is fail.

If the header is RFC-valid but weaker than this check's deployment threshold, the result is warning.

If the header is RFC-valid, meets the deployment threshold, and includes includeSubDomains, the result passes baseline HSTS validation.

If preload is present, the check validates only header-level preload requirements. It does not claim the domain is actually preloaded.

Non-Standard And Real-World Behavior

Security scanners often grade HSTS more strictly than RFC 6797 by expecting long max-age values and includeSubDomains. This check separates protocol validity from production posture:

  • RFC-valid HSTS can use any non-negative max-age
  • max-age=0 is valid syntax but removes protection and fails this check
  • this check requires at least 15552000 seconds for a pass
  • 31536000 seconds is the header threshold for preload eligibility
  • preload is optional and should be used only after domain-wide readiness review

Hstspreload.org currently recommends HSTS but does not recommend preloading by default because removal can be slow and subdomain impact is broad.

Non-Goals And Limitations

This check does not:

  • prove TLS certificate validity beyond what the scan runtime already observed
  • prove the domain is on a browser preload list
  • crawl every subdomain to prove includeSubDomains safety
  • verify every hstspreload.org operational requirement
  • validate every application route
  • replace TLS configuration scanning such as protocol versions, cipher suites, OCSP, or certificate-chain auditing
  • require preload for ordinary HSTS
  • treat an STS header observed over HTTP as effective browser protection

References

Source: lib/checks/hsts/versions/1.0.0/docs.md

6. Version Changelog

hsts v1.0.0 Changelog

  • Validates Strict-Transport-Security directive syntax, required max-age, deployment-strength threshold, subdomain scope, and preload opt-in requirements.
  • Fails plain HTTP final URLs because browsers ignore HSTS outside secure transport.
  • Distinguishes ordinary HSTS from preload eligibility.
  • Evaluates the first folded duplicate Strict-Transport-Security header field and reports duplicate header emission as a warning instead of mis-parsing later folded values as directives.

Source: lib/checks/hsts/versions/1.0.0/changelog.md