# How to Implement Content Security Policy (CSP) in Magento 2: A Complete Developer Guide

> Learn to implement Content Security Policy (CSP) in Magento 2 using the native framework and whitelist resources via csp_whitelist xml. Secure your Magento 2 store effectively.

- Repository: [Alessandro Ronchi/mageres](https://github.com/aleron75/mageres)
- Tags: how-to-guide
- Published: 2026-02-24

---

**Magento 2 includes a native CSP framework that generates HTTP `Content-Security-Policy` headers via the `Magento_Csp` module, allowing you to whitelist external resources by creating an [`etc/csp_whitelist.xml`](https://github.com/aleron75/mageres/blob/main/etc/csp_whitelist.xml) file in your theme or module.**

Magento 2 ships with a comprehensive Content Security Policy (CSP) system designed to prevent cross-site scripting (XSS) attacks by controlling which external resources can load on your storefront. According to the **mageres** resource repository, implementing CSP requires understanding the core `Magento_Csp` module and configuring XML-based whitelist files that merge automatically across all installed extensions. This guide covers the exact file paths, code examples, and third-party tools you need to implement Content Security Policy (CSP) in Magento 2 without breaking your frontend functionality.

## Understanding Magento 2's Built-In CSP Architecture

The CSP system in Magento 2 operates through a modular architecture that aggregates policy definitions from across the codebase and renders them as HTTP headers.

### Core Components and File Locations

- **`Magento_Csp` module**: The engine that parses policy definitions and builds the final header. Located at `vendor/magento/module-csp`.

- **[`csp_whitelist.xml`](https://github.com/aleron75/mageres/blob/main/csp_whitelist.xml)**: Declares allowed sources for specific directives. Modules place this in `app/code/<Vendor>/<Module>/etc/csp_whitelist.xml`, while themes use `app/design/frontend/<Vendor>/<theme>/etc/csp_whitelist.xml`.

- **[`csp_report.xml`](https://github.com/aleron75/mageres/blob/main/csp_report.xml)**: Optional configuration for violation reporting endpoints, placed in `app/code/<Vendor>/<Module>/etc/csp_report.xml`.

- **[`csp_policy.xml`](https://github.com/aleron75/mageres/blob/main/csp_policy.xml)**: Advanced configuration allowing modules to replace or extend specific directives with custom logic.

- **`GenerateCspHeader` observer**: The class `Magento\Csp\Observer\GenerateCspHeader` in [`vendor/magento/module-csp/Observer/GenerateCspHeader.php`](https://github.com/aleron75/mageres/blob/main/vendor/magento/module-csp/Observer/GenerateCspHeader.php) attaches the final header to the HTTP response.

During request processing, Magento loads every [`csp_whitelist.xml`](https://github.com/aleron75/mageres/blob/main/csp_whitelist.xml) file found in the system, merges the source lists for each directive, and constructs the `Content-Security-Policy` header. If a resource is not whitelisted, the browser blocks the request and optionally reports the violation.

## Step-by-Step Implementation of CSP in Magento 2

### Creating Your csp_whitelist.xml

Create a whitelist file in your theme or custom module to declare trusted external domains. This XML defines which sources are permitted for directives like `script-src`, `style-src`, and `img-src`.

```xml
<?xml version="1.0"?>
<!-- File: app/design/frontend/Vendor/theme/etc/csp_whitelist.xml -->
<csp_whitelist xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
               xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Csp:etc/csp_whitelist.xsd">
    <!-- Allow Google Fonts -->
    <directive name="font-src">
        <source>https://fonts.gstatic.com</source>
        <source>https://fonts.googleapis.com</source>
    </directive>

    <!-- Allow external JS libraries (e.g., Stripe) -->
    <directive name="script-src">
        <source>https://js.stripe.com</source>
    </directive>

    <!-- Allow images from a CDN -->
    <directive name="img-src">
        <source>https://cdn.example.com</source>
    </directive>
</csp_whitelist>

```

Magento automatically merges this configuration with other modules' whitelist entries, ensuring your custom sources are added to the final policy.

### Enabling Violation Reporting with csp_report.xml

To monitor blocked resources during development or production, configure a reporting endpoint that receives JSON violation reports from browsers.

```xml
<?xml version="1.0"?>
<!-- File: app/code/Vendor/Module/etc/csp_report.xml -->
<csp_report xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Csp:etc/csp_report.xsd">
    <report-uri>https://example.com/csp-report</report-uri>
    <!-- Optional: set the reporting mode (default is "report-only") -->
    <mode>enforce</mode>
</csp_report>

```

Ensure your endpoint at `https://example.com/csp-report` is publicly accessible via HTTPS and can accept POST requests without authentication.

### Deploying and Testing Your Policy

After creating your XML files, deploy static content and clear caches to apply the changes:

```bash
bin/magento setup:static-content:deploy
bin/magento cache:clean
bin/magento cache:flush

```

Verify the header appears in your browser's network tab as `Content-Security-Policy` with your whitelisted sources included.

## Advanced CSP Configuration Techniques

### Handling Inline Scripts and Nonces

Inline scripts and styles are blocked by default unless they include a **nonce** (a cryptographically unique token) or a cryptographic hash. Magento's UI components automatically generate nonces for scripts rendered through the framework. For manually added inline code, you must either:

- Render it through Magento's block system to receive an automatic nonce
- Calculate the SHA hash and add it to [`csp_policy.xml`](https://github.com/aleron75/mageres/blob/main/csp_policy.xml) for explicit allowance

### Managing Large Headers with Csp Split Header

When running many third-party extensions, the CSP header can exceed server length limits (typically 8KB). The **Csp Split Header** extension solves this by splitting the policy into multiple headers.

As referenced in the mageres repository at [`README.md`](https://github.com/aleron75/mageres/blob/main/README.md) line 339, install the extension to distribute directives across `Content-Security-Policy-1`, `Content-Security-Policy-2`, etc.:

```xml
<?xml version="1.0"?>
<!-- File: app/code/Basecom/CspSplitHeader/etc/module.xml -->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
    <module name="Basecom_CspSplitHeader" setup_version="1.0.0"/>
</config>

```

This registration activates an observer that segments the policy while maintaining full browser compatibility.

### Automating Policy Generation with AutoCSP

For a hands-off approach, the **AutoCSP** module (listed at [`README.md`](https://github.com/aleron75/mageres/blob/main/README.md) line 313 in mageres) scans your storefront's outgoing requests and auto-generates whitelist entries.

Install via Composer:

```bash
composer require henriquekieckbusch/henriquekieckbusch-module-autocsp
bin/magento module:enable Henriquekieckbusch_AutoCsp
bin/magento setup:upgrade

```

AutoCSP creates a scheduled task that aggregates required sources and writes them to [`var/autocsp/csp_whitelist.xml`](https://github.com/aleron75/mageres/blob/main/var/autocsp/csp_whitelist.xml), eliminating manual XML editing.

## Common CSP Implementation Pitfalls and Solutions

| Issue | Cause | Solution |
|-------|-------|----------|
| Inline script blocked | Script lacks a generated nonce or hash | Use Magento UI components that auto-inject nonces, or manually add hashes via [`csp_policy.xml`](https://github.com/aleron75/mageres/blob/main/csp_policy.xml) |
| Header exceeds server limit | Too many extensions contributing sources | Install **Csp Split Header** to distribute the policy across multiple headers |
| Third-party JS violations | External assets not declared in whitelist | Add domains to [`csp_whitelist.xml`](https://github.com/aleron75/mageres/blob/main/csp_whitelist.xml) or use **AutoCSP** to scan and suggest entries |
| Report URL not receiving data | Endpoint requires authentication or uses HTTP | Ensure the report URI is HTTPS and publicly accessible without authentication |

## Essential Tools from the Mageres Resource Collection

The **mageres** repository curates several extensions that streamline CSP implementation:

- **Magento CSP Whitelist Generator**: A Chrome extension that inspects your page and generates the XML whitelist automatically. Referenced in `resources.csv` line 122.

- **AutoCSP**: Automates policy generation by observing actual traffic patterns. Found at [`README.md`](https://github.com/aleron75/mageres/blob/main/README.md) line 313.

- **Csp Split Header**: Solves header length limitations by splitting the policy. Listed at [`README.md`](https://github.com/aleron75/mageres/blob/main/README.md) line 339.

- **mage2_ext_csp**: Collects CSP errors in the admin panel and suggests whitelist rules. Located at [`README.md`](https://github.com/aleron75/mageres/blob/main/README.md) line 269.

## Summary

- **Magento 2's CSP system** is implemented through the `Magento_Csp` module and configured via XML files, with the final header generated by [`vendor/magento/module-csp/Observer/GenerateCspHeader.php`](https://github.com/aleron75/mageres/blob/main/vendor/magento/module-csp/Observer/GenerateCspHeader.php).
- Create **[`csp_whitelist.xml`](https://github.com/aleron75/mageres/blob/main/csp_whitelist.xml)** in your theme or module at [`etc/csp_whitelist.xml`](https://github.com/aleron75/mageres/blob/main/etc/csp_whitelist.xml) to declare allowed external resources for specific directives.
- Use **[`csp_report.xml`](https://github.com/aleron75/mageres/blob/main/csp_report.xml)** to capture violation reports and monitor blocked resources in real-time.
- Leverage **AutoCSP** to automate whitelist generation based on observed traffic, or use **Csp Split Header** if your policy exceeds server header length limits.
- Always deploy static content and clear caches after modifying CSP configuration files.

## Frequently Asked Questions

### What is the easiest way to implement CSP in Magento 2 without manually writing XML?

Install the **AutoCSP** module (`henriquekieckbusch/henriquekieckbusch-module-autocsp`). This extension scans your storefront's outgoing requests, aggregates the domains your site actually uses, and automatically generates the [`csp_whitelist.xml`](https://github.com/aleron75/mageres/blob/main/csp_whitelist.xml) file in `var/autocsp/`, eliminating manual configuration.

### Where does Magento 2 generate the Content-Security-Policy header?

Magento 2 generates the CSP header in **[`vendor/magento/module-csp/Observer/GenerateCspHeader.php`](https://github.com/aleron75/mageres/blob/main/vendor/magento/module-csp/Observer/GenerateCspHeader.php)**. This observer class aggregates all [`csp_whitelist.xml`](https://github.com/aleron75/mageres/blob/main/csp_whitelist.xml) configurations from modules and themes, merges them, and attaches the final `Content-Security-Policy` header to the HTTP response before it reaches the browser.

### How do I fix "inline script blocked" CSP violations in Magento 2?

Inline scripts are blocked unless they contain a **nonce** or cryptographic hash. Use Magento's UI component system to render inline scripts, as it automatically injects nonces. For static inline code, calculate the SHA-256 hash of the script content and add it to your whitelist using [`csp_policy.xml`](https://github.com/aleron75/mageres/blob/main/csp_policy.xml), or refactor the code to load from an external file that can be whitelisted in [`csp_whitelist.xml`](https://github.com/aleron75/mageres/blob/main/csp_whitelist.xml).

### Can I split the CSP header if it becomes too long for my server?

Yes. Use the **Csp Split Header** extension (referenced at [`README.md`](https://github.com/aleron75/mageres/blob/main/README.md) line 339 in mageres). This extension registers an observer that divides the CSP policy into multiple headers (`Content-Security-Policy-1`, `Content-Security-Policy-2`, etc.) rather than a single large header, preventing 502 Bad Gateway errors caused by header length limits in Nginx or Apache.