Page loads scripts or styles over plain HTTP
Your HTTPS page pulls a script or stylesheet from an http:// address, which anyone on the network can replace.
- Severity
- Medium
- Who can exploit it
- Anyone on the visitor’s network
- Found by
- PatchLabs Live posture: the HTML of your home page
- Lab proof
- Not lab-proven: read from your home page’s HTML
What it is
Mixed content is an HTTPS page that loads part of itself over plain http://. PL-034 covers the parts that can take over the page: <script src="http://…"> and stylesheets (<link rel="stylesheet" href="http://…">). Whoever controls the network can replace that file, and a replaced script runs with full access to your page, including the signed-in session.
Modern browsers block these loads outright, so in practice the usual symptom is a broken feature: a widget, a font or an analytics tag that silently never loads, with a “Mixed Content” error in the console.
Why AI builders produce it
An old embed snippet copied from a provider’s documentation, a CDN URL written with http://, or a template from years ago. A generator pastes what it was given, and local development over http://localhost raises no error.
What we see
A synthetic example for app.example.com, shortened. Not taken from any real site.
<!-- index.html (vulnerable) -->
<link rel="stylesheet" href="http://cdn.example.net/widget/1.4/widget.css">
<script src="http://cdn.example.net/widget/1.4/widget.js"></script>
Check it yourself
# script and stylesheet URLs that start with http://
curl -s https://your-app.com | grep -oiE '<(script|link)[^>]+(src|href)="http://[^"]+"'
Scripts your bundle adds at runtime don’t appear in the HTML. Open the site in the browser with DevTools → Console: every blocked load is listed as “Mixed Content” with its URL.
The fix
Change each URL to https://; nearly every provider serves the same file over HTTPS. Better still, install the library from npm so it ships inside your own bundle. Then add upgrade-insecure-requests as a safety net: it tells the browser to fetch any leftover http:// subresource over HTTPS instead.
In your code
<!-- index.html (fixed) -->
<link rel="stylesheet" href="https://cdn.example.net/widget/1.4/widget.css">
<script src="https://cdn.example.net/widget/1.4/widget.js"></script>
Vercel
{
"headers": [
{
"source": "/(.*)",
"headers": [
{ "key": "Content-Security-Policy", "value": "upgrade-insecure-requests" }
]
}
]
}
If you already send a Content-Security-Policy (PL-030), add upgrade-insecure-requests to it instead of adding a second header.
Netlify / Cloudflare Pages
# public/_headers (Vite copies public/ into the publish folder)
/*
Content-Security-Policy: upgrade-insecure-requests
The file must end up in your publish directory (dist for Vite). Bolt projects deployed to Netlify use this file too. The same rule can live in netlify.toml under [[headers]] if you prefer one config file.
Lovable
This one works as a meta tag in index.html, so it needs nothing from the host:
<!-- index.html, inside <head> -->
<meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests">
Live posture findings come with the header or setting to change. PatchLabs never changes your hosting or your repo.
How PatchLabs finds it
[LOAD] https://app.example.com/ → 200 <script src="http://cdn…"> FLAG 1 script, 1 stylesheet
Live posture reads the HTML of your home page from its one page load and lists <script> and stylesheet URLs that start with http://. It doesn’t download those files, run the page’s JavaScript or look at other pages, so scripts your app adds later are not seen: the console check above covers them.
When the pattern is intended
Never for scripts or styles on an HTTPS page. Plain-HTTP images are a smaller problem and are not part of this finding, but fix them while you are there.
Why it’s rated medium
Medium: a replaced script is a full takeover of the page, but it needs someone on the network path, and current browsers block most of these loads anyway. 15 points in the Live posture grade.
Related findings
Site doesn’t force HTTPS
The plain http:// address of your site serves the page instead of redirecting to https://.
PL-030No Content-Security-Policy
Your page sends no Content-Security-Policy, so any script that gets onto it can run and send data anywhere.
PL-029No HSTS header, or max-age under 180 days
Browsers aren’t told to use HTTPS only, so a visitor’s first request can still go out over plain HTTP.
Guides
Free check
Does your site have PL-034?
Type your site’s address. The free headers check loads your public home page once, like any visitor, and grades HTTPS, the certificate, security headers, cookie flags and mixed content. No sign-up, and the result isn’t stored.
Last reviewed 10 Nov 2026. Finding IDs are stable: link to them freely. Spotted a mistake? Tell us.