How this check works
Scanaris requests your home page the way a browser would and reads the response headers. It looks for six specific headers and, for each one missing, opens a finding with a recommended value: Content-Security-Policy, Strict-Transport-Security and X-Frame-Options at medium severity, and X-Content-Type-Options, Referrer-Policy and Permissions-Policy at low severity. It does not judge the quality of the CSP or the HSTS here: that is done by the weak CSP and weak HSTS checks. Only the response of the scanned URL is inspected, so if your API lives on another domain, scan it separately.
What each header protects
- Content-Security-Policy limits where scripts, styles and images may be loaded from. It is the main defence against script injection (XSS).
- Strict-Transport-Security forces the browser to always use HTTPS with your domain, even if someone types the address without the s.
- X-Frame-Options stops your site from being embedded in someone else's iframe, which is the basis of clickjacking.
- X-Content-Type-Options: nosniff prevents the browser from "guessing" a file's type and running as a script something that was not one.
- Referrer-Policy controls how much of the URL is sent to other sites when a user clicks a link.
- Permissions-Policy disables browser APIs you do not use, such as camera, microphone or geolocation.
How to add them depending on your hosting
Vercel
In vercel.json, or in next.config with the headers() function if you use Next.js:
{
"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
A _headers file in the folder that gets published:
/*
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, inside routeRules, the '/**' rule with a headers object and the same key-value pairs. It is exactly what Scanaris does.
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;
The Content-Security-Policy is left out of the examples on purpose: it depends on which scripts and services your site loads and is best started in report-only mode. The procedure is in HTTP security headers explained for humans.
Check they are there
curl -sI https://yourdomain.com | grep -iE "strict-transport|x-frame|x-content-type|referrer-policy|permissions-policy|content-security"
All six lines should appear. If you have a CDN in front of the server, check on the public URL, because some CDNs strip or overwrite headers. The headers analyzer does the same reading with an explanation per header.
Frequently asked questions
X-Frame-Options or frame-ancestors?
Both do the same job; frame-ancestors inside the CSP is the modern version and lets you list specific domains. Keep X-Frame-Options as well for older browsers; they do not conflict.
Can adding these headers break my site?
The five in the examples break nothing on a normal site. The only risky one is the CSP, which is why it is added as Content-Security-Policy-Report-Only first and switched to enforcing once the reports are clean.
Do I need preload on HSTS?
Not to pass the check. preload lets you include your domain in the list browsers ship with; it is a long-term commitment (your whole domain and subdomains on HTTPS forever), so enable it only when you are sure.