Skip to main content

Mixed Active Content on HTTPS Pages

Issue No: 185

Category: HTTP Security Headers

Issue Type: Issue

Priority: Critical


Description

HTTPS pages must not load active resources (scripts, stylesheets, iframes) over HTTP. Browsers block mixed active content entirely, breaking page functionality and removing the HTTPS security indicator, directly harming user trust and site credibility.

Crawler Constraint: The XeoPix crawler detects mixed content declared in raw HTML only. Resources injected by JavaScript or referenced inside external CSS files via url() cannot be detected without execution or fetching external stylesheets. The triggers only fire when HTTP-scheme URLs are found in static HTML resource attributes on an HTTPS page.


How Do We Capture It

Where to Find

Mixed active content (browser blocks):

<script src="http://cdn.example.com/app.js"></script>
<link rel="stylesheet" href="http://cdn.example.com/style.css">
<iframe src="http://widget.example.com/embed"></iframe>
<object data="http://cdn.example.com/plugin.swf"></object>
<embed src="http://cdn.example.com/player.swf">

Mixed passive content (browser warns):

<img src="http://cdn.example.com/image.jpg">
<video src="http://media.example.com/clip.mp4"></video>
<audio src="http://media.example.com/track.mp3"></audio>
<source src="http://media.example.com/clip.webm">

Extraction Flow

  1. Issue an HTTP GET to the target URL; follow any redirects to the final URL.
  2. Check the scheme of the final resolved URL.
  3. If the final URL scheme is http, set page_is_https = FALSE and skip all further analysis — mixed content only applies to HTTPS pages.
  4. If the final URL scheme is https, set page_is_https = TRUE and continue.
  5. Parse the full raw HTML document.
  6. Collect resource URLs from active resource tags:
    • <script>src attribute
    • <link>href attribute (where rel is stylesheet, preload, modulepreload, or empty)
    • <iframe>src attribute
    • <object>data attribute
    • <embed>src attribute
  7. Filter for URLs where the scheme is exactly http:// (not https://, not protocol-relative //).
  8. Collect these into active_mixed_content_urls; count and set has_active_mixed_content.
  9. Collect resource URLs from passive resource tags:
    • <img>src attribute
    • <video>src attribute
    • <audio>src attribute
    • <source>src attribute
  10. Filter for URLs where the scheme is exactly http://.
  11. Collect these into passive_mixed_content_urls; count and set has_passive_mixed_content.

Note: Protocol-relative URLs (//cdn.example.com/...) inherit the page scheme. On HTTPS pages they resolve to https:// and are not mixed content. Do not flag protocol-relative URLs.

Validation Logic

The crawler validates:

  • Whether the final resolved URL uses the HTTPS scheme.
  • Whether any active resource attribute in the HTML contains an absolute http:// URL.
  • Whether any passive resource attribute contains an absolute http:// URL.
  • That has_active_mixed_content and has_passive_mixed_content are only set to TRUE when page_is_https = TRUE.

How to Get It

Crawler should:

  1. Resolve the final URL; check scheme — skip analysis entirely if http.
  2. Parse full raw HTML document.
  3. Collect src/href/data values from active tags (script, link, iframe, object, embed).
  4. Filter for http:// scheme; store as active mixed content list.
  5. Collect src values from passive tags (img, video, audio, source).
  6. Filter for http:// scheme; store as passive mixed content list.
  7. Set BOOLEAN flags based on whether each list is non-empty.

What to Store

FieldTypeComment
page_is_httpsBOOLEANWhether the final resolved crawled URL uses the HTTPS scheme
has_active_mixed_contentBOOLEANWhether any active resource (script, stylesheet, iframe, object, embed) loads over HTTP on this HTTPS page; always FALSE when page_is_https = FALSE
active_mixed_content_urlsTEXT[]List of http:// URLs found in active resource attributes on an HTTPS page
active_mixed_content_countINTNumber of distinct active mixed content URLs found
has_passive_mixed_contentBOOLEANWhether any passive resource (img, video, audio, source) loads over HTTP on this HTTPS page; always FALSE when page_is_https = FALSE
passive_mixed_content_urlsTEXT[]List of http:// URLs found in passive resource attributes on an HTTPS page
passive_mixed_content_countINTNumber of distinct passive mixed content URLs found

Condition for Trigger

The following trigger rules evaluate mixed content on HTTPS pages. Both has_active_mixed_content and has_passive_mixed_content are only set to TRUE when page_is_https = TRUE, so these triggers cannot fire on HTTP pages.

  • Trigger Rule 1: Active Mixed Content Detected

    • Target Field: has_active_mixed_content
    • Evaluation Logic: = TRUE
    • Severity: CRITICAL
    • Diagnostic Message: "Active mixed content was detected: one or more scripts, stylesheets, or iframes load over HTTP on this HTTPS page. Browsers block these resources entirely, causing page functionality to break silently. Upgrade all active resource URLs from http:// to https://."
  • Trigger Rule 2: Passive Mixed Content Detected

    • Target Field: has_passive_mixed_content
    • Evaluation Logic: = TRUE
    • Severity: WARNING
    • Diagnostic Message: "Passive mixed content was detected: one or more images, videos, or audio resources load over HTTP on this HTTPS page. Browsers display a downgraded security indicator and may block these resources in future versions. Upgrade all passive resource URLs from http:// to https://."

Sources


Long Description

Mixed content occurs when an HTTPS page loads resources from HTTP origins. The browser has established a verified TLS connection to the page, but then initiates unencrypted HTTP connections for individual resources. An attacker in a network-adjacent position (public Wi-Fi, ISP, CDN) can intercept and modify those HTTP resources in transit before they reach the browser.

Why active mixed content is critical:

Active mixed content can read or modify the page DOM and execute arbitrary JavaScript. A man-in-the-middle attacker who intercepts an HTTP script response can inject any code into the page, with full access to the user's session, cookies, and form inputs. For this reason, all modern browsers (Chrome, Firefox, Safari, Edge) block active mixed content entirely — the resource never loads.

Why passive mixed content is a warning:

Passive mixed content cannot execute code but can be inspected in transit. An attacker can observe which images the user loads (revealing page context) or modify images before delivery. Chrome now also blocks passive mixed content (images over HTTP on HTTPS pages) in many cases. Even where not blocked, the HTTPS padlock is replaced with a warning icon.

Resource type classification:

TypeTagsBrowser behavior
Activescript, link (CSS/preload), iframe, object, embedBlocked — resource does not load
Passiveimg, video, audio, sourceWarned — may load but padlock is removed

Common failure scenarios:

1. Legacy Hardcoded HTTP URLs in HTML Templates

A CMS or site generator hardcodes http://static.example.com for asset URLs in HTML templates. When the site is migrated to HTTPS, the templates are not updated and all assets continue to be referenced over HTTP.

2. User-Generated Content With HTTP Image URLs

A blog, forum, or e-commerce platform allows users to embed images from external sources. User-submitted http:// image URLs become passive mixed content on the HTTPS page.

3. Third-Party Script Loaded Over HTTP

An embedded chat widget, analytics snippet, or advertisement SDK is added via an HTTP <script> tag. The script is blocked by the browser, the widget fails silently, and the padlock is removed.

4. Protocol-Relative URLs Not Flagged

URLs beginning with // (e.g., //cdn.example.com/script.js) are protocol-relative. On HTTPS pages they resolve to https://cdn.example.com/script.js and are safe. This check does not flag protocol-relative URLs.

5. Dynamic or CSS-Injected Mixed Content Not Detected

Resources loaded by JavaScript at runtime or referenced via url() in external CSS files cannot be detected from raw HTML. These are known constraints of static crawl-based analysis.


How to Fix

Upgrade all HTTP-scheme resource URLs to HTTPS in the HTML source:

  1. Replace http:// with https:// for every resource URL in HTML templates, CMS media settings, theme files, and page builders.
  2. Verify that the HTTPS endpoint for each resource returns the correct content and an HTTP 200 response.
  3. For third-party resources, use the https:// URL provided by the vendor. If the vendor does not offer HTTPS, replace the resource with an HTTPS-capable alternative.
  4. For resources under your own domain or CDN, ensure TLS is enabled and the asset is accessible over HTTPS.
  5. Use protocol-relative URLs (//cdn.example.com/...) only when a resource must serve both HTTP and HTTPS pages from the same URL. On HTTPS pages, protocol-relative URLs automatically use HTTPS.
  6. Add Content-Security-Policy: upgrade-insecure-requests as an additional server-side safeguard. This instructs browsers to automatically upgrade HTTP resource requests to HTTPS before the request is made, providing a runtime safety net while source URLs are being fixed. This header does not replace fixing the source URLs — it is a supplemental measure only.