Update #1: it’s less worse than it looked, see details below.
Update #2: chrome got updated, the HTTPS-header is gone, see details below.
Now this is interesting.
In the Chrome 44 release (version 44.0.2403.89) that happened just yesterday, it appears the browser got a small bug significant change.
It’s now sending the HTTPS: 1
header on every request by default. This was probably meant as a security improvement, to suggest HTTPs to the server wherever possible, but it’s breaking WordPress and other webserver installations all over the place.
Why? Because most PHP software uses $_SERVER['HTTPS'];
to detect if the site is running behind an SSL certificate or not. This includes WordPress, Drupal and any custom PHP software that checks this header.
if ($_SERVER['HTTPS'] || $_SERVER['HTTP_HTTPS']) { // Assume HTTPs, redirect or enable https:// prefixes on all resources (css/js/images/...) ... }
The next planned release of Chrome is scheduled on July 27th, but they’re investigating if an emergency patch can be sent out to resolve this issue.
Bugtracker: Issue 505268: Forcing WordPress sites to use https even when not directed.
This is not going to be a fun week for Chrome users.
Update #1: only HTTP_ prefixed headers are affected.
Any request header a browser sends along, gets prefixed with HTTP_
in the $_SERVER
global variable. The User-Agent gets transformed into HTTP_USER_AGENT
, the Accept-header gets turned into HTTP_ACCEPT
, … and so on.
Here’s what those HTTP headers look like according to PHP.
print_r($_SERVER); Array ( ... [HTTPS] => on [HTTP_HOST] => ma.ttias.be [HTTP_ACCEPT] => text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 [HTTP_ACCEPT_ENCODING] => gzip, deflate, sdch [HTTP_ACCEPT_LANGUAGE] => nl-NL,nl;q=0.8,en-US;q=0.6,en;q=0.4,fr;q=0.2,it;q=0.2 [HTTP_COOKIE] => some=value [HTTP_HTTPS] => 1 [HTTP_USER_AGENT] => Mozilla/5.0 )
The first HTTPS value in the $_SERVER
variable is the one set by the webserver, to indicate HTTPs or not. The second one, HTTP_HTTPS, is the HTTPS-header sent by the Chrome browser that gets transformed into an variable for PHP.
Some PHP code, like the WooCommerce WordPress plugin didn’t only check $_SERVER['HTTPS']
, but also looked at $_SERVER['HTTP_HTTPS']
to detect HTTPS on the site. This is wrong PHP code and has nothing to do with “bad PHP by design".
The HTTP_
prefix handling done by WooCommerce is probably done as a result of a Apache bug/feature that once existed, where after 301/302 HTTP rewrites some environment variables would always get prefixed with another HTTP_
keyword.
There are also reverse proxy configs (Nginx, Varnish, …) out there that also pass environment variables along that get interpreted by Apache as headers and thus receive the HTTP_
prefix.
Either way, most plugins have had an update by now, just go to your WordPress/Drupal/… site and update all plugins. Chances are, the problems will be gone, even if Chrome takes a couple more days to get the patch out.
Fixing WooCommerce specifically
Most problems are reported by WooCommerce, the WordPress plugin. Since chances are, you can’t log into your WordPress any more, you’ll need another fix. Many thanks to Rahul Lohakare in the comments for this fix.
Modify the following file, either download it via FTP and upload it again or modify it directly on the server: wp-content\plugins\woocommerce\woocommerce.php
Comment out these lines:
if ( ! isset( $_SERVER['HTTPS'] ) && ! empty( $_SERVER['HTTP_HTTPS'] ) ) { $_SERVER['HTTPS'] = $_SERVER['HTTP_HTTPS']; }
Once those have been commented (just prefix every line with #
), WooCommerce/WordPress won’t redirect you anymore.
If that still doesn’t work, use Firefox or another browser to log into your site and update the plugin via the official WordPress update method. Since the problem is Chrome-only, you can bypass the redirect by using any other browser, temporarily.
Update #2: Chrome got updated, replaced ‘HTTPS’ with ‘upgrade-insecure-requests’
Chrome pushed out an update, everyone should get it in a few hours. I’m now on version 44.0.2403.107, anything higher will not have this problem anymore.
After the update, the HTTPS header has been removed by the upgrade-insecure-request header.
Good news for everyone!