Back to Learning Center
SaaS Security

HTTP Security Headers: The Complete Implementation Guide

12 min read
Updated May 2026By CertNotify Team

HTTP security headers are response headers that instruct browsers on how to handle your site's content. They are one of the most cost-effective security improvements you can make — a few lines of server configuration that mitigate entire classes of attacks like XSS, clickjacking, and protocol downgrade attacks. This guide covers every major security header with real configuration examples.

1. Strict-Transport-Security (HSTS)

HSTS tells browsers to always use HTTPS for your domain — even if the user types http://. This prevents SSL-stripping attacks, where an attacker downgrades your HTTPS connection to HTTP.

# Minimal (start here for testing)
Strict-Transport-Security: max-age=300

# Production recommended
Strict-Transport-Security: max-age=31536000; includeSubDomains

# Maximum security (HSTS preload — irreversible without removal process)
Strict-Transport-Security: max-age=63072000; includeSubDomains; preload

includeSubDomains

Applies HSTS to all subdomains. Only add if ALL subdomains support HTTPS.

preload

Hardcodes your domain into browsers. Requires hstspreload.org submission. Very hard to undo.

2. Content-Security-Policy (CSP)

CSP is the most powerful security header, but also the most complex. It defines which sources are allowed to load scripts, styles, images, fonts, and other resources. A strict CSP prevents most XSS attacks — even if an attacker injects malicious code, the browser refuses to execute it if it violates the policy.

# Restrictive policy (start here, then loosen as needed)
Content-Security-Policy:
  default-src 'self';
  script-src 'self' https://cdn.trusted.com;
  style-src 'self' 'unsafe-inline' https://fonts.googleapis.com;
  font-src 'self' https://fonts.gstatic.com;
  img-src 'self' data: https:;
  connect-src 'self' https://api.yourdomain.com;
  frame-ancestors 'none';
  base-uri 'self';
  form-action 'self';

# Report-only mode (test without breaking things)
Content-Security-Policy-Report-Only:
  default-src 'self';
  report-uri /csp-report-endpoint

Start with Content-Security-Policy-Report-Only to identify violations without breaking your site. Use a service like Report URI to collect and analyse violation reports.

3. X-Frame-Options

Prevents your site from being embedded in <iframe>, <frame>, or <object> elements on other sites. This stops clickjacking attacks where an attacker overlays your site invisibly to trick users into clicking on hidden elements.

X-Frame-Options: DENY           # Never allow framing
X-Frame-Options: SAMEORIGIN     # Allow framing only by same origin

Note: CSP's frame-ancestors directive is the modern replacement and provides more granular control. Set both for maximum compatibility.

4. X-Content-Type-Options

Prevents browsers from MIME-sniffing the content type of responses. Without this header, a browser might interpret a text file as JavaScript if it looks like script code — a vector for content injection attacks.

X-Content-Type-Options: nosniff

This is a zero-risk header — add it to every site unconditionally.

5. Referrer-Policy

Controls how much referrer information is sent when navigating from your site to external URLs. Without a policy, browsers may leak the full URL (including query parameters with tokens or search terms) in the Referer header.

# Recommended: send origin only for cross-origin requests
Referrer-Policy: strict-origin-when-cross-origin

# Maximum privacy: never send referrer information
Referrer-Policy: no-referrer

6. Permissions-Policy

Controls which browser features and APIs your site can use — and prevents third-party iframes from accessing them. Replaces the older Feature-Policy header.

# Disable unnecessary browser APIs
Permissions-Policy:
  camera=(),
  microphone=(),
  geolocation=(),
  interest-cohort=(),
  payment=(self)

Complete Server Configuration Examples

# Nginx — complete security headers block

# In your server {} block:
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Frame-Options "SAMEORIGIN" 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 Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self'; frame-ancestors 'self'; base-uri 'self';" always;

# Next.js — next.config.js security headers

const securityHeaders = [
  { key: 'Strict-Transport-Security', value: 'max-age=31536000; includeSubDomains' },
  { key: 'X-Frame-Options', value: 'SAMEORIGIN' },
  { key: 'X-Content-Type-Options', value: 'nosniff' },
  { key: 'Referrer-Policy', value: 'strict-origin-when-cross-origin' },
  { key: 'Permissions-Policy', value: 'camera=(), microphone=(), geolocation=()' },
];

module.exports = {
  async headers() {
    return [{ source: '/(.*)', headers: securityHeaders }];
  },
};

Security Header Grading Reference

HeaderPriorityRisk if Missing
Strict-Transport-SecurityCriticalSSL stripping, protocol downgrade attacks
Content-Security-PolicyCriticalXSS, data injection attacks
X-Frame-OptionsHighClickjacking attacks
X-Content-Type-OptionsHighMIME sniffing, drive-by downloads
Referrer-PolicyMediumInformation leakage to third parties
Permissions-PolicyMediumUnauthorised API access from third-party frames

Test your security headers instantly

Our Security Headers checker scans any URL and gives you a grade, missing headers, and specific fix recommendations — in under 3 seconds.

Scan your security headers →