Theme: Dawn (applies to all Shopify themes) File: layout/theme.liquid
Issue: PageSpeed Insights flags a “Best Practices” warning for missing Content Security Policy directives, specifically script-src and object-src. Without object-src 'none', browsers won’t block plugin-based script injection (Flash, Java applets, etc.).
Partial fix: Add this as the first line inside <head> in layout/theme.liquid:
<meta http-equiv="Content-Security-Policy" content="object-src 'none';">
This safely resolves the object-src High severity finding. No modern Shopify store uses Flash or Java plugins, so this has zero functional impact.
Why only partial: A strict script-src policy isn’t practical for most Shopify stores due to the number of third-party app scripts (analytics, chat, reviews, etc.) that would each need explicit whitelisting. This is a platform-level challenge better addressed by Shopify centrally.
Suggestion to Shopify: Consider shipping object-src 'none' as a default in Dawn’s theme.liquid — it’s a zero-risk, zero-breakage improvement for all merchants.
Regards
Puneet
Does adding this <meta> tag directly to theme.liquid trigger any issues with Shopify’s Theme Check or break preview renders when installing new third-party apps, or does it work seamlessly across all store configurations?
Hey @WetandDry
hope you’re doing well!
Agreed. object-src 'none' is a low-risk security improvement, and Shopify could easily include it by default in Dawn and other official themes
Good tip, and you were right to call it partial. Here is why it is partial and how to get a bit more of the flag cleared.
The Lighthouse “CSP is effective against XSS” audit looks for three directives together, not just one: script-src, object-src, and base-uri. So object-src ‘none’ on its own clears part of what the audit wants but leaves the other two flagged.
A cheap win to add alongside yours is base-uri ‘none’. It blocks an injected <base> tag from rewriting all your relative URLs to an attacker domain, and on a normal Shopify store it has the same near-zero functional risk as object-src, since almost no theme relies on a base tag. So this is safe to stack:
<meta http-equiv="Content-Security-Policy" content="object-src 'none'; base-uri 'none';">
Where it stops working is script-src. To pass that part Lighthouse wants per-script nonces or hashes with strict-dynamic, and you cannot generate a nonce for Shopify’s own scripts or every app’s injected script from a static theme meta tag. Add a plain script-src and you will just block half your apps. That is the real reason a meta-tag CSP will never fully green the audit, and it lines up with what ai-theme-code-editor said about this being a score improvement more than real XSS protection.
One more limit worth knowing so nobody expects too much from the meta version: a few directives are header-only and get silently ignored in a meta tag, including frame-ancestors, report-uri, and sandbox. So clickjacking protection via frame-ancestors, for example, cannot be done from the theme at all, only Shopify can set that as a header.
So object-src plus base-uri is a fair low-risk best-practices bump, and everyone is right that the proper fix is Shopify sending a real header-based CSP platform-wide.
Hi @WetandDry,
You can fix the object-src warning by adding this inside the <head> of layout/theme.liquid:
<meta http-equiv="Content-Security-Policy" content="object-src 'none';">
Place it near the top of the <head> section, before the theme loads its scripts.
I would avoid adding a strict script-src directive manually, since Shopify apps and third-party services can load scripts from different domains and a restrictive policy may break some functionality.
After adding the object-src directive, clear the cache if needed and run the store through PageSpeed Insights again to verify the result.
This should address the object-src finding without affecting the normal Shopify storefront.
Coding Fifty
Solid write-up, Puneet - the object-src 'none' recommendation is right, and your read on why strict script-src is impractical for app-heavy Shopify stores matches reality. A few additions for anyone applying this:
1. Placement genuinely matters. A CSP delivered via <meta> only governs what loads after it’s parsed, so “first line inside <head>” isn’t just tidiness - if scripts load before the tag, they’re outside the policy. Worth double-checking after adding it, since some apps inject scripts very early in the head.
2. One quick check before adding it: object-src 'none' blocks <object> and <embed> elements. No modern store uses Flash, agreed but a few stores embed PDFs (size charts, spec sheets, menus) via <object>/<embed>, and those would stop rendering. Thirty seconds of searching your theme and pages for those tags first saves a confusing support ticket later.
3. Why this can’t be fully fixed at the theme level — supporting your platform point: some of what a complete CSP wants can’t be delivered through a meta tag at all (and Report-Only mode, the safe way to trial a strict script-src, only works as an HTTP response header). Theme code can’t set response headers on the storefront, so header-level CSP really is Shopify’s to ship, not something a merchant can bolt on. Your suggestion to Shopify is the right place for that ask.
4. For merchants worried about this flag: it lives under Lighthouse’s “Best Practices” category — it doesn’t affect your Performance score, Core Web Vitals, or search ranking. It’s a worthwhile security hardening step, not a speed or SEO emergency. Apply Puneet’s fix calmly; don’t rebuild anything over it.