The HTTP Strict Transport Security (HSTS) is designed to mitigate man-in-the-middle attacks by forcing browsers to use HTTPS connections when users visit your websites. HSTS policies can be either set dynamically or preloaded in browsers. To set HSTS dynamically, send a HTTP response header “
Strict-Transport-Security: max-age=31536000; [includeSubDomains]”, meaning that in the next 31536000 seconds (1 year), browsers must use HTTPS when connect to this domain. If the optional directive
includeSubDomains is set, all its subdomains are forced to use HTTPS too.
The problem with dynamic HSTS policy is that the initial connection to the server is not protected. To fix this problem, Google maintains a HSTS preload list. Developers can submit their domains to the preload list at hstspreload.org. This list is hardcoded in the binary files of all major browsers.
Although all browsers’ lists are based on Chrome’s, the latest stable version of different browsers have different hardcoded preload list, because of varied release cycles, and extra requirements. Firefox and Chrome are open sourced, so we can easily know their preload list from the source code. Latest Firefox preload list is available from mozilla#gecko-dev, and Chrome preload list is available from chromium#chromium. Edge is not open sourced, and so far I didn’t find anyone posting the Edge’s list online, so, for curiosity, I decided to find it out myself.
It’s worth mentioning that a limitation of this method is that it only tests the domains listed in Chrome’s preload list, but since all browsers use the same list, so it won’t be too inaccurate. The idea of is that we go through each domain in the Chrome’s list. For each of them, we load it in Edge. If Edge automatically rewrites HTTP to HTTPS, then this domain is preloaded in Edge too. We can detect it in this way: for example, to check
example.com, we construct an
img element with
onload handler is invoked. If Fiddler sees a CONNECT request, this means the URL has been rewritten to HTTPS. In this case, Fiddler resets the CONNECT request, making Edge fire the
onerror handler. Then we only need to handle the
onload is fired, it’s not preloaded; if
onerror is fired, it is preloaded.
I have posted the full code I used on GitHub. It’s available at https://github.com/xiaoyinl/EdgeHSTS . If you want to try it out in your browsers, make sure to set up a proxy with rules detailed in the previous paragraph, and delete browsing history to remove dynamic HSTS entries. If you use Fiddler, just add the following three rules in AutoResponder:
Then open http://hsts.local/hststest.html in browsers you want to test. It will take a while for the test to complete.
The reference list I used is transport_security_state_static.json at commit dee803ed.
Here are the results:
- Total number of HSTS entries in
- Edge on Windows 10 Build 16299.371 with patches up to April 2018: 14843 (+636 without subdomains)
- Firefox 59.0: 33666 (+1008 without subdomains)
- Chrome 66.0.3359.117: 45447 (+0 without subdomains)
- Opera 52.0: 43611 (+0 without subdomains)
A domain is in the “without subdomains” category if its
include_subdomains property is set to
transport_security_state_static.json, but the browser doesn’t preload its subdomains.
Note that we only count the domains that are in the current reference list. There are many domains that have been removed from the master list, but not yet removed from these browsers. So the actual number of preloaded domains in each browser should be slightly higher than the above result.
I think the reason why Firefox’s list is shorter than Chrome is that Mozilla regularly checks if domains still comply with the inclusion policy. Those which no longer send
Strict-Transport-Security or the
max-age is shorter than 18 weeks are automatically removed. Mozilla documents this policy at SecurityEngineering/HTTP Strict Transport Security (HSTS) Preload List.
I find it quite surprising that Edge’s HSTS preload list is much shorter than other browsers. The Edge documentation does say that “like other browsers which have implemented this feature, the Microsoft Edge preload list is based on the Chromium HSTS preload list”. But Microsoft didn’t mention how often it’s updated or if Microsoft has extra requirements. Hopefully Microsoft will document their HSTS policies with more details in the future.