Content Security Policy (CSP) in Magento 2: Configuration and Troubleshooting
Content Security Policy (CSP) is a browser security mechanism that controls which external resources (scripts, styles, images, iframes, fonts) a page is allowed to load. Magento 2 includes built-in CSP support starting with version 2.3.5. When CSP blocks a required resource, the result is broken functionality -- missing payment forms, tracking scripts that fail to fire, or chat widgets that do not render.
How CSP Works in Magento
Magento sends CSP rules as HTTP headers with every page response. The browser reads these headers and blocks any resource that does not match the allowed sources.
CSP rules are defined per directive, each controlling a specific resource type:
script-src-- JavaScript files and inline scriptsstyle-src-- CSS files and inline stylesimg-src-- Imagesframe-src-- Iframes (payment forms, embedded content)font-src-- Web fontsconnect-src-- AJAX/fetch/WebSocket connectionsdefault-src-- Fallback for any directive not explicitly defined
CSP Modes
Report-Only Mode
In report-only mode, the browser logs CSP violations to the console but does not block the resources. This is the default for Magento in developer mode.
The response header looks like:
Content-Security-Policy-Report-Only: script-src 'self' https://example.com; ...
Use report-only mode to identify which resources need whitelisting before switching to restrict mode.
Restrict Mode
In restrict mode, the browser actively blocks resources that violate the policy. This is the recommended setting for production.
The response header looks like:
Content-Security-Policy: script-src 'self' https://example.com; ...
Configure the mode in Stores → Configuration → Security → Content Security Policy:
- Report-Only for development and testing
- Restrict for production
Configuring Whitelists with csp_whitelist.xml
To allow external resources, create a csp_whitelist.xml file in your module or theme:
app/code/Vendor/Module/etc/csp_whitelist.xml
Example: Allowing Google Analytics, Google Fonts, and a payment gateway iframe:
<?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="google-analytics" type="host">https://www.google-analytics.com</value>
<value id="google-tagmanager" type="host">https://www.googletagmanager.com</value>
</values>
</policy>
<policy id="style-src">
<values>
<value id="google-fonts" type="host">https://fonts.googleapis.com</value>
</values>
</policy>
<policy id="font-src">
<values>
<value id="google-fonts-static" type="host">https://fonts.gstatic.com</value>
</values>
</policy>
<policy id="frame-src">
<values>
<value id="payment-gateway" type="host">https://checkout.paymentprovider.com</value>
</values>
</policy>
<policy id="connect-src">
<values>
<value id="analytics-collect" type="host">https://www.google-analytics.com</value>
</values>
</policy>
</policies>
</csp_whitelist>
After adding or modifying csp_whitelist.xml, flush the cache:
php bin/magento cache:flush
Debugging CSP Violations
Using Browser DevTools
Open DevTools (F12) and check the Console tab. CSP violations appear as error messages like:
Refused to load the script 'https://example.com/script.js' because it violates the following Content Security Policy directive: "script-src 'self'"
The error message tells you:
- What type of resource was blocked (script, style, image, frame)
- The URL of the blocked resource
- Which CSP directive was violated
Use this information to add the correct domain to the appropriate policy in csp_whitelist.xml.
Common Symptoms
- Payment form not rendering: The payment gateway iframe URL is not in
frame-src - Tracking scripts not firing: The analytics domain is not in
script-src - Chat widget not loading: The chat service domain needs to be added to multiple directives (
script-src,frame-src,connect-src,style-src) - Fonts not loading: Google Fonts or custom font CDN missing from
font-src - Inline scripts blocked: Some extensions use inline JavaScript that requires
'unsafe-inline'inscript-src(avoid this if possible -- use nonces instead)
Development vs Production
During development, keep CSP in report-only mode. This allows all resources to load while logging violations, so you can build a complete whitelist.
Before deploying to production:
- Review all console violations in report-only mode
- Add all legitimate external resources to
csp_whitelist.xml - Switch to restrict mode
- Test all store functionality (checkout, tracking, third-party widgets)
Switching to restrict mode without whitelisting all required resources will break store functionality for visitors.