What Are Security Headers? HSTS, CSP and the Rest Explained

Security headers are HTTP response headers that tell the browser how to handle your site safely. The core set is Strict-Transport-Security, Content-Security-Policy, X-Content-Type-Options, a framing control (frame-ancestors or X-Frame-Options), Referrer-Policy and Permissions-Policy. They are a few lines of server configuration and block whole classes of attack.
Every time a browser loads a page, the server sends headers along with the HTML. Most of them describe the content, but a handful tell the browser to enforce extra protections: always use HTTPS, refuse to run scripts from unknown sources, do not let other sites frame the page. Browsers do not turn these on by default, so a site that never sends them misses out. This guide explains each header, gives safe starting values, and shows how to add them on common servers. Check which headers your site sends right now with the free Super Site Report checker.
What are HTTP security headers?
They are standard response headers, defined by web specifications and supported by all modern browsers, that switch on security features for a page. They do not replace secure code. They limit the damage when something goes wrong, for example when a plugin has a cross-site scripting bug or an attacker tries to load your login page in a hidden frame. The OWASP Secure Headers Project maintains the reference list.
Which security headers should every website send?
| Header | What it does | Safe starting value |
|---|---|---|
| Strict-Transport-Security (HSTS) | Forces HTTPS for future visits, even if someone types http:// or follows an old link | max-age=31536000; includeSubDomains |
| Content-Security-Policy (CSP) | Controls which scripts, styles, images and frames the page may load | Start with frame-ancestors 'self'; base-uri 'self'; object-src 'none' and tighten from there |
| X-Content-Type-Options | Stops browsers guessing (sniffing) file types, which can turn an upload into a script | nosniff |
| X-Frame-Options | Older framing control that blocks clickjacking; CSP frame-ancestors supersedes it | SAMEORIGIN |
| Referrer-Policy | Limits how much of the current URL is shared with other sites when visitors click a link | strict-origin-when-cross-origin |
| Permissions-Policy | Turns off browser features the site does not use, such as camera, microphone or geolocation | camera=(), microphone=(), geolocation=() |
What is HSTS and how do you enable it safely?
HTTP Strict Transport Security tells the browser: for the next max-age seconds, only ever contact this site over HTTPS. It closes the gap where a visitor’s first request goes out over plain HTTP and can be intercepted before the redirect. The mechanism is defined in RFC 6797.
Roll it out in steps, because browsers remember the policy:
- Make sure every page and subdomain works over HTTPS with a valid certificate.
- Start with a short value such as
max-age=300and check nothing breaks. - Raise it to one year (
31536000) and addincludeSubDomainsonce every subdomain supports HTTPS. - Only add
preloadand submit to hstspreload.org if you are sure HTTPS will be permanent, since removal from the preload list is slow.
What is a Content-Security-Policy?
A Content-Security-Policy is an allow-list of where a page may load resources from. If an attacker manages to inject a <script> tag pointing at their own server, a strict CSP stops the browser running it. MDN’s CSP guide documents every directive.
A full script-blocking policy needs testing, because analytics, ads, embeds and inline scripts all have to be accounted for. A practical path:
- Start with the low-risk directives.
frame-ancestors 'self'blocks clickjacking,object-src 'none'disables old plugin content, andbase-uri 'self'stops base-tag hijacking. These rarely break anything. - Use report-only mode. Send
Content-Security-Policy-Report-Onlywith a stricter policy and watch the browser console for violations before enforcing it. - Prefer nonces or hashes. The OWASP CSP Cheat Sheet recommends nonce- or hash-based policies over long domain lists.
Do you still need X-Frame-Options?
CSP’s frame-ancestors directive replaces X-Frame-Options in modern browsers, as noted in MDN’s X-Frame-Options reference. Sending both is harmless, and keeps older clients protected. Super Site Report accepts either one as framing protection.
How do you add security headers to your server?
Set headers at the web server or CDN wherever possible, so they apply to every response, including errors and static files.
nginx (inside the server block for HTTPS):
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
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=()" always;
add_header Content-Security-Policy "frame-ancestors 'self'; base-uri 'self'; object-src 'none'" always;
In nginx, add_header in a location block replaces all the headers inherited from the server block. If a location sets its own header, repeat the security headers there or move them to an included snippet.
Apache (.htaccess or virtual host, with mod_headers enabled):
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
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=()"
WordPress: server config is best. If you cannot edit it, use a security plugin that sends headers, or the send_headers action in a small custom plugin. Note that headers set by PHP do not apply to images, CSS and other files served directly by the server.
CDNs: Cloudflare, Fastly and similar services can add response headers through transform or edge rules, which also covers cached responses.
What about cookie security flags?
Cookies are set by a header too (Set-Cookie), and three attributes matter for security, as MDN’s cookie guide explains:
Securesends the cookie only over HTTPS.HttpOnlyhides it from JavaScript, which limits session theft through cross-site scripting.SameSite=Lax(orStrict) stops the cookie being sent on most cross-site requests, which reduces cross-site request forgery.
How do you check which security headers a site sends?
The quickest way is to run Super Site Report. The security section lists every header it found, flags missing or weak values, and gives a fix with the exact line for nginx, Apache or WordPress. You can also check from a terminal:
curl -sI https://example.com/ | grep -iE "strict-transport|content-security|x-content-type|x-frame|referrer-policy|permissions-policy"
Remember to test more than the homepage. Headers set in a single location block or by a plugin often miss other pages, which is why the Super Site Report crawl checks up to 25 pages.
What are COOP, COEP and CORP, and do you need them?
Three newer headers control how your pages and files interact with other origins. Most small sites do not need all three, but it helps to know what they do before a scanner or audit mentions them.
| Header | What it does | Typical value |
|---|---|---|
| Cross-Origin-Opener-Policy (COOP) | Separates your page from windows it opens or that open it, so a cross-origin page cannot keep a reference to it. | same-origin (or same-origin-allow-popups if you use OAuth or payment pop-ups) |
| Cross-Origin-Resource-Policy (CORP) | Tells the browser which origins may embed a resource such as an image, script or file. | same-origin or same-site for private assets; cross-origin for files you serve to other sites |
| Cross-Origin-Embedder-Policy (COEP) | Makes the page load only cross-origin resources that explicitly allow it (via CORP or CORS). | require-corp or credentialless |
Sending COOP same-origin together with COEP puts a page in a “cross-origin isolated” state, which browsers require before they enable powerful features such as SharedArrayBuffer. That is useful for web apps doing heavy computation, but COEP can block third-party images, embeds and ad scripts that do not send CORP or CORS headers. For a typical brochure site, blog or store, a sensible starting point is COOP same-origin-allow-popups and no COEP. Test checkout and sign-in flows after adding COOP, because they often rely on pop-up windows.
Which headers should you remove?
Some headers leak information without adding protection. Removing them does not make a site secure on its own, but it gives attackers less to work with:
Serverwith a full version number (for examplenginx/1.18.0). In nginx,server_tokens off;keeps the product name but drops the version.X-Powered-By, which often reveals the PHP version. Setexpose_php = Offin php.ini.X-XSS-Protection: 1, which enabled a browser feature that has since been removed and could introduce its own problems. Super Site Report flags it as informational.
The OWASP HTTP Headers Cheat Sheet keeps an up-to-date list of headers to add and headers to remove.
Frequently asked questions
Do security headers affect SEO?
They are not a direct ranking factor. HTTPS is part of Google’s page experience guidance, and HSTS helps keep visitors on HTTPS. Headers mainly protect visitors and your reputation, and a hacked site loses search visibility quickly.
Can security headers break my website?
HSTS can lock visitors out of subdomains that do not support HTTPS, and a strict Content-Security-Policy can block scripts you rely on. The other headers in the table above rarely cause problems. Roll out HSTS and CSP gradually as described.
Is X-XSS-Protection still needed?
No. Modern browsers have removed the XSS auditor that this header controlled. OWASP recommends either not sending it or setting it to 0, and relying on a Content-Security-Policy instead.
Should I add security headers with a WordPress plugin or on the server?
The server (nginx, Apache or your CDN) is the better place. Headers set there apply to every response, including images, error pages and files that never touch WordPress. A plugin only adds headers to pages that PHP generates, and caching layers can strip or duplicate them. Use a plugin only when you cannot edit the server or CDN settings.
What grade do security headers get in Super Site Report?
A missing HSTS header and missing clickjacking protection are medium-severity findings in the security category. A missing Content-Security-Policy, X-Content-Type-Options, Referrer-Policy or Permissions-Policy is low severity on its own, but several together add up. The full point values are on the methodology page.
Sources
- MDN Web Docs, Cross-Origin Resource Policy (CORP)
- MDN Web Docs, Window.crossOriginIsolated
- OWASP, Secure Headers Project
- OWASP, HTTP Security Response Headers Cheat Sheet
- OWASP, Content Security Policy Cheat Sheet
- IETF, RFC 6797: HTTP Strict Transport Security
- MDN, Strict-Transport-Security, Content Security Policy, X-Content-Type-Options, Referrer-Policy, Permissions-Policy
- HSTS Preload List Submission


