Security Headers Checklist: HSTS, X-Frame-Options, and Modern Web Security | SoniNow Blog

Limited TimeLearn More

security headershstscspweb securityhardening

Security Headers Checklist: HSTS, X-Frame-Options, and Modern Web Security

Published

2026-06-23

Read Time

5 mins

Security Headers Checklist: HSTS, X-Frame-Options, and Modern Web Security

HTTP response headers are one of the most cost-effective security investments you can make. A handful of header configurations can prevent clickjacking, MIME-type confusion, referrer leakage, and feature abuse — with zero runtime overhead.

HTTP Strict Transport Security (HSTS)

HSTS forces browsers to communicate exclusively over HTTPS, eliminating the window of vulnerability during the first HTTP request. Without HSTS, an active attacker can downgrade a user's initial connection before the server redirects to HTTPS.

Strict-Transport-Security: max-age=63072000; includeSubDomains; preload

The max-age controls how long the browser remembers to enforce HTTPS — start with 3600 seconds during testing, then increase to 63072000 (two years) for production. includeSubDomains extends enforcement to all subdomains, so verify HTTPS support across every subdomain before enabling it. Submitting to browser preload lists requires a two-year max-age and the preload directive.

X-Frame-Options and Clickjacking Prevention

Clickjacking attacks trick users into interacting with a hidden iframe of your application. Prevent this by controlling whether your pages can be embedded.

X-Frame-Options: DENY
X-Frame-Options: SAMEORIGIN

DENY blocks all embedding. SAMEORIGIN allows embedding on pages from the same origin. frame-ancestors in CSP supersedes X-Frame-Options with more granular control and is supported in modern browsers, but sending both headers ensures coverage for older clients.

# Nginx — both headers for maximum compatibility
add_header X-Frame-Options "SAMEORIGIN" always;
add_header Content-Security-Policy "frame-ancestors 'self'" always;

X-Content-Type-Options

Browsers have historically performed MIME-type sniffing on resources, which can lead to security issues when a script is served with an incorrect MIME type. This header stops MIME sniffing entirely.

X-Content-Type-Options: nosniff

When this header is set, the browser trusts the Content-Type header and refuses to load resources if the declared type doesn't match usage. For example, a CSS file served as text/plain will not be loaded as a stylesheet, preventing MIME confusion attacks. This header should be sent on every response without exception.

Referrer-Policy

The Referrer-Policy header controls how much referrer information is included with requests leaving your application. This has direct implications for user privacy and the leakage of sensitive URL parameters.

Referrer-Policy: strict-origin-when-cross-origin

This recommended setting sends the full URL as referrer for same-origin requests, sends only the origin for cross-origin requests, and sends no referrer when navigating from HTTPS to HTTP. Consider no-referrer for authentication or payment pages where URL parameters may contain session tokens or transaction IDs.

Permissions-Policy (formerly Feature-Policy)

Permissions-Policy controls which browser features and APIs your application and its embedded content can access. This limits the blast radius if an XSS vulnerability allows an attacker to call sensitive APIs.

Permissions-Policy: camera=(), microphone=(), geolocation=(self "https://maps.example.com"),
  payment=(self), accelerometer=(), gyroscope=(), magnetometer=(),
  usb=(), midi=()

Each directive specifies which origins are granted access to the feature. An empty parentheses () blocks the feature entirely. Grant features only to the origins that genuinely need them — a content site does not need camera access, and a blog page does not need USB access.

X-XSS-Protection

The X-XSS-Protection header controlled the now-deprecated Internet Explorer and legacy Edge XSS filter. Modern browsers have removed or disabled this feature in favor of CSP. Setting X-XSS-Protection: 0 is recommended to avoid inconsistencies with CSP in aging browsers, but the header is largely irrelevant for modern web applications.

Cache-Control for Sensitive Pages

For pages containing sensitive information — account settings, payment history, admin interfaces — instruct browsers and proxies not to cache the response:

Cache-Control: no-store, no-cache, must-revalidate
Cache-Control: private
Pragma: no-cache

Authentication tokens, API keys, and user profile data should never be stored in the browser cache where other processes or users could access them.

Measuring Your Security Header Score

Deploying headers is only half the work — verifying their effectiveness is the other half. The Mozilla Observatory provides a free, automated scan that grades your application across all major security headers and offers concrete improvement recommendations.

# Using observatory-cli (npm)
npx observatory-cli soninow.com --format json

Security Headers (securityheaders.com) by Probely is another excellent scanner that assigns a letter grade based on your header coverage. Aim for an A+ rating on both platforms.

Automated Header Deployment

Include security headers in your infrastructure-as-code configuration so every deployment is secure by default. Platform-as-a-service environments like Vercel, Netlify, and Railway support headers via configuration files:

{
  "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=()" }
      ]
    }
  ]
}

Putting It All Together

A production-ready set of security headers blocks common attack vectors, prevents data leakage, and reduces your application's attack surface. Implement them systematically, verify with automated scanners, and include them in your deployment pipeline from day one.

Strengthening your application's security posture starts with the basics. Our <a href="/services/web-development">web development services</a> include complete security header configuration as part of every project. Contact SoniNow for a comprehensive security audit.