A page served over HTTPS is only as trustworthy as everything it loads. If the HTML arrives over TLS but a script, stylesheet or iframe inside it is fetched from an http:// URL, that one request is unprotected, and the page is no longer reachable only over encrypted transport. This article covers what the finding means, why it is rated medium, how to remove the cleartext references, and how to confirm the fix on the next scan.
What mixed active content is
The W3C Mixed Content specification (https://www.w3.org/TR/mixed-content/) splits insecure subresources into two groups:
- Optionally blockable content is passive: images, audio and video. A tampered image can mislead a user, but it cannot execute code in the page.
- Blockable content is active: scripts, stylesheets, iframes,
fetchand XHR targets, web workers, fonts, and<object>/<embed>resources. These can read or rewrite the page, and the specification says user agents should block them on a secure page.
This finding is about the second group. It fires when an HTTPS page references active subresources over cleartext.
Typical causes:
<!-- Hard-coded scheme left over from before the HTTPS migration -->
<script src="http://cdn.example.net/vendor/analytics.js"></script>
<link rel="stylesheet" href="http://static.example.com/theme.css">
<iframe src="http://widgets.example.org/booking"></iframe>
Other sources are database content with absolute http:// URLs, a CMS "site URL" setting that was never switched to https://, third-party tags that inject further http:// scripts at runtime, and application code that calls an http:// API endpoint from JavaScript.
Why an attacker cares
Anyone on the network path can modify cleartext traffic: a hostile Wi-Fi access point, a compromised router, an ISP-level injector. If your page requests http://cdn.example.net/vendor/analytics.js, the attacker answers that request with their own script, and the browser runs it with the full privileges of your origin. That script can read session data from the DOM, rewrite the login form, add a keylogger, or redirect to a phishing page. The padlock still shows, because the top-level document was delivered securely.
Modern browsers usually block this content, and some try to upgrade it automatically. That is why the severity is medium and not high. In the common case the visible damage is a broken page: a missing script, an unstyled layout, or a dead widget. The risk stays real for three reasons:
- Blocking behaviour differs between browsers, versions, embedded webviews and enterprise-managed clients.
- The spec treats blocking as the user agent's job, so your site's security depends on the visitor's client and not on your configuration.
- Auditors read it as a failure of the claim that the site is served only over encrypted transport. It also weakens HSTS, since a policy that forces HTTPS for the page is contradicted by the page's own references.
The cost to an organization has two parts. One is the incident risk of script injection on a page that may handle logins or payments. The other is the compliance and support cost of an audit finding, plus broken features that users report as outages.
How the scanner detects and rates it
The scanner loads the page over HTTPS, follows redirects, and inspects the HTML it receives. It checks the attributes that cause a fetch of active content: src on script and iframe, href on stylesheet links, and data on object elements. Any whose resolved URL uses the http scheme is flagged. Protocol-relative URLs resolve to https on an HTTPS page and are not flagged, and absolute https:// URLs are fine.
The finding is rated medium. Browsers' default blocking reduces the likelihood of exploitation, but where blocking does not apply, the impact is arbitrary script execution in your origin. The evidence attached to the finding lists each offending URL with the tag and attribute that referenced it, so you can search your templates or content store for the exact string.
The scan only sees what is present in the delivered HTML. Resources added later by JavaScript, or on pages the scanner does not fetch, may still need a manual check in the browser console.
Fixing it
1. Find every reference
Search source and content for the hostnames in the evidence:
grep -rn "http://" templates/ static/ --include="*.html" --include="*.js" --include="*.css"
For CMS-driven sites, also check the database for absolute URLs stored in posts, widgets and theme options. Then open the page in a browser with developer tools. The console reports each blocked or upgraded request with its URL.
2. Change the URLs
Switch to https:// when the host supports it, which nearly all CDNs and widget providers do:
<script src="https://cdn.example.net/vendor/analytics.js"></script>
If a third party only serves cleartext, do not keep it. Self-host the file, pin a version, and consider a Subresource Integrity attribute so any later change is detected:
<script src="/assets/vendor/analytics-4.2.1.js"
integrity="sha384-REPLACE_WITH_HASH"></script>
3. Update configuration, not just markup
Set the site URL in your CMS or framework to https://. Check any reverse proxy too. If TLS terminates at a load balancer, make sure the application trusts the forwarded protocol header so it generates https:// links instead of http:// ones.
4. Add a safety net
The upgrade-insecure-requests directive tells the browser to rewrite insecure subresource URLs to HTTPS before fetching them:
Content-Security-Policy: upgrade-insecure-requests
For nginx:
add_header Content-Security-Policy "upgrade-insecure-requests" always;
This is a backstop and not a repair. It only works when the target host actually answers on HTTPS, and the cleartext URLs stay in your source. Fix the references, then keep the header to catch regressions. You can roll out a stricter policy in report-only mode first:
Content-Security-Policy-Report-Only: default-src https:; report-uri /csp-report
5. Keep the rest of the transport story intact
The same compliance item also expects cleartext HTTP to redirect straight to HTTPS without an intermediate downgrade, and HSTS to be published with a usable lifetime:
Strict-Transport-Security: max-age=31536000; includeSubDomains
HSTS makes the browser refuse cleartext connections to your host. It does not cover subresources on other hosts, so you still need to fix those references.
Confirming the fix
- Reload the affected pages with the developer console open. There should be no mixed-content warnings.
- Run
curl -s https://example.com/ | grep -Eo '(src|href|data)="http://[^"]+"'. It should return nothing. - Trigger a re-scan. The finding clears when the delivered HTML contains no active subresource with an
httpscheme. If it persists, the evidence list shows the remaining URLs. They are often in a template that renders only on certain pages, or in a cached copy of the page, so purge CDN and application caches before re-scanning.
Key takeaways
- Mixed active content means an HTTPS page loads scripts, styles, frames or similar resources over
http://, which lets a network attacker run code in your origin. - It is rated medium because browsers usually block it, so the common result is broken features. Where blocking does not apply, the impact is full script execution.
- Fix the references themselves: use
https://, self-host with Subresource Integrity if a vendor lacks HTTPS, and correct CMS and proxy settings. - Treat
upgrade-insecure-requestsas a safety net, not the repair. - Verify with the browser console, a
curlgrep, and a fresh scan after purging caches.