Magento CSP instellen: strict mode op de checkout zonder gedoe
Terug naar blog

Magento CSP instellen: strict mode op de checkout zonder gedoe

Bijgewerkt 7 min leestijd

Sinds Magento 2.4.7 staat CSP op je betaalpagina's standaard in restrict mode. Wie dat niet heeft voorbereid, ontdekt het als de betaalknop stilvalt.

Sinds Magento 2.4.7 staat CSP op je betaalpagina's standaard in restrict mode. Wie dat niet heeft voorbereid, ontdekt het als de betaalknop stilvalt.

Een Content Security Policy (CSP) vertelt de browser welke scripts, stylesheets, frames en verbindingen op een pagina zijn toegestaan. Alles wat niet op de lijst staat, blokkeert de browser. Dat is precies wat je wilt tegen Magecart-skimmers, maar het is ook precies wat je extensies kapot maakt als ze inline scripts of externe bronnen gebruiken die niemand heeft geregistreerd.

In dit artikel lopen we door hoe CSP in Magento werkt, wat er in de praktijk breekt en hoe je stap voor stap naar een strikte policy gaat zonder dat je conversie wegzakt.

Wat Magento 2.4.7 standaard doet

Het gedrag in 2.4.7 is helder:

  • Op de betaalpagina's (checkout) draait CSP in restrict mode. Overtredingen worden echt geblokkeerd.
  • Op alle andere pagina's draait CSP in report-only mode. De browser meldt overtredingen, maar blokkeert niets.
  • De CSP-module kun je in 2.4.7 niet meer uitschakelen.

Dat laatste is een bewuste keuze van Adobe. De reden is PCI DSS 4.0. Eis 6.4.3 vraagt om een inventaris, autorisatie en integriteitscontrole van alle scripts op de betaalpagina. Eis 11.6.1 vraagt om detectie van ongeautoriseerde wijzigingen op die pagina. Een goed ingestelde CSP helpt bij 6.4.3, omdat je per definitie een lijst hebt van toegestane scriptbronnen. Meer over de eisen lees je in ons artikel over PCI DSS 4.0 voor webshops en op de pagina security en PCI DSS.

Let op: CSP alleen is geen volledige invulling van 6.4.3 of 11.6.1. Het is een bouwsteen. Welke maatregelen jouw QSA of betaalprovider accepteert, bepaalt zij, niet wij.

Hoe een CSP eruitziet

Een CSP is een HTTP-header met directives. Een sterk vereenvoudigd voorbeeld:

Content-Security-Policy:
  default-src 'self';
  script-src 'self' https://js.betaalprovider.example;
  connect-src 'self' https://api.betaalprovider.example;
  frame-src https://pay.betaalprovider.example;
  img-src 'self' data: https:;
  report-uri https://csp.jouwdomein.example/report

De belangrijkste directives voor een webshop:

DirectiveRegeltTypische bron van problemen
script-srcWelke JavaScript mag draaienInline scripts, tag managers, chat-widgets
style-srcWelke CSS mag ladenInline styles van extensies
connect-srcWaar fetch/XHR naartoe magBetaal-API's, analytics, zoekdiensten
frame-srcWelke iframes mogen ladenHosted payment fields, 3D Secure
img-srcWaar afbeeldingen vandaan komenTracking pixels, externe beeld-CDN's
form-actionWaar formulieren naartoe postenRedirects naar de betaalprovider

Toestaan via csp_whitelist.xml

In Magento registreer je toegestane bronnen per module in etc/csp_whitelist.xml. Voor een betaalprovider ziet dat er zo uit:

xml
<?xml version="1.0"?>
<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="betaalprovider" type="host">js.betaalprovider.example</value>
            </values>
        </policy>
        <policy id="connect-src">
            <values>
                <value id="betaalprovider-api" type="host">api.betaalprovider.example</value>
            </values>
        </policy>
        <policy id="frame-src">
            <values>
                <value id="betaalprovider-pay" type="host">pay.betaalprovider.example</value>
            </values>
        </policy>
    </policies>
</csp_whitelist>

Een goede betaalmodule levert dit bestand zelf mee. Mist het? Dan is dat een kwaliteitssignaal over die module. Je kunt het zelf toevoegen in een kleine eigen module, maar dan beheer je het ook zelf bij elke wijziging van de provider.

Na het toevoegen leeg je de config-cache en controleer je de response headers op de checkout.

Inline scripts en nonces

Hier gaat het in de praktijk het vaakst mis. Een strikte CSP staat geen willekeurige inline scripts toe. Er zijn twee manieren om inline code toch te laten werken:

  • Hashes: de browser vergelijkt de hash van het inline script met de lijst in de policy. Verandert er één teken, dan klopt de hash niet meer.
  • Nonces: een willekeurige waarde per request, zowel in de header als in het script-tag. Alleen scripts met de juiste nonce draaien.

Magento heeft hiervoor de SecureHtmlRenderer. In een .phtml template laat je die het script-tag bouwen, in plaats van zelf