Source: https://w3c.github.io/webappsec/specs/upgrade/
Timestamp: 2019-04-19 23:06:18+00:00

Document:
3.1.1 Relation to "Mixed Content"
4.2 Should insecure requests be upgraded for client?
Increasingly, we encourage authors to transition their sites and applications away from insecure transport, and onto encrypted and authenticated connections [WEB-HTTPS]. While this migration has significant advantages for both authors and users, it isn’t without negative side-effects.
Most notably, mixed content checking [MIX] has the potential to cause real headache for administrators tasked with moving substantial amounts of legacy content onto HTTPS. In particular, going through old content and rewriting resource URLs manually is a huge undertaking. Moreover, it’s often the case that truly legacy content is difficult or impossible to update. Consider the BBC’s archived websites [BBC-ARCHIVE], or the New York Times' hard-coded URLs [NYT-HTTPS].
We should remove this burden from site authors by allowing them to assert to a user agent that they intend a site to load only secure resources, and that insecure URLs ought to be treated as though they had been replaced with equivalent secure URLs.
This document defines a new Content Security Policy directive, upgrade-insecure-requests, through which authors can make this assertion. Note: Delivering the policy as a header allows an administrator to easily opt a set of pages into the upgrade mechanism without touching their source code individually. The legacy content examples above would not be feasible with an approach that inlined the policy into HTML, for example.
The overarching goal is to reduce the burden of migrating websites from a priori insecure origins by reducing the negative side effects of mixed content blocking [MIX].
Authors should be able to ensure that all content requested by a given page loads successfully, and securely. Mixed content blocking should not break pages as a result of migrating to a secure origin.
Note: This requirement is not met by Mixed Content’s strict mode, which makes something like the opposite assertion.
As a result of #1, the user agent should not degrade any security indicators related to requesting mixed content, as no insecure content should be requested.
Authors should be able to ensure that all internal links correctly send users to the site’s secure address, and not to its pre-migration insecure address.
Authors should be able to achieve all these goals without editing a site’s content. This is particularly important for archived content and legacy systems for which maintenance is difficult enough, never mind upgrades.
Authors should be able to pursue a gradual transition from insecure to secure, serving secure resources to clients that support upgrades, while retaining insecure resources for clients that don’t.
Note: The mechanism defined here does not intend to supplant Strict Transport Security [RFC6797]. See §8.2 Relation to HSTS for details.
Megacorp, Inc. wishes to migrate http://example.com/ to https://example.com. They set up their servers to make their own resources available over HTTPS, and work with partners in order to make third-party widgets available securely as well.
The URL will be rewritten before the request is made, meaning that no insecure requests will hit the network. Users will be safer, and Megacorp’s administrators will be happier, as all resource requests will be transparently upgraded with no effort on their part.
User agents will upgrade requests, as described in §1.2.1 Non-navigational Upgrades, rewriting the URL as https://cdn.example.com/image.png. As the server doesn’t respond to secure requests, this results in a network error.
There is no fallback in this scenario: the user agent acts just as though the request had been intentionally made, and the request fails.
Redirect a priori insecure, safely upgradable requests from HTTP to HTTPS by responding with a Location header and a 307 status code.
If the origin is HSTS-safe, then protect against SSL-stripping man-in-the-middle attacks by sending a Strict-Transport-Security header with the preload directive, and ensure that insecure content is never loaded by enabling Mixed Content’s strict mode.
A request is said to be upgraded if it is rewritten to contain a URL with a scheme of https or wss.
A request is said to be safely upgradable if the resource representation which will be returned does not require the upgrade-insecure-requests mechanism described in this document to avoid breakage, or if the request’s header-list contains an Upgrade-Insecure-Requests header field with a value of 1.
An origin is said to be HSTS-safe if no resource representations it returns requires the the upgrade-insecure-requests mechanism described in this document to avoid breakage, and if all resource representations it returns can be served over HTTPS.
HSTS-safe origins can safely opt-into Strict-Transport-Security for all user agents, without risking broken pages for user agents which do not support upgrade-insecure-requests.
An origin is said to be conditionally HSTS-safe if one or more resource representations it returns requires the upgrade-insecure-requests mechanism described in this document to avoid breakage, and if all resource representations it returns can be served over HTTPS.
Conditionally HSTS-safe origins can safely opt-into Strict-Transport-Security only for user agents which support upgrade-insecure-requests.
A host host is a preloadable HSTS host if, when performing Known HSTS Host Domain Name Matching, host is a superdomain match for a Known HSTS Host which asserts both the includeSubDomains directive and the preload directive, or host is a congruent matchfor a Known HSTS Host which asserts the preload directive.
Note: This is a long way of saying "any host the user agent has pinned with a Strict-Transport-Security header that contained a preload directive".
In order to allow authors to mitigate the negative side-effects of migration away from a priori insecure origins, authors may instruct the user agent to transparently upgrade resource requests to potentially secure variants of the original request’s URL.
Environment settings objects and browsing contexts are given an insecure requests policy which has two potential values Do Not Upgrade and Upgrade. It is set to Do Not Upgrade unless otherwise specified. This policy is checked in §4.1 Upgrade request to a potentially secure URL, if appropriate in order to determine whether or not non-navigation requests and form submissions should be upgraded during fetching.
Environment settings objects and browsing contexts are given an upgrade insecure navigations set which contains a set of (host, port) tuples to which navigations ought to be upgraded. Its value is the empty set unless otherwise specified. This set is checked in §4.1 Upgrade request to a potentially secure URL, if appropriate in order to determine whether or not navigation requests should be upgraded.
Monitoring the upgrade-insecure-requests directive has no effect: the directive is ignored when sent via a Content-Security-Policy-Report-Only header. Authors can determine whether or not upgraded resources' original URLs were insecure via Content-Security-Policy-Report-Only. For example, Content-Security-Policy-Report-Only: default-src https:; report-uri /endpoint. See §3.4 Reporting Upgrades for additional detail.
The upgrade-insecure-requests directive results in requests being rewritten at the top of the Fetching algorithm [FETCH], as specified in §4.1 Upgrade request to a potentially secure URL, if appropriate. It’s important to note that the rewrite happens before either Mixed Content [MIX] or Content Security Policy checks take effect [CSP2].
This ordering means that upgraded requests will not be flagged as mixed content. Moreover, it means that upgrade-insecure-requests’s effect takes place before the block-all-mixed-content directive would have a chance to block the request. If the former is set, the latter is effectively a no-op.
Sites which require the upgrade mechanism laid out in this document in order to provide users with a reasonable experience over secure transit need some way to determine whether or not a particular request can safely be redirected from HTTP to HTTPS (and vice-versa). Moreover, conditionally HSTS-safe origins can only opt-into Strict-Transport-Security for supported user agents, and doing otherwise could have negative consequences for the site’s users.
Rather than relying on user-agent sniffing to make this decision, user agents can advertise their upgrade capability when making navigation requests by including an Upgrade-Insecure-Requests header field as described in §3.2.1 The Upgrade-Insecure-Requests HTTP Request Header Field.
The Upgrade-Insecure-Requests HTTP request header field sends a signal to the server expressing the client’s preference for an encrypted and authenticated response, and that it can successfully handle the upgrade-insecure-requests directive in order to make that preference as seamless as possible to provide.
Note: Though the Upgrade-Insecure-Requests header expresses a preference, sending it via the existing Prefer header is problematic, as we expect the response from the server to use it as part of the cache key. Vary: Prefer is too broad, as discussed in w3/webappsec#216.
User agents MUST send an Upgrade-Insecure-Requests header field along with requests for a priori insecure URLs.
Note: Servers can use this signal to upgrade HTTP requests to HTTPS for pages that require upgrade-insecure-requests support.
User agents MUST send an Upgrade-Insecure-Requests header field along with requests for potentially secure URLs whose url’s host is not a preloadable HSTS host.
Note: Servers can use the absence of this signal to downgrade HTTPS requests to HTTP for pages that require upgrade-insecure-requests support.
User agents SHOULD periodically send an Upgrade-Insecure-Requests header field along with requests for potentially secure URLs whose url’s host is a preloadable HSTS host. For example, user agents could send an Upgrade-Insecure-Requests header field only when the asserted max-age is a few days from expiration, or only for a small percentage of requests.
Note: preloadable HSTS hosts have asserted that they are HSTS-safe, and therefore don’t need a downgrade signal. They will need to refresh HSTS status before the asserted max-age expires, and the Upgrade-Insecure-Requests header field serves as a fine signal that HSTS could be refreshed.
When a server encounters this preference in an HTTP request’s headers, it SHOULD redirect the user to a potentially secure representation of the resource being requested.
When a server encounters this preference in an HTTPS request’s headers, it SHOULD include a Strict-Transport-Security header in the response if the request’s host is HSTS-safe or conditionally HSTS-safe [RFC6797].
Set context’s insecure requests policy to Upgrade.
For each value in context’s embedding document’s upgrade insecure navigations set, add value to context’s upgrade insecure navigations set.
Let settings be document’s incumbent settings object.
Set settings' insecure requests policy to Upgrade.
For each value in context’s upgrade insecure navigations set, add value to settings’s upgrade insecure navigations set.
Set settings object’s insecure requests policy to Upgrade.
For each value in inherited responsible browsing context’s upgrade insecure navigations set, add value to settings object’s upgrade insecure navigations set.
Note: We’re using the WHATWG HTML spec’s definition of Worker algorithms, as they’re significantly more clear on these points than [WORKERS].
Violates the policy being monitored, thereby delivering a violation report to /endpoint.
Is upgraded from http://example.com/image.png to https://example.com/image.png.
Does not violate the policy being enforced.
Note: This will be significantly clarified once [CSP2] is rewritten in terms of [FETCH].
Given a request request, this algorithm will rewrite its url if the client from which the request originates has opted-in to upgrades. It will also inject an Upgrade-Insecure-Requests header field header for insecure navigation requests in order to improve a server’s ability to feature-detect a client’s upgrade capabilities.
We will not upgrade cross-origin navigation requests, with the exception of form submissions. Form submissions will be upgraded to mitigate the risk of data leakage via plaintext submissions.
Note: This algorithm is called as step #3 of the Main Fetch algorithm.
Note: User agents can choose to append the Upgrade-Insecure-Requests header field for other requests, as discussed in §3.2.1 The Upgrade-Insecure-Requests HTTP Request Header Field.
If request is a form submission, skip the remaining substeps, and continue upgrading request.
Let tuple be a tuple of request’s url’s host and port.
If tuple is contained in client’s upgrade insecure navigations set, then skip the remaining substeps, and continue upgrading request.
Note: We only upgrade top-level navigation requests for hosts that have explicitly opted-into the behavior for a particular protected resource, as described in §1.2 Examples. Performing upgrades for navigations to third-party resources brings a significantly higher potential for breakage, so we’re avoiding it for the moment.
Return without further modifying request.
Let upgrade state be the result of executing §4.2 Should insecure requests be upgraded for client? upon request’s client.
If upgrade state is Do Not Upgrade, return without modifying request.
If request’s url’s scheme is http, set request’s url’s scheme to https, and return.
If request’s urls port is 80, set request’s urls port to 443.
Note: This will only change the URL’s port if the port is explicitly set to 80. If the port is not set, or if it is set to some non-standard value, the user agent will not modify that value. This implementation makes the same tradeoffs as HSTS (see [RFC6797], and specifically step #5 of Section 8.3, and item #6 in Appendix A).
Note: Due to [FETCH]'s recursive nature, this algorithm will upgrade insecurely-redirected requests as well as insecure initial requests.
4.2. Should insecure requests be upgraded for client?
Given an request’s client client (an environment settings object), this algorithm returns Enforced Upgrade if a priori insecure requests associated with that client should be upgraded, or Do Not Upgrade otherwise. In short, this will check the client and return the appropriate insecure requests policy set on it or its browsing context.
If client has a responsible document, return the value of its insecure requests policy.
Note: This catches Documents or Workers whose policy is set directly by the upgrade-insecure-requests directive, or which have inherited the policy from an embedding document.
If client has a responsible browsing context, return the value of its insecure requests policy.
Note: This catches requests triggered from detached clients. Not sure this is necessary, really, given the inheritance structure defined in §3.3 Policy Inheritance.
WebSockets do not use the fetching algorithm, so we need to handle those requests separately.
Let upgrade state be the result of executing §4.2 Should insecure requests be upgraded for client? upon the relevant settings object for client’s entry script.
If upgrade state is Do Not Upgrade, skip the remaining substeps.
If port is 80, set port to 443.
The upgrade-insecure-requests directive does not replace the Strict-Transport-Security HTTP response header [RFC6797]. Authors who serve their site over secure transport SHOULD send that header with an appropriate max-age in order to ensure that users are not subject to SSL stripping attacks by maliciously active network attackers, or monitoring by maliciously passive network attackers.
The upgrade mechanism specified here adds Upgrade-Insecure-Requests: 1\r\n to every outgoing navigation request to non-preloadable HSTS hosts (as discussed at length on public-webappsec@, and w3c/webappsec#216). The advantages and intent of the header are laid out in §3.2.1 The Upgrade-Insecure-Requests HTTP Request Header Field, and though we’ve taken some steps to ensure that it won’t be a permanent fixture of the platform (by carving out preloadable HSTS hosts), it’s going to be a long, long time before the header vanishes.
User agents are encouraged to find additional carveouts, and implement them.
Legacy clients which do support mixed content blocking [MIX], but do not support the upgrade-insecure-requests directive will continue to have a suboptimal experience on pages containing a priori insecure URLs. Authors SHOULD ensure that they collect violation reports in order to determine which resources are most problematic for their users, and SHOULD use that information to prioritize fixes for URLs in legacy content that users will most likely request.
The mechanism specified here deals only with the security policy for a specific protected resource. It does not deprecate, replace, or in any way reduce the value of the Strict-Transport-Security HTTP response header [RFC6797]. Authors can and should continue to use that header to ensure that their users are not subject to SSL stripping downgrade attacks, as the upgrade-insecure-requests directive will not ensure that users visiting your site via links on third-party sites will be upgraded to HTTPS for the top-level navigation.
Likewise, the Strict-Transport-Security header does not imply the behavior that upgrade-insecure-requests activates. It only ensures that resources requested from an origin will never hit the network insecurely.
We are intentionally keeping these concepts distinct, as authors may choose to activate one or the other behavior, but ought not be forced to bind them together.
Anne van Kesteren helped ensure that the initial draft of this document was sane. Peter Eckersley and Daniel Kahn Gillmor clarified the problem space, and helped point out the impact.

References: §8
 §1
 §4
 §4
 §3
 §4
 §3
 §3
 §1
 §4
 §3
 §4
 §3