Blog · Magento 2.4+

Stripe Payments Blocked by Content-Security-Policy in Magento 2 — What to Check

If a Stripe-powered card field won’t render, or Stripe.js throws errors in the console on Magento 2.4.7+, check DevTools before touching your Stripe configuration. This is a documented, real-world issue — a merchant running a custom payment gateway integrated with Stripe hit exactly this on Magento 2.4.7, and the console showed:

Refused to load the script 'https://js.stripe.com/v3/' because it violates the following
Content Security Policy directive: "script-src 'self' ..."

or, once the script does load:

Refused to connect to 'https://api.stripe.com/v1/payment_methods' because it violates
the following Content Security Policy directive: "connect-src 'self' ..."

Who this actually affects

Worth being precise here: this isn’t a blanket “Stripe breaks on Magento” problem. Magento’s core CSP module doesn’t whitelist Stripe’s domains by default, so exposure depends on which Stripe integration path you’re using:

If you’re on a well-maintained official or third-party module and checkout already works cleanly, this likely isn’t affecting you. If you built or maintain a custom Stripe integration, or you’re troubleshooting a checkout that’s failing silently, it’s worth checking directly.

Why Stripe touches more than one CSP directive

Stripe’s flow can trip several directives at once, which is why fixing one error often just surfaces the next:

How to check if this affects you

  1. Open DevTools → Console on the checkout page.
  2. Look for Refused to load or Refused to connect errors mentioning stripe.com.
  3. If you see none and a test transaction completes cleanly, your module already handles this — no action needed.
  4. If you do see them, check whether your module ships its own csp_whitelist.xml before writing one from scratch. Some do.

Fixing it with csp_whitelist.xml

If your integration doesn’t have one, the policy declaration looks like this:

<csp_whitelist>
    <policies>
        <policy id="script-src">
            <values>
                <value id="stripe-js" type="host">js.stripe.com</value>
            </values>
        </policy>
        <policy id="frame-src">
            <values>
                <value id="stripe-frame" type="host">js.stripe.com</value>
                <value id="stripe-hooks" type="host">hooks.stripe.com</value>
            </values>
        </policy>
        <policy id="connect-src">
            <values>
                <value id="stripe-api" type="host">api.stripe.com</value>
            </values>
        </policy>
    </policies>
</csp_whitelist>

This needs a module, a deploy, and static content compilation — normal for a developer, but it means every time Stripe adds a new subdomain (3D Secure rollouts have introduced new ones before) you’re back in a deploy cycle to keep checkout working.

If the XML is in place and Stripe is still blocked, see csp_whitelist.xml not working in Magento 2.

Why “just disable CSP” is the wrong call here

Checkout is the worst place on your storefront to weaken CSP. It’s the page most likely to be targeted by injected skimming scripts (Magecart-style attacks specifically target checkout and payment pages), and CSP is one of the more effective browser-level defenses against exactly that. If Stripe is blocked, whitelist Stripe’s domains specifically — don’t loosen the policy generally.

Managing it from Magento Admin instead

If you’re maintaining a custom Stripe integration and don’t want a deploy every time a payment provider adds a subdomain, CSP Manager for Magento lets an admin add js.stripe.com, hooks.stripe.com, and api.stripe.com to the relevant directives directly from System → Other Settings → CSP Manager, scoped to the store views that use Stripe. The Policy Inspector screen shows the fully merged policy per store view, so you can confirm all four directives are covered before testing checkout again — useful since Stripe issues are easy to half-fix (script loads, but the connect-src call still fails).

Every change is logged in the Audit Log, which is worth having on a checkout-adjacent config given how sensitive that page is.

Verifying the fix

  1. Clear DevTools console, reload the checkout page.
  2. Confirm no Refused to load or Refused to connect errors reference stripe.com.
  3. Enter a test card number and confirm the Stripe Elements field accepts input.
  4. Run a full test transaction, including a 3D Secure challenge if your integration uses it, since that specifically depends on frame-src being correct.