What leads CSP rollouts to stall on multi-vendor storefronts
This module extends Magento 2’s built-in CSP whitelist system with scope awareness. Each module or integration declares the sources it needs in a scoped_csp_whitelist.xml file, and entries can be pinned to a specific website, store group, or store view — not just applied globally. Best fit when you have or plan to enforce CSP and multiple third-party integrations with different source domains across different storefronts.
<p class="brocode-impact-callout">Typical impact: safer CSP rollouts with smaller blast radius — one integration’s source change no longer forces a policy relaxation across the entire storefront.</p>
<div class="brocode-cta-bar"><a class="wp-block-button__link wp-element-button" href="https://github.com/brosenberger/module-scoped-csp" rel="nofollow noopener" target="_blank" data-event="module_github_click">View on GitHub</a><a class="wp-block-button__link wp-element-button is-secondary" href="#brocode-inquiry" data-event="module_inquiry_click">Ask a question</a></div>
Who For
- Magento 2 teams moving from report-only to CSP enforce mode
- Multi-storefront sites where different websites use different analytics or payment integrations
- Security and compliance reviewers who need a clear per-module audit trail for whitelist entries
Who Skip
- Single-storefront sites with a small, static set of third-party scripts that rarely change
- Teams choosing to ban inline scripts entirely via server-level CSP headers with no per-module variation
How it works
Drop a scoped_csp_whitelist.xml into your module’s etc/ folder. Entries work like the standard csp_whitelist.xml but add two optional attributes: scopeType (website, group, store, or omitted for all scopes) and scopeCode (the scope’s code). Magento merges all loaded scoped_csp_whitelist.xml files at request time and applies only the entries that match the current store context.
<!-- etc/scoped_csp_whitelist.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<csp_whitelist xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:module:BroCode_ScopedCsp:etc/scoped_csp_whitelist.xsd">
<policies>
<policy id="img-src">
<values>
<!-- Applied to all scopes (same as standard csp_whitelist.xml) -->
<value id="cdn-global" type="host">https://cdn.example.com</value>
<!-- Applied to website "base" only -->
<value id="analytics-de" scopeType="website" scopeCode="base"
type="host">https://analytics-de.example.com</value>
<!-- Applied to website "en" only -->
<value id="analytics-en" scopeType="website" scopeCode="en"
type="host">https://analytics-en.example.com</value>
</values>
</policy>
</policies>
</csp_whitelist>
If no scopeType is set, the entry applies to all scopes — identical behaviour to the native csp_whitelist.xml. Entries with a scopeType other than default require a matching scopeCode.
Before and after
Before
- A single global CSP whitelist grows with every integration added to any storefront
- A new source domain in one payment provider forces a policy relaxation that affects all websites
- Audit ownership of whitelist entries is unclear — no per-module record
After
- Each module declares only the sources it uses, scoped to the storefronts where that integration is active
- A source change in one payment module affects only the websites that use it
- Per-
scoped_csp_whitelist.xmlfile gives reviewers a clear integration-level audit trail
Installation
composer require brocode/module-scoped-csp
bin/magento setup:upgrade
bin/magento cache:flush
The module enables itself automatically (active="true" in etc/module.xml). No module:enable step is needed.
Safe rollout plan
1. Run CSP in report-only mode and collect violations for at least one full traffic cycle (weekday + weekend).
2. Add scoped_csp_whitelist.xml entries per module/integration for legitimate violations only, scoped to the relevant websites.
3. Promote to enforce mode once violation noise stabilises.
4. Re-validate scope on every integration upgrade.
Rollback
Rollback is straightforward: switch CSP back to report-only mode. Scoped whitelist entries remain intact for the next iteration.
Compatibility
- PHP 8.1, 8.2, 8.3
- Magento 2.4.x (requires
Magento_Csp)
FAQ
Will this break my storefront?
No, when rolled out with report-only first. The module is designed for incremental promotion to enforce mode.
How does it differ from the native `csp_whitelist.xml`?
The native file applies entries globally. This module adds scopeType / scopeCode attributes so entries can be pinned to a specific website, store group, or store view.
What if a third-party integration changes its source domains?
Only that integration’s scoped_csp_whitelist.xml needs updating, not the global policy. Other integrations are unaffected.
How long does a safe rollout typically take?
Most projects move from report-only to enforce within 2–4 weeks of monitoring.
What to watch out for
- Third-party scripts loaded via tag managers can shift source domains without warning.
- Some payment integrations rotate domains; pin only what you must.
- Track
scoped_csp_whitelist.xmlchanges in your module changelog so audits stay straightforward.
Take the next step
<div class="brocode-cta-bar"><a class="wp-block-button__link wp-element-button" href="https://github.com/brosenberger/module-scoped-csp" rel="nofollow noopener" target="_blank" data-event="module_github_click">View on GitHub</a><a class="wp-block-button__link wp-element-button is-secondary" href="#brocode-inquiry" data-event="module_inquiry_click">Ask a question</a></div>