WordPress security headers configureren: A+ zonder brekage

Van F naar A+ op securityheaders.com zonder dat de admin, popup of checkout stuk gaat. Report-Only eerst, per hostingpaneel, met exacte syntax.

· 10 september, 2026 · 17 min lezen
In het kort
  • WordPress security headers configureren lukt zonder brekage als je de CSP eerst in Report-Only zet en hem pas na twee weken violation-logs afdwingt.
  • De weg van F naar A+ loopt in zeven stappen: baseline meten, Report-Only aanzetten, logs verzamelen, policy schrijven, enforcen en opnieuw scannen.
  • Zet de headers op serverniveau in .htaccess, nginx of Cloudflare Transform Rules, want daar overleven ze een plugin die je .htaccess herschrijft.
  • De grootste valkuil is direct enforcen: CSP blokkeert dan de inline scripts van wp-admin en Gutenberg, en dan zit je zelf buiten je eigen beheer.
In dit artikel

WordPress security headers configureren is een klus die er op papier simpel uitziet, maar in de praktijk verraderlijk is. Een klant uit Middelburg mailde me vorige maand: securityheaders.com gaf een F, en in Google Search Console verscheen een waarschuwing over ontbrekende Content-Security-Policy.

Zijn vorige “WordPress hardening”-script had zomaar een strenge CSP toegevoegd. Gutenberg-blocks en Google Tag Manager laadden niet meer, en de admin was voor de helft wit. We hebben het teruggedraaid en opnieuw opgebouwd, in Report-Only, met precisie.

Reken voor een volledige, veilige implementatie op 2 tot 4 uur werk. Spreid dat over 1 tot 2 weken, zodat je genoeg CSP-violation-logs verzamelt. In dit stuk lees je hoe ik dat systematisch doe, met exacte syntax per hostingpaneel en concrete workarounds voor de plekken waar het meestal misgaat.

WordPress security headers configureren A+ scan

WordPress security headers configureren: de vijf must-haves

Voordat je iets configureert, wil je begrijpen wat elke header oplost. Security headers zijn korte HTTP-response-instructies die de browser vertellen wat er wel en niet mag op jouw pagina. Ze compenseren voor kwetsbaarheden in themes, plugins en third-party scripts. Het OWASP Secure Headers Project publiceert de canonieke baseline, en die is in 2026 nog altijd de referentie voor productiesites.

De vijf headers die ik in elke WordPress-implementatie neerzet:

  1. Content-Security-Policy (CSP). Blokkeert cross-site scripting (XSS) en data-injection door precies te definiëren welke scripts, stijlen, images en frames de browser mag laden. Dit is verreweg de krachtigste header en tegelijk degene die het vaakst dingen breekt.
  2. X-Frame-Options. Voorkomt dat andere sites jouw pagina in een iframe embedden voor clickjacking-aanvallen. In moderne setups vervangt CSP’s frame-ancestors-directive deze header, maar veel oudere browsers (en scanning tools) verwachten hem nog. Ik zet beide.
  3. X-Content-Type-Options: nosniff. Blokkeert MIME-sniffing, waarbij de browser probeert te “raden” wat een bestand is. Zonder deze header kan een geüpload .txt-bestand met JavaScript-inhoud alsnog als script uitgevoerd worden. Er is maar één juiste waarde: nosniff.
  4. Referrer-Policy. Bepaalt hoeveel URL-informatie meegaat wanneer een bezoeker via een link jouw site verlaat. Zonder policy lekt de volledige URL (inclusief sessie-tokens in queryparameters) naar externe partijen.
  5. Permissions-Policy. Deze vervangt de oude Feature-Policy. Hij regelt welke browser-APIs (camera, microfoon, geolocatie, USB, payment) een pagina mag aanspreken. Voor een reguliere WordPress-site zet je vrijwel alles uit. Zie de MDN Permissions-Policy referentie voor de actuele directive-lijst.

HSTS (Strict-Transport-Security) hoort er ook bij, maar dat is een apart hoofdstuk met eigen preload-lijst en voorwaarden. Daar heb ik een aparte gids voor HSTS Preload op WordPress.

Vergelijkingstabel: syntax per header

HeaderFunctieSimpel syntaxAdvanced syntax
Content-Security-PolicyBlokkeert XSS en injectiedefault-src 'self'default-src 'self'; script-src 'self' 'nonce-{random}' https://www.googletagmanager.com; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; img-src 'self' data: https:; font-src 'self' https://fonts.gstatic.com; frame-ancestors 'self'; report-to csp-endpoint
X-Frame-OptionsClickjacking-preventieSAMEORIGINDENY (als je site nooit in eigen iframes hoeft)
X-Content-Type-OptionsMIME-sniffing blokkerennosniffn/a (één geldige waarde)
Referrer-PolicyPrivacylek beperkenstrict-origin-when-cross-originno-referrer-when-downgrade (marketing-vriendelijker) of no-referrer (strengst)
Permissions-PolicyCamera/mic/geo/USB gatecamera=(), microphone=(), geolocation=()camera=(), microphone=(), geolocation=(self), payment=(self "https://checkout.mollie.com"), interest-cohort=()

De keuze tussen “simpel” en “advanced” hangt af van je stack. Een brochuresite zonder formulieren komt weg met de simpele varianten. Een WooCommerce-site met Mollie, GTM en Elementor Pro heeft de advanced kolom nodig om A+ te halen zonder brekage.

Bouw je WordPress security headers-config

Kies je headers en platform. Je krijgt direct een kopieerbaar startconfig met waarschuwingen voor HSTS en CSP.

1. Kies je headers

De vijf basisheaders staan alvast aan. Permissions-Policy is optioneel.

Headers opnemen
2. Kies je platform
5 headers geselecteerd Apache-config met Header always set.
3. Jouw headers-config

Controleer bestaande headers eerst. Dubbele regels kunnen onverwachte uitkomsten geven.

Volgende stap Voeg dit toe op staging, controleer de response headers en bekijk eerst de CSP-rapporten.
Test bij Security Headers

Een startpunt, geen kant-en-klare productieconfig. Test elke wijziging en controleer de site voordat je CSP enforcement aanzet.

De 7-stap roadmap: van F naar A+ zonder brokstukken

Dit is de volgorde die ik altijd aanhoud. Doe geen enkele stap over of door elkaar.

  1. Baseline meten (5 minuten). Ga naar securityheaders.com, voer je domein in, screenshot de F- of D-score. Doe direct daarna een tweede scan op Mozilla Observatory. Twee referentiepunten, want ze wegen headers net anders.
  2. Report-Only mode inschakelen (15 minuten). Voeg alle vijf headers toe, maar de CSP als Content-Security-Policy-Report-Only. In deze mode blokkeert de browser niks; hij stuurt alleen rapportages over wat er geblokkeerd zou zijn. Zo zie je de brekage aankomen zonder impact op bezoekers.
  3. Logs verzamelen 1 tot 2 weken. Laat de site draaien. Verzamel de violation-reports via een report-endpoint (report-uri.com heeft een gratis tier) of via een simpel eigen PHP-endpoint dat naar een logbestand schrijft.
  4. Analyseer de violations. Filter op unieke blocked-uri. Meestal zie je 5 tot 20 unieke domains die je onbedoeld blokkeert: Google Fonts, GTM, Facebook Pixel, YouTube-embed, Stripe, Mollie, je CDN. Elk hoort in de policy of moet weg.
  5. Custom CSP schrijven met specifieke domains. Bouw je policy op basis van de logs. Toets hem tegen Google's CSP Evaluator. Die tool markeert onveilige patronen zoals 'unsafe-inline' zonder nonce, of te brede wildcards.
  6. Report-Only naar Enforce switchen. Verander de header-naam van Content-Security-Policy-Report-Only naar Content-Security-Policy. Vanaf dat moment blokkeert de browser echt. Doe dit buiten kantooruren, en houd de eerste 24 uur violation-logs strak in de gaten.
  7. Post-implementation verify (10 minuten). Nieuwe scan op securityheaders.com. Als je alle vijf headers goed hebt en HSTS eronder, staat er A of A+. Screenshot als bewijsstuk voor je klant of voor je jaarrapport.

Rush geen enkele stap. Ik heb sites gezien die op stap 6 in vier uur alle inline JavaScript van Gutenberg blokkeerden, waardoor de editor voor redacteuren onbruikbaar werd. De Report-Only-fase van 1 tot 2 weken bestaat juist om dat te voorkomen.

Per hostingpaneel: waar zet je de headers neer

De headers moeten op server- of platformniveau. In principe kan het ook via een WordPress plugin (zie verderop), maar server-level is stabieler omdat je headers dan ook stuurt bij statische bestanden en 404's.

Overzicht per paneel

PaneelConfiguratielocatieBestand of UIReload nodig
cPanel (Apache/LiteSpeed)Document root van de site.htaccessNee (direct actief)
PleskDomain settingsApache & nginx Settings → Additional nginx directivesAuto-reload nginx
DirectAdminPer-domein config templatecustom_httpd.conf of .htaccessApache/LiteSpeed restart
Hostinger hPanelFile Manager.htaccess in public_htmlNee
CloudflareDashboardRules → Transform Rules → Response HeaderNee (paar seconden)
RunCloud/GridPaneWeb application settingsNginx custom configAuto-reload nginx
WordPress fallbackSite zelfmu-plugins/security-headers.phpNee

cPanel .htaccess (Antagonist, Vimexx, Hostnet, Argeweb)

cPanel-hostings draaien meestal Apache of LiteSpeed. Beide lezen .htaccess.

  1. Log in op cPanel → File Manager.
  2. Navigeer naar public_html/ (of de subfolder van je site).
  3. Open .htaccess. Als hij verborgen is: rechtsboven Settings → "Show Hidden Files" aanvinken.
  4. Voeg dit blok toe boven de # BEGIN WordPress-regel:
<IfModule mod_headers.c>
    # De vier veilige headers direct enforce
    Header always set X-Content-Type-Options "nosniff"
    Header always set X-Frame-Options "SAMEORIGIN"
    Header always set Referrer-Policy "strict-origin-when-cross-origin"
    Header always set Permissions-Policy "camera=(), microphone=(), geolocation=(self)"

    # CSP eerst als Report-Only voor 2 weken
    Header always set Content-Security-Policy-Report-Only "default-src 'self'; script-src 'self' 'unsafe-inline' https://www.googletagmanager.com https://www.google-analytics.com; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; font-src 'self' https://fonts.gstatic.com; img-src 'self' data: https:; frame-ancestors 'self'; report-uri /csp-endpoint.php"
</IfModule>
  1. Bewaar en refresh de site.
  2. Test met curl -I https://jouwsite.nl in een terminal, of gebruik https://securityheaders.com. Je moet alle vijf headers in de respons zien.

Plesk Additional nginx directives (TransIP zakelijk, Combell)

Plesk zet nginx voor Apache als reverse-proxy. Headers zet je in het Plesk-panel zelf, dan wordt nginx opnieuw geladen.

  1. Domains → jouwsite.nl → Apache & nginx Settings.
  2. Scroll naar Additional nginx directives.
  3. Plak in:
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "camera=(), microphone=(), geolocation=(self)" always;
add_header Content-Security-Policy-Report-Only "default-src 'self'; script-src 'self' 'unsafe-inline' https://www.googletagmanager.com; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; img-src 'self' data: https:; report-uri /csp-endpoint.php" always;
  1. Apply onderaan de pagina. Plesk herlaadt nginx automatisch.
  2. Test opnieuw via securityheaders.com.

Let op: de always-parameter is belangrijk. Zonder hem stuurt nginx de header niet mee bij 4xx/5xx-responses, wat op securityheaders.com tot puntenverlies leidt bij deep scans.

DirectAdmin custom_httpd (Neostrada, Argeweb-oud)

DirectAdmin gebruikt template-bestanden voor Apache/OpenLiteSpeed. Voor per-domein overrides zet je een custom_httpd config aan.

  1. SSH-toegang aanvragen bij je hoster, of via Advanced Features → File Manager in DirectAdmin.
  2. Navigeer naar /usr/local/directadmin/data/users/{gebruikersnaam}/domains/{domein}.conf/.
  3. Maak (of open) custom_httpd.conf voor de VirtualHost en voeg toe:
<IfModule mod_headers.c>
    Header always set X-Content-Type-Options "nosniff"
    Header always set X-Frame-Options "SAMEORIGIN"
    Header always set Referrer-Policy "strict-origin-when-cross-origin"
    Header always set Permissions-Policy "camera=(), microphone=(), geolocation=(self)"
    Header always set Content-Security-Policy-Report-Only "default-src 'self'; report-uri /csp-endpoint.php"
</IfModule>
  1. Rebuild de config: directadmin --build all (root-only). Of via DirectAdmin: Server Manager → Custom HTTPD Configurations → Save.
  2. Herstart Apache/LiteSpeed via het paneel.

Als je géén SSH hebt op DirectAdmin, gebruik dan de .htaccess-route zoals bij cPanel. DirectAdmin ondersteunt dat ook.

Cloudflare Transform Rules → Rewrite Response Headers

Als je site achter Cloudflare zit, is dit de simpelste plek. Je hoeft niks op je server aan te passen, en je kunt regels per URL-patroon maken (bijvoorbeeld strengere CSP voor /wp-admin/* uit).

  1. Log in op Cloudflare dashboard → kies je zone.
  2. Rules → Overview → Create rule → Response Header Transform Rule.
  3. Rule name: "Security headers baseline".
  4. When incoming requests match: kies "All incoming requests" (of filter op hostname als je meerdere zones hebt).
  5. Then: klik Modify response header → Operation: Set static → Header name en Value invullen. Voeg voor elk van de vijf headers een aparte "Modify" toe.
  • Set: X-Content-Type-Options = nosniff.
  • Set: X-Frame-Options = SAMEORIGIN.
  • Set: Referrer-Policy = strict-origin-when-cross-origin.
  • Set: Permissions-Policy = camera=(), microphone=(), geolocation=(self).
  • Set: Content-Security-Policy-Report-Only = je policy-string.
  1. Deploy. Werkt binnen enkele seconden globaal.

Cloudflare heeft daarnaast Managed Transforms onder Rules → Managed Transforms met een "Add security headers"-preset. Handig voor snel starten, maar je hebt geen controle over de CSP. Zelf schrijven blijft aan te raden. Zie de Cloudflare docs voor Response Header Transform Rules voor de meest actuele UI.

WP-CLI + functions.php als noodoplossing

Als je géén server-toegang hebt en geen Cloudflare, kun je headers via WordPress zelf sturen. Nadeel: alleen bij PHP-responses, dus niet bij statische assets of 404's van niet-WordPress-bestanden. Toch werkt het voor de meeste scanners.

Voeg toe aan wp-content/themes/{child-theme}/functions.php, of nog beter, in een mu-plugins/security-headers.php:

<?php
add_action('send_headers', function() {
    if (!headers_sent()) {
        header('X-Content-Type-Options: nosniff');
        header('X-Frame-Options: SAMEORIGIN');
        header('Referrer-Policy: strict-origin-when-cross-origin');
        header('Permissions-Policy: camera=(), microphone=(), geolocation=(self)');
        header("Content-Security-Policy-Report-Only: default-src 'self'; script-src 'self' 'unsafe-inline' https://www.googletagmanager.com; report-uri /csp-endpoint.php");
    }
});

Deployen via WP-CLI vanaf je lokale machine (of via SSH):

# Bevestig dat de mu-plugin actief is
wp plugin list --status=must-use

# Test dat de header binnenkomt
wp eval 'wp_remote_get(home_url()); print_r(wp_remote_retrieve_headers(wp_remote_get(home_url())));'

Voor productie is dit de minst nette oplossing. Server-level of Cloudflare heeft mijn voorkeur. De WordPress-route is prima voor development of als tijdelijke fix terwijl je op je hoster wacht.

Cloudflare Transform Rules met vijf headers

Wat breekt CSP het vaakst (en hoe je het fixt)

CSP breekt vaak omdat WordPress zwaar leunt op inline styles en inline scripts. Daar komen de third-party CDN's van het ecosysteem nog bij. Onderstaande tabel toont de patronen die ik 90% van de tijd tegenkom.

ElementWaarom breekt CSPFix
Inline <script> in header/footerZonder 'unsafe-inline' of 'nonce-' blokkeert de browser elk <script>...</script>-blok zonder externe srcVoeg 'unsafe-inline' toe (zwak) of implementeer nonces via wp_get_script_tag()-filter (sterk)
Google Fontsfonts.googleapis.com (CSS) en fonts.gstatic.com (WOFF) zijn twee aparte domainsstyle-src 'self' https://fonts.googleapis.com; font-src 'self' https://fonts.gstatic.com
Google Tag ManagerGTM injecteert extra scripts runtime van variabele hostnamesscript-src 'self' 'unsafe-inline' https://www.googletagmanager.com https://www.google-analytics.com; connect-src 'self' https://www.google-analytics.com https://analytics.google.com
Google AdSenseAds laden via ep2.adtrafficquality.google en andere subdomainsscript-src 'self' https://pagead2.googlesyndication.com https://*.googlesyndication.com; frame-src https://googleads.g.doubleclick.net
Gutenberg blocks met inline stylesBlock-editor injecteert style="..." attributes op elementenstyle-src 'self' 'unsafe-inline' blijft nodig totdat WP core nonces uitrolt (Core issue #57381)
YouTube embedyoutube.com/embed/* iframesframe-src https://www.youtube.com https://www.youtube-nocookie.com
Mollie/Stripe checkoutPayment iframes en JSscript-src ... https://js.stripe.com https://www.mollie.com; frame-src https://js.stripe.com https://www.mollie.com

Elke keer dat je een nieuwe integratie toevoegt (nieuwsbrief-widget, chatbot, webinar-tool), scan je opnieuw en verleng je de policy. Dat is de reden dat CSP een levend document is en geen one-shot config.

Drie concrete scenario's uit de praktijk

Scenario A: A+ score halen zonder Cloudflare

Klant in Terneuzen met een simpele brochuresite op Antagonist. Geen CDN, geen GTM, alleen Google Fonts en een Contact Form 7-formulier.

Aanpak:

  1. cPanel → .htaccess → vijf headers toevoegen. CSP eerst Report-Only.
  2. Report-Only twee weken laten draaien. Enige violation was Google Fonts (verwacht).
  3. CSP naar enforce, met default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; font-src 'self' https://fonts.gstatic.com; img-src 'self' data:; frame-ancestors 'self'.
  4. HSTS al aan sinds de SSL-uitrol vorig jaar.
  5. Eindresultaat: A+ op securityheaders.com. Doorlooptijd 2,5 uur verspreid over 15 dagen.

Scenario B: WordPress admin-toolbar breekt na CSP enable

Bij een webshop in Hulst na de Report-Only-naar-Enforce switch: de zwarte toolbar bovenaan wp-admin renderde niet meer, plus de Gutenberg-editor toonde alleen een spinner.

Diagnose: In browserconsole: Refused to execute inline script because it violates the following Content Security Policy directive: "script-src 'self'". WordPress core injecteert honderden inline scripts in de admin.

Fix: Uitzondering voor /wp-admin/*. In .htaccess:

<IfModule mod_headers.c>
    # Standaard strenge CSP
    Header always set Content-Security-Policy "default-src 'self'; script-src 'self'"

    # Ruimere CSP alleen voor wp-admin
    <If "%{REQUEST_URI} =~ m#^/wp-admin/#">
        Header always set Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'"
    </If>
</IfModule>

Voor Cloudflare-users: maak een tweede Transform Rule met filter URI Path starts with /wp-admin/ en een lossere CSP-waarde. Frontend blijft streng, admin blijft werken.

Scenario C: Elementor of WPBakery inline styles versus CSP

Elementor Pro-site met een strenge policy: style-src 'self' (zonder 'unsafe-inline'). Resultaat: alle Elementor-widgets kwijt hun styling. Pagina's zagen eruit als 1998.

Waarom: Elementor genereert per-widget inline styles op <div style="..."> attributen. Nonces werken niet voor style-attributes, alleen voor <style>-tags. In 2026 is er nog geen structurele fix in Elementor core.

Workaround:

  1. style-src 'self' 'unsafe-inline' accepteren als tijdelijk realiteit. Je verliest 5 punten op securityheaders.com maar Elementor werkt.
  2. Óf: alle Elementor-styling laten "regenerate CSS files" (Elementor → Tools → Regenerate Files & Data). Zorgt dat globals en widget-styles in externe .css-bestanden komen. Vermindert inline styles met 60 tot 80%, maar niet compleet.
  3. Voor A+ ambitie: overschakelen naar een block-based theme (Twenty Twenty-Five, Kadence) waar inline styles minder voorkomen.

Ik ben in de praktijk pragmatisch: op een e-commerce site levert Elementor omzet op, dus 'unsafe-inline' voor styles blijft. Voor scripts blijf ik streng.

Testing tools: welke gebruik je waarvoor

ToolDoelURL
securityheaders.comSnelle grade (F tot A+), gewogen scoring per headersecurityheaders.com
Google CSP EvaluatorDiepte-analyse van je CSP-string, spot bypassescsp-evaluator.withgoogle.com
Mozilla ObservatoryGrondige check inclusief cookie-attributes en SRIobservatory.mozilla.org
HardenizeTLS + headers + DNS-security in één rapporthardenize.com
Browser DevTools → ConsoleLive violation-messages tijdens ontwikkelingF12 → Console-tab
curl -IRuwe respons-headers uit een terminalcurl -I https://jouwsite.nl

Draai deze niet één keer maar bouw ze in in je maandelijkse audit. Ik heb een simpele cron met curl -I die de headers naar een logbestand schrijft en me mailt als er iets is weggevallen.

Voor en na: wat het scheelt in scores

Header ingesteldsecurityheaders.comMozilla Observatory
Geen (default WordPress)F (0/130)F (0/100)
Alleen X-Content-Type-Options + X-Frame-OptionsD (35)D (40)
Vier headers zonder CSPC (65)C (55)
Vier headers + CSP Report-OnlyB (80)B (70)
Vijf headers + CSP enforce + HSTSA (105)A (85)
Vijf headers + CSP enforce + HSTS Preload + COOP/COEPA+ (120+)A+ (100+)

Merk op dat A+ op Mozilla Observatory strenger scoort dan securityheaders.com. Als je op beide A+ wilt, komt Cross-Origin-Opener-Policy en Cross-Origin-Embedder-Policy erbij. Dat is werk voor een advanced sessie, buiten deze baseline.

Alternatief: security headers via een plugin

Voor MKB'ers zonder server-toegang bestaan er WordPress-plugins die dit werk overnemen. In mijn praktijk gebruik ik ze zelden omdat server-level altijd stabieler is, maar de goede zijn:

  • HTTP Headers plugin op WordPress.org: gratis, actief onderhouden (release april 2026). Alle headers configureerbaar via UI. Nadeel: geen intelligentie over CSP, je moet zelf weten wat je typt.
  • Really Simple Security Pro: betaald (rond €50/jaar single site). Pro-versie genereert automatisch een WordPress-tailored CSP en biedt Report-Only mode als switch. Combineert met firewall, 2FA en HSTS-preload configuratie. Voor MKB-klanten die één plugin willen die alles regelt: dit is de rustigste keuze.
  • Wordfence kan geen headers zetten. Wordfence is een WAF en malware-scanner. Verwar deze scopes niet.

Voor kleinere sites (bijvoorbeeld een lokale ondernemer in Zeeuws-Vlaanderen die zelf onderhoudt) adviseer ik Really Simple Security Pro. Voor sites die ik zelf beheer: server-level, altijd.

A+ scanresultaat op smartphone

Preventie: headers behouden na updates

Ik heb sites gezien waar na een WordPress core-update ineens de headers weg waren. Oorzaak: een plugin-update herschreef .htaccess en gooide het -blok eruit. Dit voorkom je met een monitoring-workflow.

  1. Zet headers waar plugins niet aankomen. Op cPanel: leg de header-config in /etc/apache2/conf.d/userdata/ (root only, via je hoster). Op Plesk: in de nginx additional directives (die overleeft plugin-updates). Op Cloudflare: sowieso safe, plugin kan er niet bij.
  2. Maandelijkse header-scan als recurring task. Schrijf een simpele cron:
#!/bin/bash
# /usr/local/bin/check-headers.sh
HEADERS=$(curl -sI https://jouwsite.nl)
for H in "X-Content-Type-Options" "X-Frame-Options" "Referrer-Policy" "Permissions-Policy" "Content-Security-Policy"; do
    if ! echo "$HEADERS" | grep -qi "$H"; then
        echo "MISSING: $H on jouwsite.nl" | mail -s "Security header alert" jij@jouwsite.nl
    fi
done

Zet deze in crontab -e als 0 9 1 * * (elke eerste van de maand 9:00).

  1. Na elke major WP-update: securityheaders.com opnieuw draaien. Neem 5 minuten. Als de score gedaald is, direct kijken wat er weg is.
  2. Documenteer je CSP in git. Ik houd voor elke klant een csp-history.md bij met de policy per datum en de reden van elke wijziging. Bij een violation-onderzoek weet ik precies wanneer we https://cdn.mailchimp.com hebben toegevoegd.
  3. Vervolg-workflow voor nieuwe integraties. Nieuwe chatwidget installeren? Eerst Report-Only mode aanzetten voor 3 dagen, violations bekijken, dán de policy uitbreiden en enforce herstellen.

Wanneer een webmaster inschakelen

Doe dit zelf als je een klein tot middelgrote site hebt met max 10 third-party integraties en toegang tot .htaccess of Cloudflare. De roadmap kost je 2 tot 4 uur werk verspreid over 2 weken en je leert ontzettend veel over je eigen stack.

In deze gevallen bel je beter iemand in.

  • Je draait een WooCommerce-site met veel externe payment providers, marketing pixels en headless integraties.
  • Je hebt een strikte compliance-eis (bijvoorbeeld ISO 27001 of NEN 7510 in de zorg) en documentatie nodig.
  • Report-Only-logs laten 500+ unieke violations per dag zien en je weet niet welke legitiem zijn.
  • Je admin zit al stuk door een eerdere te snelle enforce-poging.

In mijn praktijk kost een volledige security-header-implementatie voor een MKB-site 2 tot 4 uur (€140 tot €280). Daarin zit 1 tot 2 weken monitoring en een lever-document met de policy-tekst en verantwoording per directive. Voor Elementor- of WooCommerce-sites met veel plugins reken 4 tot 6 uur.

Vast door je headers?

Zit je in een Report-Only-log te staren zonder te weten welke violation legitiem is, of is je site na een enforce-switch half stuk? Stuur me een mail via /contact/. Ik kijk binnen 4 uur mee tijdens kantoortijden, factuur alleen de daadwerkelijk bestede tijd (€70/uur), en lever een gedocumenteerde CSP-policy die je aan je hoster of compliance-auditor kunt overhandigen. Zeeuws-Vlaanderen of remote: voor headers maakt de locatie niks uit.

Serhii Lypii
Wat je krijgt

Loop je vast met beveiliging?

Stuur me een mail via /contact/. Binnen 24 uur reactie tijdens kantooruren.

Contact
Vond je dit nuttig? Deel het:
FAQ

Veelgestelde vragen

Is de HTTP Headers plugin genoeg?
Voor een simpele brochuresite ja, mits je zelf een correcte CSP kunt formuleren. Voor GTM, WooCommerce of Elementor krijg je dezelfde CSP-problemen als bij server-level. De plugin scheelt je alleen server-toegang, niet het denkwerk.
Betekent een A+ score op securityheaders.com dat mijn site veilig is?
Nee. Het betekent dat je HTTP-headers correct staan. Je site kan alsnog kwetsbaar zijn voor SQL-injection, brute-force of verouderde plugins. Zie A+ als één laagje in defense-in-depth naast WAF, updates, backups en 2FA.
Wat als CSP mijn admin breekt en ik kan er niet meer in?
Open je .htaccess via FTP of File Manager. Comment de Content-Security-Policy-regel uit met # en save. Zit de header in je nginx-config of functions.php? Dan doe je daar hetzelfde. Refresh admin. Terugdraaien is 60 seconden werk, geen database-issue.
Hoe zie ik in DevTools welke CSP-violations er precies zijn?
F12 → Console-tabblad. Elke violation verschijnt rood en noemt de geblokkeerde URL. Een typisch voorbeeld is Refused to load the script 'https://example.com/x.js' because it violates the following Content Security Policy directive: "script-src 'self'". De melding vertelt precies welke directive te streng is en welke URL toegevoegd moet.
HSTS heb ik al ingesteld, hoort dat hier ook bij?
HSTS is de zesde header uit de OWASP-baseline en telt zwaar voor A+. Ik behandel HSTS-preload apart omdat de submission bij hstspreload.org een eigen risico-analyse verdient. Zie mijn gids over HSTS Preload voor WordPress MKB.
Serhii Lypii
Over de auteur

Serhii Lypii

Freelance webmaster · Terneuzen

Sinds 2012 werk ik met websites en leverde ik ruim 210 projecten op. Ik help mkb-ondernemers met onderhoud, snelheid, beveiliging en praktische automatisering. Nuchter, zonder hype.

Ik schreef dit artikel op en werkte het voor het laatst bij op .

Meer over Lypii
Even sparren over je site?

Loop je ergens tegenaan of twijfel je over je site? Ik denk graag mee. Kies hieronder hoe je contact opneemt.

Reactie binnen 4 uur op werkdagen
Navigatie
Home Over mij Kennisbank
Contact
+31 6 39 56 93 03 serhii@lypii.nl WhatsApp
Stuur een bericht