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:
| Directive | Regelt | Typische bron van problemen |
|---|---|---|
script-src | Welke JavaScript mag draaien | Inline scripts, tag managers, chat-widgets |
style-src | Welke CSS mag laden | Inline styles van extensies |
connect-src | Waar fetch/XHR naartoe mag | Betaal-API's, analytics, zoekdiensten |
frame-src | Welke iframes mogen laden | Hosted payment fields, 3D Secure |
img-src | Waar afbeeldingen vandaan komen | Tracking pixels, externe beeld-CDN's |
form-action | Waar formulieren naartoe posten | Redirects 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 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 in HTML te typen. Magento zorgt dan dat het inline blok in de policy komt.
Het oude patroon waar het misgaat ziet er zo uit:
<button onclick="doSomething()">Klik</button>
<script>
var config = <?= $block->getJsonConfig() ?>;
</script>
Inline onclick-attributen en losse script-blokken van derden worden geblokkeerd. De oplossing is de event listener via de renderer registreren en scripts via de renderer uitvoeren. Dat is werk per template, geen configuratie-instelling.
Nonces hebben een nadeel: pagina's die in een full page cache of op een CDN staan, kunnen niet per request een nieuwe nonce krijgen zonder extra werk. Dat is een van de redenen dat Magento voor inline code met hashes werkt.
Wat er breekt
Uit audits kennen we een vast lijstje terugkerende boosdoeners:
- Oude of goedkope betaalmodules met inline scripts en zonder
csp_whitelist.xml. - Tag managers die zelf weer scripts van derden inladen. Je whitelist dan niet één domein, maar een onvoorspelbare keten.
- Chat- en review-widgets die extra domeinen aanroepen.
- Luma-extensies met
eval-achtige constructies, zoals oudere RequireJS-patronen. Een striktescript-srcstaatunsafe-evalniet toe. - Eigen thema-code met inline event handlers.
Op een Hyvä-shop is dit probleem kleiner. Hyvä gebruikt Alpine.js met een CSP-compatibele aanpak, zonder unsafe-eval, en er zit veel minder third-party JavaScript in de standaardinstallatie. Lees meer over Hyvä en waarom minder JavaScript ook een securityvoordeel is.
Stap voor stap naar strikt
Zet CSP niet in één keer overal op strikt. Zo pak je het aan:
- Inventariseer. Open de checkout met de browserconsole open en doorloop de volledige flow: gast, ingelogd, elke betaalmethode, elke verzendmethode. Noteer elke CSP-melding.
- Zet een
report-uriofreport-toin. Verzamel overtredingen van echte bezoekers. Een testrun mist de randgevallen, zoals een 3D Secure-scherm van één specifieke bank. - Draai eerst report-only op de overige pagina's. Dat is de standaard. Laat het minstens een of twee weken verzamelen, inclusief een piek zoals een actie.
- Whitelist wat legitiem is. Voeg alleen toe wat je kunt verklaren. Staat er een domein in de rapporten dat niemand herkent? Dat is geen whitelist-kandidaat, dat is een onderzoek.
- Los inline code op in de bron. Herschrijf templates naar de
SecureHtmlRendererin plaats vanunsafe-inlinetoe te staan.unsafe-inlinemaakt je policy grotendeels waardeloos tegen XSS en skimmers. - Test elke betaalmethode op staging. Doe een echte testbetaling, niet alleen een pagina-load.
- Zet monitoring op de rapporten. Een piek aan meldingen na een deploy betekent bijna altijd dat een extensie of een tag is veranderd.
Wanneer is dit overkill?
Eerlijk: sommige shops hoeven dit niet zelf uit te zoeken. Gebruik je een volledig gehoste betaalpagina waar de klant naartoe wordt doorgestuurd, dan staan er op jouw checkout weinig betaalgevoelige scripts. Dan is een strikte CSP nog steeds nuttig, maar de winst zit meer in het schoon houden van je eigen scripts dan in een lange whitelist.
Voor PCI-verplichtingen in die situatie (SAQ A) zijn 6.4.3 en 11.6.1 in v4.0.1 aangepast. Vraag je QSA of betaalprovider wat voor jou geldt. Dit is geen juridisch of compliance-advies.
CSP is een laag, geen vervanger
Een CSP stopt niet elke aanval. Een skimmer die vanuit een al toegestaan domein laadt, komt er gewoon door. Dat gebeurt bij gecompromitteerde extensies of tag managers. Combineer CSP daarom met:
- Subresource Integrity voor de scripts zelf.
- Bewaking op wijzigingen in bestanden en database, zie Magecart-skimmers detecteren en verwijderen.
- Een kritische blik op extensies en supply chain-risico.
- De bredere Magento 2 security checklist.
Veelgestelde vragen
Kan ik CSP in Magento 2.4.7 uitschakelen?
Nee. De CSP-module kan in 2.4.7 niet meer uit. Je kunt wel het gedrag per pagina afstellen, bijvoorbeeld door een pagina in report-only te laten draaien. Op betaalpagina's is restrict mode de standaard.
Waarom is mijn checkout kapot na een upgrade naar 2.4.7?
Meestal blokkeert de CSP een script of verbinding van een betaalmodule of extensie. Open de browserconsole op de checkout en kijk naar CSP-meldingen. Ze noemen de directive en het geblokkeerde domein. Voeg het domein toe via csp_whitelist.xml of vraag een update aan de leverancier.
Is unsafe-inline een acceptabele oplossing?
Als noodoplossing tijdelijk, ja. Als eindstaat niet. Met unsafe-inline in script-src kan een XSS-lek of een geïnjecteerd script nog steeds draaien, en dan verliest de CSP het grootste deel van zijn waarde.
Moet ik CSP ook op mijn Hyvä-shop instellen?
Ja, de CSP-module werkt ook met Hyvä. Je hebt er minder werk aan, omdat Hyvä met Alpine.js zonder unsafe-eval werkt en er standaard minder externe JavaScript is. Je betaalmodules en tags blijven wel je aandachtspunt.
Vervangt CSP de PCI DSS-eisen 6.4.3 en 11.6.1?
Nee. CSP is een hulpmiddel, geen complete invulling. Je hebt ook een inventaris en rechtvaardiging per script nodig, plus detectie van wijzigingen. Wat jouw situatie vraagt, stem je af met je QSA.
Wil je weten of jouw checkout klaar is voor een strikte CSP? Wij testen het met je mee en lossen de blokkades direct op. Neem contact op via /contact of bekijk onze aanpak voor Magento security.

Geschreven door Ruthger Idema
15+ jaar ervaring in e-commerce development. Gespecialiseerd in Magento, Shopify en Laravel maatwerk.
Meer over ons team →


