Mixed content: HTTP resources on an HTTPS page
An HTTPS page that loads a script or stylesheet over HTTP is not secure and browsers block it. squirrel lists every HTTP resource per page.
What mixed content is
Mixed content is an HTTPS page that pulls in a subresource over plain HTTP. The document arrives encrypted, the subresource does not, and anything in the network path can read or replace it. A tampered script has the same power as any other script on the page.
Browsers treat the two halves differently. Active content, meaning scripts, stylesheets, frames and workers, is blocked outright. Passive content, meaning images, audio and video, is usually upgraded to HTTPS and blocked when the upgrade fails. Some requests are blocked rather than upgraded, including srcset and <picture> images and anything on an IP-literal host. What a visitor notices first is a missing asset, so mixed content tends to surface as a broken page before it surfaces as a security report.
What squirrel checks
The rule runs on every crawled page and emits a check named mixed-content:
- Info when the page URL does not start with
https://, since the concept does not apply. Message:Mixed content check not applicable - page not HTTPS. - Fail when the HTML has a resource element whose
src,hrefordataattribute literally starts withhttp://. Message:3 HTTP resource(s) on HTTPS page (2 potentially blocked, 1 potentially upgraded; from markup, not observed loads). Severity error. - Pass when none do. Message:
No mixed content detected.
Each listed URL keeps the tag, attribute and rel it came from, so you can see whether it is a <script src>, a <link rel="stylesheet" href> or an <img src>.
The selectors are img[src], script[src], link[href], iframe[src], video[src], audio[src], source[src], embed[src] and object[data]. The match is on the literal http:// prefix in the markup, so protocol-relative URLs such as //cdn.example.com/x.js are not flagged, and neither are HTTP URLs that only appear in inline scripts or CSS.
Only elements that fetch a resource count
A <link> is reported only when its rel makes the browser fetch something: stylesheet, modulepreload, preload, prefetch, manifest and the icon relations. <link rel="canonical">, rel="alternate" (hreflang and feed links) and other metadata links are not fetched, so an http:// URL there is not mixed content. Fix those for other reasons, such as canonical hygiene.
Potentially blocked or potentially upgraded
Findings come from the markup, not from a browser, so they are labelled by what a browser would do:
- Potentially blocked: scripts, stylesheets, frames,
embed,object, fonts and other preloads, and anything on an IP-literal host. - Potentially upgraded: images, audio, video and icons, which browsers rewrite to HTTPS and block only when the upgrade fails.
Each item carries meta.kind (potentially-blocked or potentially-upgraded) and meta.evidence: "static-markup". squirrel does not report an insecure load that a browser observed.
Loopback URLs
localhost, *.localhost, 127.0.0.0/8 and [::1] are potentially trustworthy origins, and browsers do not treat them as mixed content. They are left out of the mixed-content check. A separate local-development-url warning lists them, because a URL like http://localhost:3000/app.js left in production markup only works on the developer’s own machine.
Elements inside <noscript> are skipped: a browser with scripting enabled reads <noscript> content as plain text, so nothing in it loads or renders. See content inside noscript.
How to fix it
<script src="https://cdn.example.com/lib.js"></script>Change the URL to https:// at the source, in the template or the CMS field that produced it. For a large legacy corpus, Content-Security-Policy: upgrade-insecure-requests makes the browser rewrite the requests while you work through the markup, but it is a mitigation rather than the fix.
A third-party host that has no HTTPS endpoint cannot be upgraded. Self-host the asset or drop it.
| Rule ID | security/mixed-content |
| Category | Security |
| Scope | Per-page |
| Severity | error |
| Weight | 7/10 |
Enable / disable
Disable this rule
[rules]
disable = ["security/mixed-content"]Disable all Security rules
[rules]
disable = ["security/*"]Enable only this rule
[rules]
enable = ["security/mixed-content"]enable replaces the default ["*"], so this is the only rule selected. Leave disable out: a rule that matches any disable pattern is skipped even when enable names it. Only an enabled setting under a rule’s own [rule_options] table overrides both lists.
Related rules
- security/https: whether the page itself is HTTPS before its subresources matter.
- links/https-downgrade: navigation links, rather than subresources, that point at
http://. - security/sri: integrity hashes for the cross-origin assets that remain.
- images/broken-images: images that fail to load, which is how blocked mixed content usually surfaces.
Security findings ship in every audit next to the SEO, performance and agent experience rules. See Website security scan with AI for how an agent works through a report.
References
Check your site
Run squirrel audit https://example.com and open the Security section of the report. Every HTTP resource is listed by page with its URL. Signed-out local audits need no account and cost nothing. Signed-in audits spend credits.