HSTS Priming

A Collection of Interesting Ideas,

This version:
Richard Barnes (Mozilla)
(Google Inc.)


This document proposes modifications to Strict Transport Security’s behavior in order to mitigate the risk that mixed content blocking will prevent migrations from HTTP to HTTPS.

Table of Contents

1. Introduction

This section is not normative.

Migrating sites onto HTTPS is difficult. It has been our common understanding that these difficulties were wrapped up in server configuration, performance, and certificate maintenance. It’s recently become clear that the true challenges lie elsewhere. In particular, opting into secure transport comes with a number of restrictions which ensure that "secure" really means something. Mixed Content in particular can block an upgrade entirely. Brad Hill has laid out an excellent explanation of the challenges that mixed content blocking presents, and pointed out a number of situations in which cross-dependencies between insecure Origin A and Origin B might cause real deadlock where no one is able to upgrade without breakage. His "Why isn’t HTTPS everywhere yet?" document [TRANSITIONAL] explains the situation quite well, and proposes one approach to solving the problem. This document proposes another, which is smaller but simpler.

Today, the mechanism outlined in [UPGRADE-INSECURE-REQUESTS] allows a site to make assertions on behalf of the resources it loads that they ought to be requested over secure transport. If we provide a similar mechanism to those resources' owners, then that new mechanism could be used to break deadlocks by allowing Origin B to upgrade to HTTPS, and assert that requests from Origin A should be upgraded rather than blocked as mixed content. [RFC6797] introduced the Strict-Transport-Security header, which looks like it could be that mechanism.

HSTS, however, is currently checked after mixed content blocking has already happened. This is due to the fundamental property that HSTS takes effect only after a user’s agent has requested a resource from a host that sends the header. The effect is therefore determined by the vagaries of a particular user’s browsing history. If she visits Origin B before Origin A, then Origin A’s resources could be upgraded without issue. If she visits Origin A first, then those resources won’t be upgraded, and the site will break in some interesting way.

Origin A’s developer, of course, is overwhelmingly likely to have visited Origin B, given the dependencies. This means that they are both extremely unlikely to experience the failure, and extremely likely to fall into the "Works on my machine!" trap when dealing with user’s bug reports. Users would be sad, developers would be confused, and the world would collapse into an unfortunately indeterminate pile of partially broken sites.

It doesn’t have to be this way, however. This document proposes updates to [FETCH], [MIXED-CONTENT], and [RFC6797] which introduce the concept of an HSTS priming request. This request will attempt to validate an insecure resource’s host’s HSTS policy before blocking it as mixed content, therefore allowing any relevant upgrade from HTTP to HTTPS to be made in a deterministic way for all users.

This is not a recommendation-track document, it simply intends to explain the notion of HSTS priming, and gather up relevant changes in a single place for discussion. The normative changes will happen in the relevant documents.

1.1. Example

Origin A contains the following HTML:

<script src="http://origin-b/widget.js"></script>

Before blocking this insecure request as mixed content, the user agent performs an HSTS priming request to the root of the resource’s host, as follows:

Host: origin-b

Origin B sends back a response which triggers HSTS for the host:

HTTP/1.1 200 OK
Strict-Transport-Security: max-age=10886400; includeSubDomains

The user agent can then safely upgrade the initial request from HTTP to HTTPS, rather than blocking it as mixed content.

1.2. Goals

HSTS priming has the overarching goal of removing mixed content as a barrier to securing the internet. This breaks down into two concrete objectives:

  1. Convert the Strict-Transport-Security assertion from a negative one ("This host is only available via secure transport") to a positive one ("Any resource on this host addressed by an insecure scheme is available via secure transport. Please grab it from there instead.").

  2. Teach user agents how to verify this new HSTS assertion early enough in a request’s lifecycle to avoid being blocked as mixed content.

2. Proposed Modifications

2.1. Fetch

2.1.1. Main Fetch Modifications

  1. After the current step 3 (which deals with Upgrade-Insecure-Requests), add the following steps:

    1. If request's client prohibits mixed security contexts, and request's current url’s scheme is "http" or "ws", and it isn’t a navigation request, and its host does not match the HSTS cache, then perform an HSTS priming request for request.

  2. Move the current step 6 (which deals with HSTS) before the current step 4 (which deals with CSP and mixed content).

    Note: This isn’t entirely accurate, as we probably want reporting to happen before the upgrade (that is, before the current step 3). That’s a bug in the existing algorithm that I need to take care of.

    Note: Maybe use the newly defined HSTS cache for the upgrade instead of deferring to the RFC.

Note: If a user agent implements prerendering or prefetching, it might be a wonderful idea to perform a priming request for any insecure navigation that such a function proposes. The performance impact would be (mostly) hidden by the background nature of such a request, and the security impacts would be interesting indeed.

2.1.2. HTTP-network Fetch modifications

Modify HTTP-network Fetch as follows:

  1. After the current step 9 (which processes the Set-Cookie header), execute the following steps:

    1. If response's header list contains one or more headers named Strict-Transport-Security, then add an entry to the HSTS cache with the following properties:


      response's url’s host


      Parse the header.


      Parse the header.



2.1.3. HSTS Priming Requests

To perform an HSTS Priming Request for request, run these steps:

  1. If request's current url’s scheme is not "http" or "ws", abort these steps.

    Note: I’m assuming that Web Sockets are going to be folded into Fetch at some point?

  2. Let primer be a new request whose properties are set as follows:




    A new URL whose scheme is "https", host is request's current url’s host, and port is request's current url’s port


    request's initiator


    request's type


    request's destination

    credentials mode

    request's credentials mode

    redirect mode




    referrer policy


  3. Append a header named "Upgrade-Insecure-Requests" with a value of "1" to primer's header list.

  4. Let response be the result of performing an HTTP-network-or-cache fetch using primer.

  5. If response's header list does not contain one or more headers named Strict-Transport-Security, then add an entry to the HSTS cache with the following properties:


    primer's url’s host


    A reasonable expiration. Perhaps 24 hours?




    "do not upgrade"

2.1.4. HSTS Cache

An HSTS cache consists of a collection of HSTS cache entry objects, each with the following properties:


A host


A timestamp, after which this entry is no longer valid


"include" or "exclude"


"upgrade" or "do not upgrade"

2.1.5. Does request match the HSTS cache?

A request (request) matches the HSTS cache if there exists an HSTS cache entry entry in the user agent’s HSTS cache such that:
  1. The current time is not after entry's expiration

  2. entry's host is a concurrent match for request's current url’s host


    entry's subdomains is "include", and entry's host is a superdomain match for request's current url’s host

2.2. Mixed Content

  1. Explain the nature of the relationship to HSTS.

2.3. RFC 6797

  1. Explain the nature of the new assertion that’s being made, and its implications.

  2. Integrate the spec with Fetch.

Lots more specifics everywhere.

3. Open Questions

  1. Would it be valuable enough to do this for navigational requests as well? That would have the impact of making the initial window for attack marginally smaller (e.g. the attacker would have to actively block connections over 443, rather than executing an ssl stripping attack), but it’s not clear that there’s much value in the additional complexity.

4. Security Considerations

HSTS priming makes it more likely that developers can upgrade their sites from HTTP to HTTPS, as discussed in the introduction.

It has the nice side-effect of making it possible for CDNs and widget providers to increase the security of the web in one fell swoop, which increases the value of the Strict-Transport-Security header significantly.

5. Privacy Considerations

5.1. Leakage via Divergent Hosts

As little sense as it may make, some hosts do serve different content via HTTPS than they serve via HTTP (forbes.com is the canonical example). HSTS priming has the potential of leaking information about insecure resource requests to the secure variant of the requests' host. We mitigate this risk by stripping out interesting information from the priming request. It does not contain referrer information (as we set the referrer policy to none), it contains no credential information, and it doesn’t contain the URL of the resource being requested (as we target the root of the secure origin).

5.2. History Leakage

The HSTS state of a host leaks some information about a user’s browsing history. Likewise, if the user agent caches failed HSTS priming requests, those failures leak information. User agents SHOULD give users the ability to clear these caches, and should expire them in a reasonable amount of time.

6. Acknowledgements

Richard Barnes proposed this treatment in a thread that included very helpful comments from Eric Mill, Brad Hill, Mark Nottingham, Brian Smith, Tanvi Vyas, Martin Thomson, and Anne van Kesteren.


Conformance requirements are expressed with a combination of descriptive assertions and RFC 2119 terminology. The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in the normative parts of this document are to be interpreted as described in RFC 2119. However, for readability, these words do not appear in all uppercase letters in this specification.

All of the text of this specification is normative except sections explicitly marked as non-normative, examples, and notes. [RFC2119]

Examples in this specification are introduced with the words “for example” or are set apart from the normative text with class="example", like this:

This is an example of an informative example.

Informative notes begin with the word “Note” and are set apart from the normative text with class="note", like this:

Note, this is an informative note.


Terms defined by this specification

Terms defined by reference


Normative References

Anne van Kesteren. Fetch Standard. Living Standard. URL: https://fetch.spec.whatwg.org/
Mike West. Mixed Content. 8 October 2015. CR. URL: http://www.w3.org/TR/mixed-content/
Document Object Model URL: https://dom.spec.whatwg.org/
S. Bradner. Key words for use in RFCs to Indicate Requirement Levels. March 1997. Best Current Practice. URL: https://tools.ietf.org/html/rfc2119
J. Hodges; C. Jackson; A. Barth. HTTP Strict Transport Security (HSTS). November 2012. Proposed Standard. URL: https://tools.ietf.org/html/rfc6797
Anne van Kesteren; Sam Ruby. URL. 9 December 2014. WD. URL: http://www.w3.org/TR/url-1/

Informative References

Brad Hill. Why isn't HTTPS everywhere yet?. URL: http://webappsec-test.info/~bhill2/DifferentTakeOnOE.html
Mike West. Mixed Content. 8 October 2015. CR. URL: http://www.w3.org/TR/mixed-content/
Mike West. Upgrade Insecure Requests. 8 October 2015. CR. URL: http://www.w3.org/TR/upgrade-insecure-requests/

Issues Index

Parse the header.
Parse the header.
Lots more specifics everywhere.