Skip to content

Add HSTS preload list check via hstspreload.org API (--phone-out)#3060

Open
potato-20 wants to merge 2 commits into
testssl:3.3devfrom
potato-20:revive-hsts-preload
Open

Add HSTS preload list check via hstspreload.org API (--phone-out)#3060
potato-20 wants to merge 2 commits into
testssl:3.3devfrom
potato-20:revive-hsts-preload

Conversation

@potato-20

Copy link
Copy Markdown
Contributor

Describe your changes

Adds an HSTS preload list status check. When --phone-out is supplied, run_hsts() queries the hstspreload.org status API (/api/v2/status) for the tested host and reports whether the domain is preloaded / pending / rejected / unknown, combining that with the served-header state (marked-for-preload, same-domain, bulk) to produce an appropriate severity (OK / INFO / LOW / MEDIUM, or WARN if the API is unreachable).

Fixes #1248
Supersedes #1809 — this revives @tosticated's (Jim Blankendaal) original work, rebased onto current 3.3dev. Since that PR is a draft on his fork it can't be pushed to, hence a fresh PR; credit is retained in CREDITS.md.

What is your pull request about?

  • New feature (adds functionality)

If it's a code change please check the boxes which are applicable

  • For the main program: my edits contain no tabs, indentation is five spaces and line endings contain no blank chars
  • I've read CONTRIBUTING.md and Coding_Convention.md
  • I have tested this new feature against hosts that show it and hosts that don't
  • I made corresponding changes to the documentation and to help()
  • I added the contributor to CREDITS.md and the change to CHANGELOG.md

Notes

  • Addresses the review comments on HSTS preload list check against API #1809: the API-response matching is now pure bash ([[ ... == *...* ]], no grep fork), the JSON quoting is handled inside check_hsts_preloadlist_match() so callers pass plain values, and the value arrays use local -a. The output decision table is kept as-is (per your feedback on HSTS preload list check against API #1809).
  • Only known status/bulk values are matched against the API response, so no untrusted API input is reflected back to the user.
  • Unit test added: t/53_hsts_preload.t (github.com listed → preloaded, example.com not → unknown), modeled on t/52_ocsp_revoked.t, core Test::More only.
  • The rendered man pages doc/testssl.1 and doc/testssl.1.html are not regenerated here (needs pandoc) — only the doc/testssl.1.md source is updated. Could you regenerate them with make -C doc?

Credit for the original implementation and the decision table goes to @tosticated.

@drwetter

Copy link
Copy Markdown
Collaborator

hi @potato-20 ,

first: thanks for reviving this! And awesome you amended that with a unit test.

Quick shot:

  • yes, can run pandoc later. There are some glitches anyway, as I have to do that manually ---either on MacOS or Linux (and I always forgot which is the right one) as otherwise there will be a huge diff. That should be automated by github preferably *) . For a line though I often end up manually edit the HTML and roff file.
  • UI: One thing which is incomprehensible to the user is "unknown" which comes directly from the API . Off the top of my head don't know what the right wording could be. Maybe if we change HSTS preload list to HSTS preload API we could use something like no entry (=unknown) or just no entry.

More later.

*) there was a discussion here but atm I cannot find it.

@drwetter

Copy link
Copy Markdown
Collaborator

PS: if you rebase, the .1 and .html file will be autogenerated

Revives and rebases testssl#1809 by @tosticated (Jim Blankendaal) onto 3.3dev. When --phone-out is set, run_hsts now queries https://hstspreload.org/api/v2/status and reports whether the domain is on the browser HSTS preload list (preloaded/pending/rejected/unknown), cross-referenced with the served header, the same-domain check and the bulk flag.

Addresses the review comments on testssl#1809: the API-response matching uses native bash string matching instead of forking grep, the JSON quoting is handled inside check_hsts_preloadlist_match() so callers pass plain values, and the value arrays use 'local -a'. The output decision table is kept as-is (per maintainer feedback). Adds t/53_hsts_preload.t. Original design and decision table by @tosticated.
@potato-20 potato-20 force-pushed the revive-hsts-preload branch from 6e70d06 to 391f6a6 Compare June 17, 2026 09:44
@potato-20

Copy link
Copy Markdown
Contributor Author

Fixed — replaced "unknown" with "no entry" (your suggestion), keeping the section header as HSTS preload list since the rename wasn't strictly needed to fix the comprehension issue. Also rebased onto current 3.3dev; the man pages will auto-generate via #3064. Unit test updated to match.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

HSTS Browser Preloading Check ( Like SSL Labs )

2 participants