What is mixed content?
It’s worth emphasising that identification of insecure resources is a worthwhile exercise whether or not you’ve already moved to HTTPS.
- If you’re trying to salvage a botched migration, securing these requests is essential if you’re to close off vulnerabilities and ensure your site behaves correctly.
- If you’re yet to migrate, securing resources is a great step towards future-proofing your site in readiness for an HTTPS migration. As we shall see, in many cases this can be done instantly and at zero expense.
Identifying mixed content manually can be time-consuming, but with the right tools you can make your life easier.
Tackling mixed content with Lighthouse
Google’s rapidly advancing Lighthouse tool has been equipping site owners with the tools they need to make protocol migrations as painless as possible. While often associated with performance testing for progressive web apps, Lighthouse has become a very good high-level benchmark for accessibility, security, usability, and modern best practices.
Released last week, version 2.8 introduced the Mixed Content audit. This new audit is not run by default in Lighthouse. You’ll need to run the command line version of the tool and install Chrome Canary.
If you’re new to the command line version, you’ll need to install Node.js. If you’re on Windows, you’ll want to enable the Windows Subsystem for Linux or get Git Bash (included with Git for Windows) to ensure a usable command line environment.
Install lighthouse from the node package manager:
npm install -g lighthouse
Next, head to your working directory and run lighthouse with the –mixed content flag to generate the report:
lighthouse --mixed-content --view https://www.example.com/
The HTML report will open in your default browser. The results are helpfully divided into two categories:
The second category is the most useful. This shows insecure resources which are easily upgradeable to HTTPS (i.e. the domain in question already has a valid SSL certificate). In many cases these will be resources loaded from a third-party CDN which are hard-coded to use the HTTP protocol. For example:
These URLs can simply be changed to specify the secure protocol. On secure pages this will prevent mixed content, but it’s worth making this change on insecure (HTTP) pages too: it will tighten up security by preventing man-in-the-middle attacks and make it easier to upgrade your site to HTTPS in the near future. It’s also worth mentioning that – contrary to popular opinion – requesting secure assets from non-secure pages does not have any meaningful negative performance implications. All assets which are available securely should always be requested via HTTPS.
For resources which are requested over HTTP which cannot simply be requested via HTTPS, the situation is a little more complex. Your options will vary depending on the specifics of your setup, but in many cases you may be able to either load the resource from a different host or CDN, or host the asset on your own (secured) servers.
Finally, you might also see resources on your own domain listed in the Lighthouse report. Let’s say you’ve decided on a phased approach to your HTTPS migration, and are allowing both HTTP and HTTPS versions to resolve while you iron out any issues. The use of relative or protocol-relative URL paths will cause assets to be requested insecurely:
<link rel="stylesheet" href="//mydomain.com/style.css">
While an eventual full migration to HTTPS (i.e. site-wide permanent redirects and the HSTS header enabled) will ensure these resources are requested securely, there’s nothing to stop you from upgrading these requests to HTTPS now, should you wish to do so.
Tackling mixed content with HTTP headers
By setting a Content Security Policy (CSP), it is possible to manage mixed content at scale. If you’re unfamiliar with the principles behind CSP, the articles at HTML5Rocks and the MDN are good places to start.
You can set a CSP by including the Content-Security-Policy or Content-Security-Policy-Report-Only HTTP headers in your server responses. These headers allow us to communicate to compatible browsers how we want them to handle mixed content: we can choose to block, automatically upgrade, or simply report mixed content back to us.
When life throws a challenge your way, it’s often advisable to take stock of the situation before grabbing your hammer. Mixed content problems are no exception: far better to know how many resources you’re dealing with and where they’re being found than to blindly block everything like a maniac. The following response header will instruct compatible browsers to send a JSON-formatted violation report as a POST request to a suitable endpoint every time an asset is requested via HTTP:
Content-Security-Policy-Report-Only: default-src https: 'unsafe-inline' 'unsafe-eval'; report-uri https://example.com/myReportingEndpoint
These reports are JSON-formatted, and you can instruct your developer to ensure the endpoint processes them into your preferred format.
"violated-directive": "default-src https: 'unsafe-inline' 'unsafe-eval'",
"original-policy": "default-src https: 'unsafe-inline' 'unsafe-eval'; report-uri https://example.com/myReportingEndpoint",
Once you’ve tackled the issues and are ready to start enforcing your CSP, you can opt to automatically upgrade all insecure requests to HTTPS:
This is a relatively new standard (remember that CSPs are only respected by browsers that support them) but support is climbing rapidly. This header will force browsers to upgrade requests automatically, and if a particular resource is not available via HTTPS, it will not be loaded (thereby preserving security).
Finally, you may opt to block mixed content completely:
This is fairly self-explanatory, but it’s worth noting that this directive will cascade into <iframe> elements too.
The benefits of HTTPS – and indeed the dangers of remaining on HTTP – are growing every day, but that’s not to say that a migration to HTTPS should be rushed. On the contrary, it is more important than ever that protocol migrations be executed carefully and with consideration given to SEO.
For site owners and developers who are yet to make that jump (or for anyone who’s made the jump but broken their legs on landing thanks to a carelessly placed insecure resource), the tools and techniques I’ve outlined above should help you to take positive steps towards securing your site in a smooth migration to HTTPS.
Thanks for reading!