HTTP Security Headers Explained:CSP, HSTS and More
The HTTP security headers worth setting (HSTS, Content-Security-Policy, X-Content-Type-Options, Referrer-Policy, Permissions-Policy and frame protection), what each prevents and how to roll them out safely.

Table of Contents
- The headers at a glance
- Strict-Transport-Security (HSTS)
- Content-Security-Policy (CSP)
- X-Content-Type-Options
- Referrer-Policy
- Permissions-Policy
- Clickjacking protection
- Where to set headers
- How to check
- Example: setting headers on Apache, LiteSpeed and Nginx
- Rolling out CSP on a WordPress site
- Frequently Asked Questions
- Related reading
- Sources
HTTP security headers are instructions a website sends to the browser that turn on built-in protections: forcing HTTPS, restricting which scripts can run, stopping the page being framed by other sites, and limiting what information and features are exposed. The most useful are Strict-Transport-Security (HSTS), Content-Security-Policy (CSP), X-Content-Type-Options, Referrer-Policy, Permissions-Policy, and frame protection (frame-ancestors in CSP, or X-Frame-Options).
They cost little to add, but some (HSTS and CSP especially) need careful rollout to avoid breaking the site.
The headers at a glance
| Header | Protects against | Typical value |
|---|---|---|
Strict-Transport-Security |
Downgrade to HTTP, cookie theft over HTTP | max-age=31536000; includeSubDomains |
Content-Security-Policy |
Cross-site scripting, content injection, clickjacking | A policy listing allowed sources |
X-Content-Type-Options |
MIME-type sniffing attacks | nosniff |
Referrer-Policy |
Leaking full URLs to other sites | strict-origin-when-cross-origin |
Permissions-Policy |
Unwanted access to camera, microphone, location and other features | camera=(), microphone=(), geolocation=() |
X-Frame-Options / CSP frame-ancestors |
Clickjacking (your page framed by another site) | DENY / frame-ancestors 'none' |
Strict-Transport-Security (HSTS)
HSTS tells browsers to use HTTPS for your domain for a period, even if someone types http:// or follows an HTTP link.
Roll out carefully:
- Make sure the whole site, and every subdomain if you use
includeSubDomains, works over HTTPS. - Start with a short
max-age(for example 300 seconds), then increase it gradually to a year. - Consider the
preloadlist only when you are certain, because removal takes a long time.
See what is SSL/TLS and how does HTTPS work.
Content-Security-Policy (CSP)
CSP lists where scripts, styles, images, fonts, frames and connections may come from. If an attacker injects a script, the browser refuses to run it unless it matches the policy. A simple starting policy:
Content-Security-Policy: default-src 'self'; img-src 'self' data: https:; script-src 'self'; style-src 'self' 'unsafe-inline'; frame-ancestors 'none'; base-uri 'self'; form-action 'self'
Real sites usually need to allow analytics, payment providers, fonts and other third parties. Practical advice:
- Start with
Content-Security-Policy-Report-Onlyto see what would be blocked without breaking anything. - Avoid
'unsafe-inline'and'unsafe-eval'for scripts where possible; use nonces or hashes for inline scripts. - Add sources deliberately, not with wildcards like
*. - Tighten the policy step by step.
X-Content-Type-Options
nosniff stops browsers from guessing a file's type and, for example, executing an uploaded text file as a script. It is safe to enable everywhere.
Referrer-Policy
Controls how much of the current URL is sent when a visitor follows a link to another site. strict-origin-when-cross-origin sends only the origin to other sites over HTTPS and keeps full paths (which may contain identifiers) private. It is also the default in modern browsers.
Permissions-Policy
Disables browser features your site does not use, such as camera, microphone or geolocation, reducing what injected or third-party code could abuse.
Clickjacking protection
Stop other sites from loading your pages inside a frame to trick users into clicking: use CSP frame-ancestors 'none' (or 'self'), and X-Frame-Options: DENY for older browsers.
Where to set headers
- Web server configuration (Apache, Nginx, LiteSpeed) or
.htaccesson shared hosting. - Your application or framework, which can set headers per response (useful for CSP nonces).
- A CDN or proxy, which can add headers at the edge.
Avoid setting the same header in two places with different values.
How to check
Use your browser's developer tools (Network tab → response headers) or an online header scanner, and test important pages after every change.
Example: setting headers on Apache, LiteSpeed and Nginx
Apache or LiteSpeed (.htaccess or server configuration), with mod_headers:
<IfModule mod_headers.c>
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
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 X-Frame-Options "DENY"
</IfModule>
Nginx (inside the server block):
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" 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 X-Frame-Options "DENY" always;
Note that in Nginx, add_header directives in a location block replace those inherited from the server block, so headers can silently disappear on some paths. Check several URLs after configuring.
Add the Content-Security-Policy separately, starting in report-only mode, because it needs tailoring to each site.
Rolling out CSP on a WordPress site
- Start with
Content-Security-Policy-Report-Onlyand a basic policy. - Browse the site, including admin and checkout, and read the console reports.
- Add the sources the site genuinely needs: analytics, payment providers, fonts, embedded videos.
- Keep inline scripts to a minimum; many plugins add them, which is the main obstacle to a strict policy.
- Switch to the enforcing header once reports are clean, and keep monitoring.
For WordPress hardening beyond headers, see the WordPress security checklist, and for the bigger picture of protecting applications, OWASP Top 10 explained.
Frequently Asked Questions
Can security headers break my site?
HSTS and CSP can, if rolled out too aggressively. Use report-only mode for CSP and short HSTS durations at first.
Is X-XSS-Protection still useful?
No. Modern browsers have removed the old XSS filter it controlled; use CSP instead.
Do headers replace secure coding?
No. They limit damage when something goes wrong; validating input and escaping output remain essential.
Related reading
Headers are part of secure configuration in website security basics. For applications built with security in mind, see ServerNeed custom web development.
Sources
Last updated 7 October 2026



