Magento 2's Silent CSP Reporting Flaw: Are You Missing Critical Security Data?

Uncovering a Hidden Flaw in Magento 2 CSP: Why Your Security Reports Might Be Incomplete

As e-commerce migration experts at Shopping Mover, we constantly monitor the Magento ecosystem for critical insights that impact our clients. A recent GitHub issue (#41232) has brought to light a significant, yet silent, flaw in Magento 2's Content Security Policy (CSP) reporting mechanism that could be leaving merchants and developers with incomplete security data.

The Silent Data Loss Problem

The core of the issue lies in how Magento 2 constructs the Report-To header. Since Magento Open Source 2.4.0 (and even 2.3.5+), the Magento\Csp\Model\Policy\Renderer\SimplePolicyHeaderRenderer::render() method uses the same report_uri value for both the classic report-uri directive and the newer report-to directive. This is problematic because modern Content Security Policy Level 3 specifies that if report-to is present, user agents (browsers) should ignore report-uri entirely.

The critical assumption made by Magento's core code is that a single endpoint will serve both reporting mechanisms: the older application/csp-report payload for report-uri and the newer batched application/reports+json payload for the Reporting API (via report-to). In practice, security collectors often expose these as two separate addresses. Consequently, browsers that support and prioritize report-to (like Chromium-based browsers and newer Firefox versions) end up sending their security reports to an endpoint that isn't configured to accept the application/reports+json payload, leading to silent failures and missing data.

The original issue author, ScottHelme, highlighted this with the following code snippet:

    if ($config->getReportUri() && !$response->getHeader('Report-To')) {
        $reportToData = ['group' => 'report-endpoint', 'max_age' => 10886400,
                         'endpoints' => [['url' => $config->getReportUri()]]];
        $value .= ' report-uri ' . $config->getReportUri() . ';';
        $value .= ' report-to '  . $reportToData['group'] . ';';
        $response->setHeader('Report-To', json_encode($reportToData), true);
    }

This code explicitly builds the Report-To header from the report_uri, creating the conflict.

Deeper Dive: Browser Behavior and Deprecated Headers

The discussion in the comments section, particularly from lbajsarowicz, provided crucial clarifications and deepened the understanding of the problem:

  • Safari's Complete Blind Spot: Safari 16.4+ implements report-to but critically, it only reads the Reporting-Endpoints header, not the deprecated Report-To header that Magento emits. This means Safari users are losing 100% of their CSP reports on Magento 2 stores.
  • Firefox's Evolution: Firefox versions 149 and newer now also prioritize report-to, behaving like Chrome and contributing to the silent data loss if the endpoint isn't correctly configured for the Reporting API.
  • Deprecated Header Usage: Magento currently emits the Report-To header, which is part of the deprecated Reporting API v0. The current W3C specification defines Reporting-Endpoints. This means even a "fix" that adds a separate field for Report-To would still leave Safari unsupported.
  • CORS and Max-Age Considerations: Cross-origin Reporting API endpoints require CORS preflight requests. Furthermore, the hardcoded max_age of 126 days (10886400 seconds) for the Report-To header means that even after a merchant corrects their configuration, browsers that have already "primed" with the old setting will continue sending reports to the incorrect endpoint for months.

Immediate Workarounds and Future Fixes

Currently, the only viable workaround for affected Magento 2 stores is to implement a plugin on the SimplePolicyHeaderRenderer to correctly manage the CSP headers. This allows developers to override Magento's default behavior and ensure reports are sent to the appropriate Reporting API endpoint.

For a permanent core solution, the community suggests:

  • Adding a dedicated configuration field for the Reporting API endpoint, separate from report_uri.
  • Critically, Magento's core should transition from emitting the deprecated Report-To header to the current standard, Reporting-Endpoints, to ensure compatibility with all modern browsers, including Safari.

This issue, confirmed by the Magento engineering team, highlights the importance of staying updated on browser and web security standards. For merchants and developers, it's a call to action to verify their CSP reporting setup to ensure comprehensive security monitoring.

Start with the tools

Explore migration tools

See options, compare methods, and pick the path that fits your store.

Explore migration tools