Test je headers nu op securityheaders.com. Vul je domein in en kijk naar de score. Bij de meeste WordPress-sites die ik onder ogen krijg, staat er een D of een F. Niet omdat de site onveilig is, maar omdat er nooit iemand naar de headers heeft gekeken.
Dit artikel laat zien hoe je WordPress security headers correct instelt. Welke headers het belangrijkst zijn, hoe je ze toevoegt via .htaccess of Nginx, en waar het conflict ontstaat met page builders zoals Elementor of Bricks. Met code-snippets die je direct kunt gebruiken.
Ik werk vanuit Terneuzen aan onderhoud en hardening van bestaande sites. Headers zijn een quick win: in een uur van een F naar een A, zonder de site te raken. Mits je weet wat je doet.

Waarom security headers ertoe doen
Security headers zijn HTTP-headers die de browser instructies geven over hoe hij met je site moet omgaan. Welke scripts mogen laden, of de site in een iframe mag, hoe de verbinding moet zijn. Ze worden door de webserver meegestuurd bij elk response.
De belangrijkste werken preventief. Een goed ingestelde Content-Security-Policy blokkeert kwaadaardige scripts die via een XSS-lek binnenkomen. HSTS dwingt HTTPS af, ook bij typfouten. X-Frame-Options voorkomt clickjacking via een iframe.
Voor wie meer wil weten over het onderliggende model, staat een uitstekend overzicht in de MDN-documentatie over HTTP-headers. Voor de praktijk: je kunt ze zonder code-wijziging aan je WordPress-site toevoegen, en de winst is direct meetbaar.
De zes headers die je nodig hebt
In de praktijk gaat het om zes headers. Niet meer, niet minder.
Strict-Transport-Security (HSTS). Dwingt de browser om alleen via HTTPS te verbinden. Voorkomt downgrade-aanvallen en SSL-stripping.
Content-Security-Policy (CSP). Bepaalt welke bronnen (scripts, stijlen, afbeeldingen) mogen laden. De krachtigste header, ook de lastigste om goed in te stellen.
X-Frame-Options. Voorkomt dat je site in een iframe op een andere site wordt geladen. Bescherming tegen clickjacking.
X-Content-Type-Options. Zet nosniff-modus aan zodat de browser geen MIME-types raadt. Voorkomt dat een geüploade afbeelding als script wordt uitgevoerd.
Referrer-Policy. Bepaalt hoeveel informatie je site meestuurt bij links naar externe sites. Een privacy-instelling.
Permissions-Policy. Beperkt welke browser-features (camera, microfoon, geolocatie) je site mag aanroepen.
X-XSS-Protection laat ik bewust weg. Moderne browsers ondersteunen die niet meer, en de officiële aanbeveling is om hem niet meer te gebruiken.
.htaccess-snippet voor Apache en LiteSpeed
De meeste WordPress-sites draaien op Apache of LiteSpeed. Beide ondersteunen .htaccess. Onderstaand snippet gaat boven of onder het bestaande WordPress-blok in het .htaccess-bestand in de root van de site.
apache
<IfModule mod_headers.c>
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
Header always set X-Frame-Options "SAMEORIGIN"
Header always set X-Content-Type-Options "nosniff"
Header always set Referrer-Policy "strict-origin-when-cross-origin"
Header always set Permissions-Policy "camera=(), microphone=(), geolocation=()"
Header always set Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' data:; connect-src 'self'; frame-ancestors 'self';"
</IfModule>Belangrijk: maak eerst een back-up van je .htaccess. Een tikfout maakt je site onbereikbaar. Voor wat de directives precies betekenen, staat documentatie op de Apache mod_headers-pagina.
De CSP hierboven is bewust ruim. 'unsafe-inline' en 'unsafe-eval' zijn nodig omdat WordPress en de meeste plugins inline scripts en eval gebruiken. Een strikte CSP zonder die twee breekt vrijwel iedere WordPress-site. Daar kom ik bij het stuk over page builders op terug.

Nginx-snippet
Voor sites op Nginx (vaker bij VPS-hosting of beheerd-hosting met Nginx-front) zet je de headers in het server-block van je config:
nginx
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' data:; connect-src 'self'; frame-ancestors 'self';" always;Het always-keyword zorgt ervoor dat de headers ook op foutpagina’s worden meegestuurd. Zonder dat krijg je verschillende scores op verschillende URL’s.
Na het wijzigen van de config: nginx -t om te testen, daarna systemctl reload nginx. Heb je geen SSH-toegang, dan moet de host de wijziging doorvoeren. Bij Hostinger en de meeste shared-hosters kun je via het paneel een set headers instellen, of een ondersteuningstickets indienen.
CSP en page builders: waar het misgaat
Content-Security-Policy is de moeilijkste header in WordPress. Niet omdat de techniek complex is, maar omdat WordPress en zijn ecosysteem inline scripts overal gebruiken.
In de praktijk loop ik tegen drie soorten conflicten aan.
Page builders (Elementor, Bricks, Divi). Deze tools injecteren inline styles en scripts bij elke pagina-render. Een strikte style-src 'self' zonder 'unsafe-inline' breakt direct de visuele weergave. Oplossing: 'unsafe-inline' voor styles toelaten, of nonces gebruiken (dat werkt niet betrouwbaar met page builders).
Externe scripts en fonts. Google Fonts, Google Analytics, een chat-widget. Elk externe script vereist een aparte script-src– of connect-src-vermelding. Vergeet er één en de functionaliteit valt uit zonder duidelijke fout.
Admin-area. De WordPress admin gebruikt eval() en inline scripts intensief. Een te strikte CSP maakt het backend onbruikbaar. Daarom geef ik vaak een lossere CSP voor /wp-admin/ en een striktere voor de frontend.
Hoe los ik dit op? Begin met een ruime CSP, zoals in de snippets hierboven. Test elke pagina van de site. Kijk in de browser-console (DevTools, tab Console) naar Content Security Policy warnings. Voeg externe bronnen toe waar nodig.
Voor sites met een chat-widget of Google Analytics ziet de script-src er vaak zo uit:
script-src 'self' 'unsafe-inline' 'unsafe-eval' https://www.googletagmanager.com https://www.google-analytics.com;Dit is geen perfecte CSP, het is een werkbare CSP. Een zuiverder beleid met nonces vereist code-aanpassingen in het thema. Voor de meeste MKB-sites is dat overkill.

HSTS en de preload list
HSTS is bijzonder omdat je hem kunt aanmelden bij de browsers zelf. Eenmaal op de HSTS preload list, weet elke moderne browser dat je domein verplicht HTTPS gebruikt, zelfs bij het allereerste bezoek.
Voor inclusie op de preload list moet de header er als volgt uitzien:
Strict-Transport-Security: max-age=63072000; includeSubDomains; preloadVoorwaarden:
max-ageminimaal 31536000 seconden (één jaar), aanbevolen 63072000 (twee jaar)includeSubDomainsdirectief aanwezigpreloaddirectief aanwezig- Het domein moet via HTTPS bereikbaar zijn, ook alle subdomeinen
Pas op met includeSubDomains. Heb je een subdomein dat nog op HTTP draait (bijvoorbeeld een oud staging-domein), dan wordt dat onbereikbaar zodra je in de preload list staat. Verwijdering uit de list duurt weken. Dit is geen actie die je terugdraait op een vrijdagmiddag.
Ik raad de preload list aan voor sites die over de hele linie op HTTPS draaien en geen losse subdomeinen meer hebben. Voor sites met veel legacy-subdomeinen: alleen de HSTS-header zonder preload is al voldoende voor een goede score.
Testen en verifiëren
Na het instellen, drie checks die ik standaard draai.
securityheaders.com. Geeft een rating van A+ tot F en wijst aan welke headers ontbreken. Streef naar A of A+ voor de frontend.
Browser DevTools. Open de site, F12, tab Network, klik op de hoofdpagina-request, kijk onder Response Headers. Hier zie je per URL welke headers actief zijn.
Mozilla Observatory. Geeft een uitgebreidere analyse inclusief TLS-configuratie. Een tweede mening naast securityheaders.com.
Op staging eerst testen, daarna live zetten. Bij twijfel: rol terug door het toegevoegde blok in .htaccess weg te halen. Een ongelukkige header kan een live site bruikbaar maken voor bezoekers, maar onbruikbaar voor wp-admin of formulieren.
Wat ik regel op een onderhoudscontract
Voor klanten met een WordPress onderhoudscontract horen security headers bij de standaard-setup. Bij de start van een contract loop ik de huidige score na en stel ik de headers in die ontbreken. Geen extra kosten, gewoon onderdeel van het werk.
Bij Onderhoud Basis (€58 per maand) is dit een eenmalige inrichting bij de start. Onderhoud Plus (€175 per maand) krijgt er een periodieke hercontrole bovenop, omdat plugins die externe scripts laden de CSP soms breken bij een update.
Geen 24/7-support. Spoedwerk reken ik tegen €105 per uur. Standaard uurtarief is €70. Migratie en serverwerk valt onder €95 per uur, omdat een verkeerde header-instelling een site offline kan halen en zorgvuldigheid extra tijd kost.
Heb je een F-score op securityheaders.com en wil je er een A van maken? Stuur me je URL en welke page builder of plugins je gebruikt. Ik kijk ernaar en mail terug. Meer artikelen staan in de categorie website beveiliging.



