What is the "Upgrade-Insecure-Requests" HTTP header?

user193130 picture user193130 · Aug 11, 2015 · Viewed 139.9k times · Source

I made a POST request to a HTTP (non-HTTPS) site, inspected the request in Chrome's Developer Tools, and found that it added its own header before sending it to the server:

Upgrade-Insecure-Requests: 1

After doing a search on Upgrade-Insecure-Requests, I can only find information about the server sending this header:

Content-Security-Policy: upgrade-insecure-requests

This seems related, but still very different since in my case, the CLIENT is sending the header in the Request, whereas all the information I've found is concerning the SERVER sending the related header in a Response.


So why is Chrome (44.0.2403.130 m) adding Upgrade-Insecure-Requests to my request and what does it do?


Update 2016-08-24:

This header has since been added as a W3C Candidate Recommendation and is now officially recognized.

For those who just came across this question and are confused, the excellent answer by Simon East explains it well.

The Upgrade-Insecure-Requests: 1 header used to be HTTPS: 1 in the previous W3C Working Draft and was renamed quietly by Chrome before the change became officially accepted.

(This question was asked during this transition when there were no official documentation on this header and Chrome was the only browser that sent this header.)

Answer

Simon East picture Simon East · Aug 14, 2015

Short answer: it's closely related to the Content-Security-Policy: upgrade-insecure-requests response header, indicating that the browser supports it (and in fact prefers it).

It took me 30mins of Googling, but I finally found it buried in the W3 spec.

The confusion comes because the header in the spec was HTTPS: 1, and this is how Chromium implemented it, but after this broke lots of websites that were poorly coded (particularly WordPress and WooCommerce) the Chromium team apologized:

"I apologize for the breakage; I apparently underestimated the impact based on the feedback during dev and beta."
— Mike West, in Chrome Issue 501842

Their fix was to rename it to Upgrade-Insecure-Requests: 1, and the spec has since been updated to match.

Anyway, here is the explanation from the W3 spec (as it appeared at the time)...

The HTTPS 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.

...

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].