09 Sept 2026 · 3 min read
Content Security Policy and subresource integrity in Magento 2
How to roll out a Content Security Policy in Magento 2 without breaking the storefront, wire subresource integrity for third-party scripts, and the mistakes that make CSP cosmetic.
Part 2 of the Magento 2 security series — implementation-focused. The overview is at /blog/magento2-security.
Why CSP matters here
A storefront loads JavaScript from many sources: the theme, payment iframes, analytics, tag managers, and assorted third-party widgets. A Content Security Policy (CSP) tells the browser which sources are allowed to execute script, load styles, or embed frames. Without it, a single injected <script> — via a stored XSS, a compromised dependency, or a malicious admin widget — runs with full page privileges.
Magento ships native CSP support (a csp_whitelist.xml and a report-only mode), so you do not need an extension to start. You need discipline to do it without breaking checkout.
Start in report-only mode
Never flip CSP to enforce on day one. Magento's CSP module supports a report-only mode that logs violations to the browser console and (optionally) a collector, without blocking anything. Run it for one or two release cycles:
<!-- etc/csp_whitelist.xml -->
<?xml version="1.0"?>
<csp_whitelist xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Csp:etc/csp_whitelist.xsd">
<policies>
<policy id="script-src">
<values>
<value id="self" type="host">self</value>
</values>
</policy>
</policies>
</csp_whitelist>
While in report-only, watch the console on every key route — home, category, product, cart, checkout, and the admin. Each violation is a source you must decide to allow or fix at the source.
Whitelisting the right way
Add only the hosts the storefront actually uses, and be as specific as possible:
<policy id="script-src">
<values>
<value id="payments" type="host">https://js.payments-provider.example</value>
<value id="analytics" type="host">https://www.googletagmanager.com</value>
</values>
</policy>
Avoid unsafe-inline and unsafe-eval — they defeat most of CSP's value. If a vendor script demands them, that is a signal to find a better integration or to hash/nonce the specific inline block (Magento can emit nonces for inline scripts via its CSP module).
Subresource integrity for third-party scripts
For scripts loaded from outside your control (CDNs, vendor JS), add an SRI hash so a tampered file fails to load rather than executing:
<script src="https://cdn.vendor.example/widget.js"
integrity="sha384-<base64-hash>"
crossorigin="anonymous"></script>
Magento's layout does not emit SRI automatically for arbitrary CDN scripts, so when you add a vendor <script> through a layout block/referenceBlock, compute the hash from the exact file you ship and pin it. If the vendor updates the file without telling you, the hash mismatch blocks it — which is the point: no silent supply-chain execution.
Mistakes that make CSP cosmetic
- Leaving
unsafe-inlinebecause "it was easier." This allows any inline script, including injected ones. Solve the specific inline need with a nonce instead. - Whitelisting
*hosts. Ascript-src https://*style rule is barely better than none. Pin hosts. - Forgetting the admin. The admin panel loads its own scripts and widgets; a CSP that only covers the storefront leaves the highest-privilege surface unprotected. Test admin routes too.
- Skipping checkout after a theme change. A new payment method or a Hyva checkout upgrade changes the script sources; re-run report-only after any such change (see the Hyva performance post for the checkout-CSP interaction).
Verification
- Report-only ran for a full release cycle with zero unexpected violations on key routes.
-
unsafe-inline/unsafe-evalabsent from the enforced policy. - Third-party scripts carry SRI hashes.
- Admin routes covered.
- A violate-and-confirm test: inject a
<script>from an unknown host and confirm the browser blocks it.
What's next
CSP protects the browser surface; the next post hardens the admin itself — 2FA, access control, and the mistakes that leave a superuser exposed.
Next in this series: Two-factor auth and admin access hardening —
/blog/magento2-security-2fa