Hoe deze controle werkt
Scanaris vraagt je homepage op zoals een browser dat zou doen en leest de headers van het antwoord. Het zoekt zes specifieke headers en opent voor elke ontbrekende een bevinding met een aanbevolen waarde: Content-Security-Policy, Strict-Transport-Security en X-Frame-Options met gemiddelde ernst, en X-Content-Type-Options, Referrer-Policy en Permissions-Policy met lage ernst. De kwaliteit van de CSP of de HSTS wordt hier niet beoordeeld: dat doen de controles zwakke CSP en zwakke HSTS. Alleen het antwoord van de gescande URL wordt bekeken, dus als je API op een ander domein leeft, scan die dan apart.
Wat elke header beschermt
- Content-Security-Policy beperkt waar scripts, stijlen en afbeeldingen vandaan mogen komen. Het is de belangrijkste verdediging tegen scriptinjectie (XSS).
- Strict-Transport-Security dwingt de browser om altijd HTTPS te gebruiken met je domein, ook als iemand het adres zonder de s typt.
- X-Frame-Options voorkomt dat je site in een vreemde iframe wordt ingebed, de basis van clickjacking.
- X-Content-Type-Options: nosniff voorkomt dat de browser het type van een bestand "raadt" en iets als script uitvoert dat dat niet was.
- Referrer-Policy bepaalt hoeveel van de URL naar andere sites gaat wanneer een gebruiker op een link klikt.
- Permissions-Policy schakelt browser-API's uit die je niet gebruikt, zoals camera, microfoon of locatie.
Hoe je ze toevoegt, afhankelijk van je hosting
Vercel
In vercel.json, of in next.config met de functie headers() als je Next.js gebruikt:
{
"headers": [
{
"source": "/(.*)",
"headers": [
{ "key": "Strict-Transport-Security", "value": "max-age=63072000; includeSubDomains; preload" },
{ "key": "X-Frame-Options", "value": "DENY" },
{ "key": "X-Content-Type-Options", "value": "nosniff" },
{ "key": "Referrer-Policy", "value": "strict-origin-when-cross-origin" },
{ "key": "Permissions-Policy", "value": "camera=(), microphone=(), geolocation=()" }
]
}
]
}
Netlify
Een bestand _headers in de map die gepubliceerd wordt:
/*
Strict-Transport-Security: max-age=63072000; includeSubDomains; preload
X-Frame-Options: DENY
X-Content-Type-Options: nosniff
Referrer-Policy: strict-origin-when-cross-origin
Permissions-Policy: camera=(), microphone=(), geolocation=()
Nuxt
In nuxt.config, binnen routeRules, de regel '/**' met een headers-object en dezelfde sleutel-waardeparen. Dat is precies wat Scanaris doet.
Express
import helmet from 'helmet';
app.use(helmet());
nginx
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
add_header X-Frame-Options "DENY" 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;
De Content-Security-Policy ontbreekt bewust in de voorbeelden: hij hangt af van welke scripts en diensten je site laadt en start het best in rapportagemodus. De werkwijze staat in HTTP-beveiligingsheaders uitgelegd voor mensen.
Controleer of ze er zijn
curl -sI https://jouwdomein.com | grep -iE "strict-transport|x-frame|x-content-type|referrer-policy|permissions-policy|content-security"
Alle zes regels moeten verschijnen. Heb je een CDN voor de server, controleer dan op de publieke URL, want sommige CDN's verwijderen of overschrijven headers. De headeranalyzer doet dezelfde uitlezing met uitleg per header.
Veelgestelde vragen
X-Frame-Options of frame-ancestors?
Beide doen hetzelfde; frame-ancestors binnen de CSP is de moderne versie en laat je specifieke domeinen opsommen. Houd X-Frame-Options erbij voor oudere browsers; ze zitten elkaar niet in de weg.
Kan ik de site breken door deze headers toe te voegen?
De vijf uit de voorbeelden breken niets op een normale site. De enige met risico is de CSP, daarom wordt die eerst toegevoegd als Content-Security-Policy-Report-Only en pas op blokkeren gezet als de rapporten schoon zijn.
Is preload nodig bij HSTS?
Niet om de controle te halen. preload laat je domein opnemen in de lijst die browsers vanuit de fabriek meekrijgen; het is een verbintenis voor de lange termijn (je hele domein en subdomeinen voorgoed op HTTPS), dus schakel het alleen in als je zeker bent.