Skip to content
MDView as Markdown

Adobe Commerce and Magento

One platform, three names. Adobe Commerce is the paid edition, Magento Open Source is the free edition, and Mage-OS is a community-governed fork. All three ship the same Magento_Csp module and configure CSP identically, so everything on this page applies to all of them from 2.3.5 onwards.

You do not need an extension and you do not need to hand-write the header - the platform builds the policy for you and gives you a place to put your reporting endpoint.

Storefront and Admin are configured separately, which is worth knowing before you start wondering why a change had no effect on the page you were looking at.

What the platform gives you

  • Two modes per area: report-only, where violations are reported but nothing is blocked, and restrict, where the browser enforces the policy.
  • Four configurable reporting endpoints out of the box - a default for the storefront, a default for the Admin, and a specific one each for the checkout and the Admin create-order page.
  • csp_whitelist.xml for adding trusted domains to individual directives (script-src, style-src, font-src and the rest), or for allowing specific inline scripts and styles by hash.
  • A CSP nonce provider from 2.4.7, so inline scripts can be allowed without 'unsafe-inline'.
  • Per-page overrides in config.xml, so one page can enforce while the rest of the site is still only reporting.

Which pages enforce by default

This catches people out on upgrade, so it is worth being precise. From 2.4.7 the two payment pages enforce and everything else reports:

Page Default mode Set by
Storefront (everything else) Report-only Magento_Csp
Admin (everything else) Report-only Magento_Csp
Storefront - One Page Checkout Restrict Magento_Checkout
Admin - Create Order Restrict Magento_Sales

Those two pages also drop 'unsafe-inline' from script-src, so an inline script that was merely noisy before the upgrade starts failing to run afterwards. Review them first.

Setting your reporting endpoint in the Admin

Go to Stores > Configuration > Security > Content Security Policy (CSP) > Mode. You will find four groups, each with a single Report URI field:

  • Admin Default
  • Admin > Create Order
  • Storefront Default
  • Storefront > One Page Checkout

A page-specific field that is left empty falls back to the default for its area, so filling in the two defaults is enough to start collecting reports everywhere. The field is URL-validated, so paste the full endpoint including the scheme.

Your URL comes from the Setup page in your account and looks like this:

https://abc123.report-uri.com/r/d/csp/reportOnly

Use the right endpoint for the right mode

Because checkout enforces while the rest of the storefront only reports, a single endpoint across both mixes enforced violations and report-only violations into one data set. Set them separately:

Field Endpoint
Storefront Default .../r/d/csp/reportOnly
Storefront > One Page Checkout .../r/d/csp/enforce
Admin Default .../r/d/csp/reportOnly
Admin > Create Order .../r/d/csp/enforce

Reports are sent in both modes, so you keep getting data after you switch a page from report-only to restrict - remember to move that page's endpoint to enforce at the same time.

Setting it in config.xml instead

If you would rather keep the configuration in code, add it to a custom module's etc/config.xml. The area defaults look like this:

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Store:etc/config.xsd">
    <default>
        <csp>
            <mode>
                <storefront>
                    <report_only>1</report_only>
                    <report_uri>https://abc123.report-uri.com/r/d/csp/reportOnly</report_uri>
                </storefront>
                <admin>
                    <report_only>1</report_only>
                    <report_uri>https://abc123.report-uri.com/r/d/csp/reportOnly</report_uri>
                </admin>
            </mode>
        </csp>
    </default>
</config>

report_only is 1 for report-only and 0 for restrict.

Per-page configuration uses the same nodes under csp/mode/{area}_{full_action_name}/, where the area is storefront or admin and the action name is Magento's full action name for the route:

<storefront_checkout_index_index>
    <report_only>0</report_only>
    <report_uri>https://abc123.report-uri.com/r/d/csp/enforce</report_uri>
</storefront_checkout_index_index>

Both values fall back to the area default when they are not set for the page, so you only need to declare what differs.

Allowing resources with csp_whitelist.xml

Add trusted hosts to individual directives from your own module's etc/csp_whitelist.xml. Every value needs an id that is unique within its directive:

<?xml version="1.0" encoding="UTF-8"?>
<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="example_cdn" type="host">https://cdn.example.com</value>
            </values>
        </policy>
    </policies>
</csp_whitelist>

Inline scripts and styles can be allowed the same way with type="hash" algorithm="sha256", taking the SHA-256 of the tag's contents and Base64-encoding it. The algorithm attribute is optional in the schema but the module reads it unconditionally, so leaving it off emits a malformed source expression and the script stays blocked. Add the domain to the narrowest directive that will work - putting a host in default-src because you need one .js file from it opens far more than you meant to.

Flush the cache after any change here or you will be looking at the old header.

Things to watch for

  • Third-party extensions frequently inject their own scripts. Each one needs an entry in csp_whitelist.xml, and your CSP reports are the fastest way to find the ones nobody documented.
  • Hashes break whenever the inline script changes by a single character, including whitespace. Prefer the nonce provider on 2.4.7 and above.
  • Configuration is store-scoped, so check you are editing the right scope on a multi-store install.
  • Your checkout is a payment page in the sense PCI DSS 4.0 means it, so Requirements 6.4.3 and 11.6.1 apply to it. Our Compliance guides cover what is expected.

Official documentation

Start Monitoring with Report URI

Already using us for CSP? Find your report-uri value on Setup, or view your CSP reports.

New to Report URI? Create an account and grab your report-uri value from the Setup page. Working towards PCI DSS 4.0 on your checkout? See our Compliance guides.

Start your free trial