Security Headers: The 6 That Matter Most (And How to Fix Them)
AIClicks Team · October 9, 2026
Security headers are the closest thing web security has to free lunch. They're HTTP response headers — a few lines of server configuration — that tell browsers how to behave: enforce HTTPS, block clickjacking, restrict which scripts can run. No code changes, no performance cost, no licensing fees.
And yet they remain one of the most neglected layers of web defense. Frameworks don't set them by default, hosting platforms don't ship them, and because missing headers cause no errors or alerts, nobody notices they're absent — until an attack succeeds that a single header would have stopped.
This guide covers the six headers that matter most: what each one protects against, how to verify it's set correctly, and exact configuration snippets for Nginx and Apache you can deploy today. Four of the six carry essentially zero breakage risk; the other two just need a careful rollout.
The 6 headers that matter most
Dozens of security-related headers exist, but six do the heavy lifting for nearly every website: Strict-Transport-Security (HSTS), Content-Security-Policy (CSP), X-Frame-Options (or CSP's frame-ancestors), X-Content-Type-Options, Referrer-Policy, and Permissions-Policy. Together they cover transport security, script execution, framing, content sniffing, referrer leakage, and browser feature access.
Priority order matters. If you deploy nothing else, set HSTS, X-Frame-Options, X-Content-Type-Options, and Referrer-Policy today — they take minutes and break nothing. Add Permissions-Policy next. Tackle CSP last, because it's the most powerful header and the only one that demands a careful rollout.
Below, each header gets the same treatment: what it does, the exact value to set, how to check it, and the mistake that most commonly neuters it.
1. Strict-Transport-Security: enforce HTTPS, always
HSTS tells browsers to only ever connect to your domain over HTTPS, for a duration you specify. It kills SSL-stripping attacks, where an attacker on the network downgrades a victim's connection to plain HTTP to steal credentials or inject content. Without HSTS, your HTTPS site is one hostile Wi-Fi network away from credential theft.
The recommended value: Strict-Transport-Security: max-age=63072000; includeSubDomains; preload. That's two years, applied to all subdomains, with a request to be added to the HSTS preload list built into browsers — which protects even first-time visitors, who otherwise get no HSTS protection on their initial visit.
Three cautions. First, test on staging with a short max-age (300 seconds) before committing to two years in production — once a browser has seen your HSTS header, it will refuse plain HTTP until max-age expires, even if you remove the header. Second, don't add includeSubDomains until every subdomain works over HTTPS; one forgotten internal tool on HTTP becomes unreachable. Third, only add preload after you're fully committed, and submit your domain at the official preload list site.
How to check: curl -sI https://yourdomain.com | grep -i strict — you should see the header with a max-age of at least 31536000 (one year). Anything less is weak; max-age=0 explicitly disables HSTS.
2. Content-Security-Policy: your XSS firewall
CSP is the single most powerful header on this list. It declares which sources are allowed to load scripts, styles, images, fonts, and other resources. A tight CSP makes cross-site scripting (XSS) — still one of the most common web vulnerabilities — dramatically harder to exploit, because even injected scripts won't execute unless they come from an approved source.
A reasonable starting policy for a typical site: Content-Security-Policy: default-src 'self'; script-src 'self'; object-src 'none'; base-uri 'self'; frame-ancestors 'none'. Tighten from there based on what your site actually loads — analytics, CDNs, embedded players each need explicit allowances.
The critical deployment rule: start in report-only mode. Publish the same policy as Content-Security-Policy-Report-Only with a report-uri or report-to directive, run it for a week, and review the violation reports. They'll show you exactly what would break. Then enforce. Teams that skip this step either break their site or — worse — ship a policy full of 'unsafe-inline' that protects nothing.
The most common CSP failure is a policy that allows 'unsafe-inline' and 'unsafe-eval' for scripts while claiming to be secure. If your policy needs those, treat it as a to-do item: refactor inline scripts to external files with nonces or hashes, then remove the unsafe allowances.
3. X-Frame-Options and frame-ancestors: stop clickjacking
Clickjacking overlays your page inside an invisible iframe on an attacker's site, tricking users into clicking buttons they can't see — changing settings, authorizing actions, or revealing information. Framing protections prevent your pages from being embedded elsewhere.
Set X-Frame-Options: DENY — or SAMEORIGIN if you legitimately frame your own pages. The modern replacement is CSP's frame-ancestors directive (frame-ancestors 'none'), which supersedes X-Frame-Options wherever both are present and supports more granular control.
Best practice: set frame-ancestors in your CSP and keep X-Frame-Options: DENY as a fallback for older browsers that don't understand CSP framing directives. The classic mistake is X-Frame-Options: ALLOWALL (or the typo ALLOW-FROM-everywhere patterns) — ALLOWALL is not a valid protective value and leaves you exactly as exposed as having no header at all.
4. X-Content-Type-Options: nosniff, no exceptions
Browsers try to be helpful by 'sniffing' file types — if a file served as text/plain looks like HTML, some browsers will render it as HTML anyway. Attackers exploit this by uploading malicious files (an 'image' that's actually a script) to sites that host user content.
X-Content-Type-Options: nosniff disables sniffing: the browser respects the declared Content-Type, period. There is no valid reason to omit this header and no breakage risk in setting it — provided your server declares correct Content-Types, which it should anyway.
Check it with: curl -sI https://yourdomain.com | grep -i x-content-type — expect exactly 'nosniff'. This is the closest thing to a pure win on the entire list.
5. Referrer-Policy: control what leaks when users click away
Every time a user clicks a link on your site, the browser may send the referring page's URL to the destination — including query strings, which sometimes contain session tokens, password-reset tokens, or private search terms. Referrer-Policy controls how much of that URL is shared.
The sane default for almost every site: Referrer-Policy: strict-origin-when-cross-origin. Same-origin navigations send the full URL (your analytics keep working); cross-origin navigations send only the origin (yourdomain.com, not the full page path). That single setting eliminates the most common referrer-leakage scenarios without breaking anything.
Alternatives for stricter needs: same-origin sends referrers only within your own site; no-referrer sends nothing at all (maximum privacy, but breaks some analytics and affiliate tracking). Avoid the legacy default of sending full URLs cross-origin — that's the behavior you're trying to replace.
6. Permissions-Policy: disable browser features you don't use
Modern browsers expose powerful features to websites: camera, microphone, geolocation, payment APIs, fullscreen, and more. Most sites use none of them — but by default, embedded third-party content (iframes, widgets) can request them.
Permissions-Policy lets you switch features off at the HTTP layer: Permissions-Policy: camera=(), microphone=(), geolocation=(). Empty parentheses mean 'allowed for no one, including my own page.' If you genuinely need geolocation, allow it narrowly: geolocation=(self).
This header is low-risk and increasingly expected in security reviews. Start with camera, microphone, and geolocation disabled; add payment, usb, and fullscreen to the deny list if your site doesn't use them. Review annually as browser features evolve.
Deploying headers: copy-paste configurations
On Nginx, add headers inside your server block. Use the 'always' parameter so headers are also sent on error responses (4xx/5xx), which otherwise ship without them: 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;
On Apache, use the Header directive inside your VirtualHost (requires mod_headers): Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" and likewise for each header. The 'always' keyword matters here for the same reason — without it, headers vanish on error responses.
Behind a CDN or edge platform, you may not need origin changes at all. Cloudflare offers managed security headers and Transform Rules; Vercel supports a headers array in vercel.json; Netlify reads a _headers file at deploy time. Edge configuration is often the fastest path — but verify with curl afterward, because edge rules and origin headers can conflict or duplicate.
CSP goes in the same places, but remember the rollout order: publish as Content-Security-Policy-Report-Only first, collect a week of violation reports, then switch to the enforcing Content-Security-Policy header.
7 mistakes that neuter your headers
One: HSTS with max-age under a year, or max-age=0 — the latter explicitly disables HSTS. Two: includeSubDomains enabled before every subdomain supports HTTPS, which bricks internal tools. Three: X-Frame-Options: ALLOWALL, which is not a protective value. Four: CSPs full of 'unsafe-inline' that look secure in a scanner's presence-check but stop nothing.
Five: forgetting 'always' in Nginx or Apache, so headers disappear on error pages — exactly where attackers probe. Six: setting headers at the origin but having the CDN strip or override them (or vice versa), producing inconsistent protection depending on which edge serves the request. Seven: deploying CSP straight to enforcing mode without a report-only phase, then either breaking the site or panic-adding wildcards that gut the policy.
Every one of these is detectable in seconds with a header check. The fix for most is a one-line config change — which is precisely why headers have the best effort-to-protection ratio in web security.
Verify your headers in 60 seconds
The fastest check is curl: curl -sI https://yourdomain.com | grep -iE 'strict-transport|x-frame|x-content|referrer|permissions-policy|content-security-policy'. Every header above should appear with a sane value. For a deeper read — grading, misconfiguration detection, and exact fix snippets for your server — run a dedicated headers scan.
Make header verification part of your deploy pipeline, not a one-time task. Headers regress silently: a framework upgrade, a new reverse proxy, a CDN config change can strip them without anyone noticing. Scan after every infrastructure change, and set up monitoring that alerts when your header configuration drifts.
How AIClicks helps
Security headers checker
Free check of HSTS, CSP, X-Frame-Options and 10+ more — with exact fix snippets.
Full site scan
Headers are one module of the complete evidence-backed security report.
Threat Radar
Alerts when header configurations change or regress after deploys.
FAQ
Will adding security headers break my site?
Five of the six headers in this guide (HSTS, X-Frame-Options, X-Content-Type-Options, Referrer-Policy, Permissions-Policy) have essentially zero breakage risk with the values given. CSP needs care — deploy in report-only mode first, review violations for a week, then enforce.
Do I need all of these if I already use HTTPS?
Yes. HTTPS without HSTS is vulnerable to SSL stripping on hostile networks. And HTTPS does nothing against clickjacking or XSS — that's what framing and content policies are for.
What's the difference between X-Frame-Options and frame-ancestors?
frame-ancestors (in CSP) is the modern replacement and supersedes X-Frame-Options where both are present. Set frame-ancestors in your CSP; keep X-Frame-Options: DENY as a fallback for older browsers.
How do I check my headers right now?
Run curl -sI against your domain and look for the six headers, or use a free headers checker that grades them and flags misconfigurations — not just absence — with exact fix snippets.
Should I use the HSTS preload list?
Yes, once you're confident your entire domain (including subdomains) works over HTTPS. Preload protects even first-time visitors, who otherwise get no HSTS protection on their initial visit. Test with a short max-age on staging first.
The bottom line
Six headers, a few lines of configuration, protection against entire classes of attacks. Security headers remain one of the rare controls where the effort-to-protection ratio is absurdly favorable — most of the list deploys in minutes with no breakage risk, and the one that needs care (CSP) repays the effort many times over.
Scan your site now, deploy what's missing, and add header verification to your deploy pipeline. The attacks these headers stop aren't theoretical — but neither is the fix.
Check your security headers free
13+ headers tested, misconfigurations flagged, fix snippets included.
Scan my headersMore from the blog
Why Your Website Gets Zero AI Citations (And How to Fix It)
ChatGPT, Perplexity, and Google AI Overviews cite a tiny fraction of the web. Here's how AI citation actually works, why most sites are invisible, and a 30-day plan to change that.
DMARC p=reject: The 10-Minute Setup That Stops Email Spoofing
Anyone can send email 'from' your domain today. DMARC at p=reject fixes that. Here's the exact setup — SPF, DKIM, and DMARC in the right order, without breaking legitimate mail.
How to Write an llms.txt File (Free Generator + Examples)
llms.txt is a markdown file at your domain root that tells AI systems what your site is and which pages matter. Here's the exact spec, a complete annotated example, the five mistakes that make most llms.txt files useless, and a free generator.
