What is mixed content?

In web security, you may have heard of "mixed content". Maybe you saw a DevTools message like this one.

Mixed Content: Upgrading insecure display request ‘http://...’ to use ‘https’.

This blog post is going to explain what "mixed content" means, its implications for your website and how to handle mixed content.

Mixed Content: active or passive?

When hosting a web page on secure HTTPS, as it should be the default nowadays, the term "mixed content" refers to content on your web page that is not using HTTPS. Typical examples are images in <img> tags, stylesheets or scripts which still point to URLs starting with http://. Ideally, a website that supports HTTPS should ensure that all its content is also secured with HTTPS. Otherwise, the protection against network attackers that it gained with HTTPS could be compromised:

When the browser visits a web page that uses mixed content, a passive network attacker can gain information about the user's browsing behavior because of those unprotected mixed content URLs in the web page. Furthermore, an active network attacker could replace or modify the mixed content and therefore attack the whole home page.

Browsers have long since included protection against the harms of mixed content. Already in July 2014, a first working draft came out in the W3C web application security working group, that suggested browsers should block so-called active mixed content. Originally, this referred to <script> and <iframe> elements, ensuring that a network attacker can not modify or inject scripts into a victim page. Other content, so-called passive mixed content (e.g., images) were still allowed. The goal of this change, back then, was to prevent the attack from active network attackers but still supporting existing content, which still used a lot of HTTP. As such, the active attacks were thwarted, but passive attackers were still be able to infer browsing behavior through network sniffing.

From then on, all new HTML elements and features, like responsive images in <picture>, elements were all considered "active" elements and supposed to be blocked.

Upgrade Insecure Requests

Right after that, the webappsec working group developed a new directive for Content-Security-Policy (CSP) headers. Web pages that want their mixed content to be secure can supply a response header of Content-Security-Policy: 'upgrade-insecure-requests' and the browser will implicitly rewrite all HTTP URLs into HTTPS. This includes passive and active mixed content. Hyperlinks with an <a>, are also rewritten but only when they refer to the same-origin. But again, this upgrading is all opt-in.

Mixed Content: upgradable and blockable

Then, in year 2020, the engineers in the Chrome browser's network security group did a thorough study to learn more about mixed content that is still to be observed across the web.

The outcome was an even newer, improved Mixed Content standard. So that now, as of 2024, most browsers no longer distinguish between "active" and "passive" mixed content.

From now on, all browsers will instead distinguish between blockable and upgradable mixed content. Where the former includes HTML elements that have already been blocked (e.g., like <script>, <iframe>), and we assume we can't start loading lest sites break again. The latter is the passive content that we have previously loaded insecurely.

In essence, web pages that are hosted on HTTPS and contain image, audio or video elements pointing to HTTP will receive an automatic, implicit upgrade. Browsers will still not upgrade <a> elements that point to same- or cross- origin URLs.

This is true for the browsers Firefox 127, Chrome 86, and Safari 18 (currently in Tech Preview and expected to be released in the fall of 2024) or newer.

Now, with that changed in the Mixed Content standard, if you want your same-origin URLs to be redirected, you can use an HTTPS Strict_Transport-Security header. You can still set a Content-Security-Policy with 'upgrade-insecure-requests' to upgrade all, the blockable, the upgradable content and the <a> elements.

This blog post was written as a counterpart to our release announcement blog post at "Firefox will upgrade more Mixed Content in Version 127" at the Mozilla Security blog.

If you find a mistake in this article, you can submit a pull request on GitHub.

Other posts

  1. The Mozilla Monument in San Francisco (Fri 05 July 2024)
  2. What is mixed content? (Sat 15 June 2024)
  3. How I got a new domain name (Sat 15 June 2024)
  4. How Firefox gives special permissions to some domains (Fri 02 February 2024)
  5. Examine Firefox Inter-Process Communication using JavaScript in 2023 (Mon 17 April 2023)
  6. Origins, Sites and other Terminologies (Sat 14 January 2023)
  7. Finding and Fixing DOM-based XSS with Static Analysis (Mon 02 January 2023)
  8. DOM Clobbering (Mon 12 December 2022)
  9. Neue Methoden für Cross-Origin Isolation: Resource, Opener & Embedding Policies mit COOP, COEP, CORP und CORB (Thu 10 November 2022)
  10. Reference Sheet for Principals in Mozilla Code (Mon 03 August 2020)
  11. Hardening Firefox against Injection Attacks – The Technical Details (Tue 07 July 2020)
  12. Understanding Web Security Checks in Firefox (Part 1) (Wed 10 June 2020)
  13. Help Test Firefox's built-in HTML Sanitizer to protect against UXSS bugs (Fri 06 December 2019)
  14. Remote Code Execution in Firefox beyond memory corruptions (Sun 29 September 2019)
  15. XSS in The Digital #ClimateStrike Widget (Mon 23 September 2019)
  16. Chrome switching the XSSAuditor to filter mode re-enables old attack (Fri 10 May 2019)
  17. Challenge Write-up: Subresource Integrity in Service Workers (Sat 25 March 2017)
  18. Finding the SqueezeBox Radio Default SSH Password (Fri 02 September 2016)
  19. New CSP directive to make Subresource Integrity mandatory (`require-sri-for`) (Thu 02 June 2016)
  20. Firefox OS apps and beyond (Tue 12 April 2016)
  21. Teacher's Pinboard Write-up (Wed 02 December 2015)
  22. A CDN that can not XSS you: Using Subresource Integrity (Sun 19 July 2015)
  23. The Twitter Gazebo (Sat 18 July 2015)
  24. German Firefox 1.0 ad (OCR) (Sun 09 November 2014)
  25. My thoughts on Tor appliances (Tue 14 October 2014)
  26. Subresource Integrity (Sun 05 October 2014)
  27. Revoke App Permissions on Firefox OS (Sun 24 August 2014)
  28. (Self) XSS at Mozilla's internal Phonebook (Fri 23 May 2014)
  29. Tales of Python's Encoding (Mon 17 March 2014)
  30. On the X-Frame-Options Security Header (Thu 12 December 2013)
  31. html2dom (Tue 24 September 2013)
  32. Security Review: HTML sanitizer in Thunderbird (Mon 22 July 2013)
  33. Week 29 2013 (Sun 21 July 2013)
  34. The First Post (Tue 16 July 2013)