HTTP Security Headers: What Most Sites Are Missing and How to Fix It
Security headers most sites are missing, what HSTS, CSP, and X-Frame-Options actually prevent, how Cache-Control directives work, and which headers reveal server information you should hide in production.
By sadiqbd Β· June 8, 2026
HTTP response headers are a diagnostic layer most developers rarely inspect β until something is wrong
A page loads correctly. Users can browse it. Then a security researcher files a report: missing Content-Security-Policy, no HSTS, X-Content-Type-Options absent. Or a caching bug surfaces: CloudFront is serving stale content but the Cache-Control headers say max-age=0. Or a redirect loop runs for three hops because each hop added its own Location header.
Response headers carry more operational and security information than most front-end developers ever look at. Inspecting them directly β on any URL, without digging through server config β reveals configuration problems that aren't visible from the page itself.
Security headers: what's missing from most sites
Browser security features are mostly opt-in β servers have to explicitly enable them through response headers. Without them, browsers apply permissive defaults that leave known attack vectors open.
Strict-Transport-Security (HSTS)
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
Once a browser receives this header over HTTPS, it refuses to connect to the same origin over plain HTTP for max-age seconds (31,536,000 = one year). This prevents SSL stripping attacks, where an attacker downgrades an HTTPS connection to HTTP.
Without HSTS: a user who types example.com in their browser first connects over HTTP. An attacker on the same network can intercept and manipulate this before the HTTPS redirect happens. With HSTS, the browser enforces HTTPS directly after the first visit.
The preload directive submits the domain to browsers' built-in HSTS preload lists β the browser enforces HTTPS even on the first visit. To be preloaded, you must also set includeSubDomains and have max-age of at least one year. Submit at hstspreload.org.
Content-Security-Policy (CSP)
Content-Security-Policy: default-src 'self'; script-src 'self' 'nonce-xyz'; img-src 'self' data:
CSP defines which sources are permitted for various resource types: scripts, styles, images, fonts, frames, and more. It's the primary defence against Cross-Site Scripting (XSS) β if an attacker injects a script tag, CSP prevents the browser from loading it (unless the source matches the policy).
CSP is the hardest security header to implement correctly because it requires knowing every legitimate resource source. Start in report-only mode:
Content-Security-Policy-Report-Only: default-src 'self'; report-uri /csp-violations
Violations are reported but not blocked. After analysing reports and refining the policy, switch to enforcing mode.
Common CSP directives:
default-srcβ fallback for all resource typesscript-srcβ JavaScript sourcesstyle-srcβ CSS sourcesimg-srcβ image sourcesconnect-srcβ fetch/XHR/WebSocket URLsframe-ancestorsβ which origins can embed this page (replaces X-Frame-Options)
X-Frame-Options
X-Frame-Options: DENY
Prevents the page from being embedded in an iframe. Protects against clickjacking β attacks where a malicious page overlays an invisible iframe over something else.
DENY β never allow framing.
SAMEORIGIN β allow framing only from the same origin.
Note: CSP's frame-ancestors directive provides more granular control and supersedes X-Frame-Options in modern browsers. Set both for compatibility.
X-Content-Type-Options
X-Content-Type-Options: nosniff
Prevents the browser from MIME-sniffing a response away from the declared Content-Type. Without this, a browser might execute a file served as text/plain as JavaScript if it looks like JavaScript. nosniff forces strict adherence to Content-Type.
Referrer-Policy
Referrer-Policy: strict-origin-when-cross-origin
Controls how much referrer information is sent with navigation requests. The default no-referrer-when-downgrade sends full URLs when navigating between HTTPS sites β meaning the destination site receives the full URL you navigated from, including any query parameters (which may contain sensitive data).
strict-origin-when-cross-origin β sends only the origin (not the path or query) for cross-origin requests. A good default for most sites.
no-referrer β sends nothing. Maximum privacy but breaks analytics attribution for cross-site referrals.
Permissions-Policy (formerly Feature-Policy)
Permissions-Policy: camera=(), microphone=(), geolocation=(self)
Restricts which browser features the page (and embedded iframes) can use. Disabling camera, microphone, and geolocation by default on pages that don't need them reduces the attack surface if XSS occurs.
Caching headers: what controls browser and CDN caching
Cache-Control
Cache-Control: public, max-age=31536000, immutable
Cache-Control: no-store
Cache-Control: no-cache, must-revalidate
The primary caching directive:
publicβ cacheable by browsers and CDNsprivateβ cacheable by browser only, not CDNmax-age=Nβ cache for N secondsno-storeβ don't cache at all (use for sensitive data)no-cacheβ cache but revalidate before using (sends conditional request)immutableβ the content at this URL will never change; skip revalidation even within max-agemust-revalidateβ once max-age expires, must revalidate before serving stale
Practical strategy: static assets with content-hashed filenames (e.g. app.a7f3bc.js) can use max-age=31536000, immutable since the URL changes when content changes. HTML files should use no-cache to ensure fresh content on each visit.
ETag and Last-Modified
ETag: "33a64df5-1234"
Last-Modified: Tue, 10 Jun 2024 09:00:00 GMT
Validation headers: when the browser's cached copy expires, it sends If-None-Match: <etag> or If-Modified-Since: <date>. If content hasn't changed, the server returns 304 Not Modified with no body β saving bandwidth while ensuring freshness.
Diagnostic headers to look for
Server
Server: Apache/2.4.51
Server: nginx/1.25.0
Reveals the web server software and version. This is a security information disclosure issue β knowing the exact server version helps attackers target known CVEs. Production servers should either omit the Server header or use a generic value (Server: Apache without version).
X-Powered-By
X-Powered-By: PHP/8.2.0
X-Powered-By: Express
Similar problem β version disclosure. Remove from production. In PHP: expose_php = Off in php.ini. In Express: app.disable('x-powered-by') or use Helmet middleware.
Via
Via: 1.1 cloudfront.amazonaws.com (CloudFront)
Reveals proxy and CDN intermediaries. Useful for debugging caching β confirms traffic is going through the CDN as expected.
CF-Cache-Status (Cloudflare)
CF-Cache-Status: HIT
CF-Cache-Status: MISS
CF-Cache-Status: EXPIRED
Cloudflare-specific header showing whether the response was served from cache. HIT = cached; MISS = not cached, fetched from origin; EXPIRED = cache expired, freshly fetched.
How to use the HTTP Headers Checker on sadiqbd.com
- Enter the URL β any public URL
- Fetch headers β the tool makes an HTTP request and returns all response headers
- Review:
- Security headers present/absent
- Cache-Control values
- Server software disclosure
- HSTS configuration
- Any unusual or custom headers
Useful for auditing your own sites, debugging CDN caching, or investigating third-party service headers.
Frequently Asked Questions
Do security headers affect SEO? Not directly β search engines don't use them as ranking signals. But HTTPS (enforced by HSTS) is a ranking factor, and security headers reduce the risk of XSS attacks that could inject spam content or redirect links that would harm your search presence.
What's the fastest way to add security headers?
If using Cloudflare: Transform Rules can inject security headers without touching server config. On nginx: add headers in the server block. On Apache: use Header always set. Vercel, Netlify, and similar platforms have header configuration in their project settings.
How do I test CSP without breaking my site?
Use Content-Security-Policy-Report-Only with a report endpoint. All violations are logged but not blocked. Analyse the logs for a week or two to identify all legitimate sources before switching to enforcement mode.
Is the HTTP Headers Checker free? Yes β completely free, no sign-up required.
Response headers are the server's metadata layer β configuring them correctly takes an hour and prevents classes of attacks that would otherwise require significantly more work to mitigate at the application level.
Try the HTTP Headers Checker free at sadiqbd.com β inspect all response headers for any URL instantly, without browser tools or curl.