Content Security Policy for ecommerce: PCI DSS 4.0 requirement explained
In March 2025, two PCI DSS 4.0 requirements that had been labeled "best practice" became mandatory: Requirement 6.4.3 (payment page script management) and Requirement 11.6.1 (change detection for HTTP headers and payment page content). Both requirements respond directly to the wave of Magecart-style JavaScript skimming attacks that stole hundreds of millions of card numbers over the previous decade.
Content Security Policy is central to both requirements. Understanding what CSP does, how to implement it and why it matters for PCI DSS gives ecommerce security teams a concrete path to compliance.
What is a Content Security Policy
Content Security Policy is an HTTP response header (or a meta tag, though the header is preferred) that tells the browser which sources of content are trusted. It is a whitelist: only content from explicitly listed origins is permitted to load or execute.
Without CSP, a browser will execute any JavaScript that is referenced from a page, regardless of where it comes from. If a third-party script (an analytics tag, a chat widget, a pixel) is compromised through a supply chain attack, the browser has no mechanism to distinguish the legitimate version from the malicious modified version. It executes both.
With CSP, the browser checks every resource request against the policy. If the source is not listed, the resource is blocked. A compromised third-party script attempting to exfiltrate card data to an attacker's domain would be blocked if that domain is not in the CSP.
How CSP directives work
A CSP policy consists of directives, each governing a resource type. The most important directives for ecommerce payment pages:
script-src: controls which JavaScript sources can be loaded and executed. This is the most critical directive for PCI DSS. If you list only your CDN, your payment processor's domain and a few analytics providers, any injected script from an unlisted domain is blocked.style-src: controls CSS sources. Less critical for PCI DSS but relevant for preventing clickjacking via CSS overlay attacks.frame-src/child-src: controls which origins can be loaded in iframes. Payment processor iframes (Stripe, Braintree, Adyen) must be listed here.connect-src: controls which origins JavaScript can send data to via XMLHttpRequest, fetch, WebSocket or EventSource. This is critical: a skimmer that captures card data will try to send it somewhere. If the destination is not listed inconnect-src, the exfiltration is blocked.img-src: controls image sources. Trackers using 1x1 pixel images can use img-src to exfiltrate data in URL parameters.default-src: a fallback for directives not explicitly listed. Set to'self'as a baseline and add specific directives for each resource type.form-action: controls where forms can submit. Set this to your payment processor's domain and your own domain. Prevents form hijacking attacks.
PCI DSS 4.0 Requirement 6.4.3 and CSP
Requirement 6.4.3 states that all payment page scripts that are loaded and executed must be managed by the entity. This has three sub-requirements:
First, a method must be in place to confirm that each script is authorized. This means maintaining an inventory of every script on your payment page, what it does and why it is there.
Second, each script must be protected from unauthorized modification. This is where CSP and Subresource Integrity (SRI) come in. CSP prevents unauthorized scripts from loading. SRI verifies that authorized scripts have not been modified.
Third, each script must be attested to that it is authorized. This means someone in the organization formally approves each script on the payment page.
A CSP header that lists every authorized script source satisfies the "method to confirm authorization" sub-requirement: if a script is not in the CSP, it does not load. The inventory and attestation requirements are process controls that CSP supports but does not fully replace.
PCI DSS 4.0 Requirement 11.6.1 and CSP
Requirement 11.6.1 requires a mechanism to detect unauthorized changes to HTTP headers and payment page content. Specifically, you must be alerted when headers are modified or when scripts are added, modified or removed from payment pages.
CSP violation reporting is part of this. When a browser blocks a resource because it violates the CSP, it can send a report to a configured endpoint. These reports include the blocked URL, the violating directive and the page where the violation occurred.
CSP violation reports serve as an early warning system. If a skimmer is injected onto your checkout page and attempts to load a script from an external domain, the first blocked attempt generates a CSP violation report. Monitoring these reports in real time means you can detect injection attacks within minutes.
The report-uri directive (or the newer report-to directive and Reporting API) configures the endpoint: report-uri https://yoursite.com/csp-reports. You need to build or use a service to receive and alert on these reports.
Report-Only mode vs enforce mode
CSP has two deployment modes. Enforce mode blocks resources that violate the policy. Report-Only mode logs violations but does not block anything. The header for Report-Only is Content-Security-Policy-Report-Only.
The standard deployment path: start in Report-Only mode, collect violations for 2-4 weeks, identify all legitimate sources you need to whitelist, update the policy to include all legitimate sources, then switch to enforce mode.
Common mistake: deploying enforce mode without the Report-Only phase. This breaks payment processors (whose scripts are blocked), analytics (which stops collecting data) and chat widgets (which disappear). The broken functionality is often not caught until customers complain.
For PCI DSS compliance, enforce mode on the payment page is required. Report-Only alone does not satisfy Requirement 6.4.3's "protected from unauthorized modification" sub-requirement, because it logs violations but does not prevent them. The payment page security guide covers additional controls that complement CSP enforcement.
Building a CSP for Shopify
Shopify is the most common ecommerce platform and one of the hardest to apply CSP to, because Shopify itself loads many scripts and Shopify's checkout is hosted on checkout.shopify.com.
For Shopify Online Store 2.0 storefronts, you can add CSP headers via Shopify's HTTP headers configuration, but the platform's own scripts must be included in your policy. Shopify's CDN (cdn.shopify.com), Shopify's checkout (checkout.shopify.com) and the Shopify analytics endpoint must be listed.
Shopify Checkout is hosted on Shopify's domain, which means if you are using Shopify's checkout, Shopify controls the checkout page's scripts. Shopify maintains their own PCI DSS compliance for the checkout. Your PCI DSS scope for hosted checkout is reduced: you do not control the payment page, so Requirements 6.4.3 and 11.6.1 apply to Shopify, not you.
If you use Shopify Checkout Extension points or custom checkout UI extensions, you are extending Shopify's checkout with your code. Shopify reviews extensions for security before approval, but you are responsible for the security of your extension's code.
Building a CSP for WooCommerce
WooCommerce on WordPress gives you full server control, which means you can set CSP headers via your web server configuration (Nginx or Apache) or via PHP headers in your theme or a plugin.
WooCommerce payment pages (the checkout page with payment fields) are the highest-risk pages. If you use WooCommerce Payments, Stripe for WooCommerce or a similar hosted fields integration, the payment processor's scripts and iframe origins must be listed.
A baseline WooCommerce checkout CSP must include your own domain ('self'), your payment processor's domain, jQuery CDN (if you load from CDN rather than self-hosting), and any analytics or conversion tracking that runs on checkout. WordPress's admin bar on the frontend must be accounted for if logged-in admin users will ever see the checkout.
WordPress plugins are a significant challenge for CSP. Plugins add scripts from various external domains. An audit of all plugins active on the checkout page is required before writing the policy.
Handling inline scripts
Inline scripts (JavaScript written directly in a script tag in the HTML, rather than loaded from an external file) are blocked by default in a strict CSP. The script-src: 'unsafe-inline' keyword re-enables them, but it also re-enables any injected inline scripts, negating the protection against Magecart-style attacks.
Two approaches allow specific inline scripts without enabling all inline scripts:
Nonces: a random value generated per request is added to the CSP header as 'nonce-RANDOMVALUE' and added to each trusted inline script as an attribute: <script nonce="RANDOMVALUE">. Scripts with matching nonces execute. Scripts without the nonce attribute are blocked. Nonces must be cryptographically random and unique per request. If an attacker cannot predict the nonce, they cannot use it on injected scripts.
Hashes: compute the SHA-256 (or SHA-384/512) hash of the inline script content. Add the hash to the CSP: 'sha256-BASE64HASH'. Only scripts whose content exactly matches the hash execute. This is good for static inline scripts that do not change. Any modification to the script content changes the hash and causes it to be blocked.
For ecommerce, hashes work well for small static inline scripts (e.g., a snippet that initializes a chat widget variable). Nonces are better for dynamic inline scripts that are generated per request. Neither approach is as clean as moving all JavaScript to external files, which are governed by script-src source allowlists.
Tag manager compatibility with CSP
Google Tag Manager (GTM) is used on most ecommerce sites to manage third-party scripts without requiring code deploys. GTM and CSP have a complex relationship.
GTM itself loads from googletagmanager.com, which can be listed in script-src. The problem: GTM's purpose is to dynamically load additional scripts at runtime. Scripts loaded by GTM are loaded from their own CDN domains, which must also be listed. Every tag added to GTM potentially adds a new domain that needs to be in the CSP.
This creates a governance challenge: if a marketing team can add tags to GTM without engineering review, they can inadvertently break the CSP or cause scripts from unlisted domains to be blocked. The process solution is requiring CSP review for any new GTM tag that loads external scripts.
Google's server-side tagging (SGTM) helps: third-party tags are proxied through your own domain rather than loading directly from vendor CDNs. This simplifies CSP because all GTM-managed scripts load from your domain, which is already in 'self'. Server-side GTM reduces CSP complexity significantly for large tag environments.
CSP reporting endpoints and monitoring
CSP violation reports are delivered as JSON POST requests to the configured endpoint. A typical violation report includes: the document URI, the violated directive, the blocked URI, the line number in the source where the violation occurred, and the original policy.
Processing volume: a large ecommerce site can receive thousands of CSP reports per day, most of them from browser extensions injecting code into pages. Filtering out extension-generated reports (identified by their chrome-extension:// or moz-extension:// URIs) is necessary to find signal in the noise.
Services that receive and analyze CSP reports: report-uri.com, csper.io, and custom endpoints backed by logging infrastructure. For PCI DSS 11.6.1 compliance, you need a mechanism that alerts in near-real-time on anomalous violations. Batch log reviews do not satisfy the requirement's intent.
Frequently asked questions
- What is Content Security Policy (CSP)?
- CSP is an HTTP response header that tells the browser which content sources are trusted. It acts as a whitelist: only scripts, styles and resources from explicitly listed origins are permitted to load or execute.
- Is CSP required for PCI DSS 4.0 compliance?
- CSP is not explicitly named as a requirement, but it is one of the most effective technical controls for satisfying Requirement 6.4.3 (script authorization) and supporting Requirement 11.6.1 (tamper detection via violation reporting).
- What is the difference between CSP enforce mode and Report-Only mode?
- Enforce mode blocks resources that violate the policy. Report-Only mode logs violations but does not block anything. For PCI DSS compliance, enforce mode on payment pages is required because Report-Only does not prevent unauthorized scripts.
- Can I use Google Tag Manager with a strict CSP?
- GTM and strict CSP are difficult to combine because GTM dynamically loads scripts from many domains. The practical approach is to exclude GTM from payment pages entirely or use server-side tagging to proxy requests through your own domain.
- How do I deploy CSP without breaking my checkout?
- Start with Content-Security-Policy-Report-Only mode for 2 to 4 weeks to identify all legitimate script sources. Update the policy to include all legitimate sources, then switch to enforce mode.
Complyko checks your checkout and payment pages for missing CSP headers, weak CSP configurations and script inventory gaps. See your PCI DSS 4.0 exposure in one report.
Get your free scan →