AI QA Monkey
AI Security Intelligence
Fix Guide

Security Headers Guide: CSP, HSTS, X-Frame-Options & More

HTTP security headers are your first line of defense against common web attacks. They instruct browsers to enable built-in security features that protect your users from clickjacking, XSS, protocol downgrade attacks, and data leakage — all with zero performance cost.

Despite being free and easy to implement, over 70% of websites are missing critical security headers. In our analysis of 50,000+ scans on AI QA Monkey, the most commonly missing headers were Content-Security-Policy (82% missing), Permissions-Policy (78% missing), and HSTS (45% missing).

Why Security Headers Matter

Security headers protect against specific attack categories:

  • Content-Security-Policy: Prevents XSS, data injection, clickjacking
  • Strict-Transport-Security: Prevents protocol downgrade and cookie hijacking
  • X-Frame-Options: Prevents clickjacking attacks
  • X-Content-Type-Options: Prevents MIME-type sniffing attacks
  • Referrer-Policy: Controls information leakage via Referer header
  • Permissions-Policy: Restricts browser feature access (camera, mic, geolocation)

They're also increasingly important for compliance. PCI DSS 4.0, ISO 27001, and SOC 2 all reference security headers as expected controls.

Content-Security-Policy (CSP) CRITICAL

CSP is the most powerful security header. It tells the browser exactly which resources are allowed to load, effectively preventing XSS attacks even if an attacker finds an injection point.

CSP Directives Explained

# CSP Directive Reference
Content-Security-Policy:
  default-src 'self';                    # Fallback for all resource types
  script-src 'self' https://cdn.js.com;  # JavaScript sources
  style-src 'self' 'unsafe-inline';      # CSS sources
  img-src 'self' data: https:;           # Image sources
  font-src 'self' https://fonts.gstatic.com;  # Font sources
  connect-src 'self' https://api.example.com;  # AJAX/fetch/WebSocket
  frame-src 'none';                      # iframe sources
  object-src 'none';                     # Flash/Java (always 'none')
  base-uri 'self';                       # Restrict <base> tag
  form-action 'self';                    # Form submission targets
  frame-ancestors 'self';                # Who can iframe this page
  upgrade-insecure-requests;             # Auto-upgrade HTTP to HTTPS

CSP Implementation Strategy

  1. Start with Report-Only mode: Use Content-Security-Policy-Report-Only to log violations without blocking
  2. Audit your resources: Check browser console for CSP violations
  3. Tighten gradually: Remove 'unsafe-inline' and 'unsafe-eval' once you've refactored inline scripts
  4. Use nonces for inline scripts: script-src 'nonce-randomValue123' allows specific inline scripts

Starter CSP (Practical)

# A practical CSP that works for most websites
Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net https://www.googletagmanager.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://www.google-analytics.com; frame-src 'none'; object-src 'none'; base-uri 'self'; form-action 'self';

Strict-Transport-Security (HSTS) CRITICAL

HSTS forces browsers to always use HTTPS, preventing protocol downgrade attacks and cookie hijacking on public WiFi networks.

# Recommended HSTS configuration
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload

# Parameters:
# max-age=31536000  — Remember for 1 year (in seconds)
# includeSubDomains — Apply to all subdomains
# preload           — Submit to browser preload list (permanent HTTPS)
Warning: HSTS Preload Is Permanent

Once you add preload and submit to hstspreload.org, your domain will be hardcoded into browsers to always use HTTPS. This is very difficult to undo. Only add preload when you're 100% certain all subdomains support HTTPS.

X-Frame-Options HIGH

Prevents your site from being embedded in iframes on other domains — the primary defense against clickjacking attacks.

# Options:
X-Frame-Options: DENY          # No framing allowed at all
X-Frame-Options: SAMEORIGIN    # Only same-origin framing (recommended)

# Note: CSP's frame-ancestors directive is the modern replacement
# Use both for backward compatibility

X-Content-Type-Options HIGH

Prevents browsers from MIME-sniffing a response away from the declared content type, blocking attacks where an attacker uploads a file disguised as an image but containing JavaScript.

# Only one valid value
X-Content-Type-Options: nosniff

Referrer-Policy MEDIUM

Controls how much referrer information is sent when navigating away from your site. Prevents leaking sensitive URL parameters (tokens, session IDs) to third-party sites.

# Recommended: Send origin only, not full URL path
Referrer-Policy: strict-origin-when-cross-origin

# Options (from most to least restrictive):
# no-referrer                    — Never send referrer
# same-origin                    — Only for same-origin requests
# strict-origin-when-cross-origin — Origin only for cross-origin (recommended)
# origin-when-cross-origin       — Full URL for same-origin, origin for cross-origin
# no-referrer-when-downgrade     — Don't send on HTTPS→HTTP

Permissions-Policy MEDIUM

Controls which browser features (camera, microphone, geolocation, payment) your site and embedded iframes can use.

# Disable all sensitive features (recommended for most sites)
Permissions-Policy: camera=(), microphone=(), geolocation=(), payment=(self), usb=(), magnetometer=(), gyroscope=(), accelerometer=()

# If you need specific features:
Permissions-Policy: camera=(self), microphone=(self), geolocation=(self "https://maps.google.com")

Complete Configuration

Apache (.htaccess)

# Complete Security Headers — Apache
<IfModule mod_headers.c>
  # Prevent XSS and data injection
  Header always set Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net https://www.googletagmanager.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://www.google-analytics.com; frame-src 'none'; object-src 'none'; base-uri 'self'; form-action 'self';"

  # Force HTTPS
  Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"

  # Prevent clickjacking
  Header always set X-Frame-Options "SAMEORIGIN"

  # Prevent MIME sniffing
  Header always set X-Content-Type-Options "nosniff"

  # Control referrer information
  Header always set Referrer-Policy "strict-origin-when-cross-origin"

  # Restrict browser features
  Header always set Permissions-Policy "camera=(), microphone=(), geolocation=(), payment=(self)"

  # Remove server information
  Header always unset X-Powered-By
  Header always unset Server
</IfModule>

Nginx

# Complete Security Headers — Nginx
# Add to server {} block

add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net https://www.googletagmanager.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://www.google-analytics.com; frame-src 'none'; object-src 'none'; base-uri 'self'; form-action 'self';" always;

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=(), payment=(self)" always;

# Hide server version
server_tokens off;

Testing Your Headers

# View all response headers
curl -I https://yourdomain.com

# Check specific headers
curl -sI https://yourdomain.com | grep -iE "(content-security|strict-transport|x-frame|x-content-type|referrer-policy|permissions-policy)"

For a comprehensive check, use AI QA Monkey's free security scanner — it tests all security headers and provides specific fix commands for missing or misconfigured headers.

Check Your Security Headers

Free scan — tests all HTTP security headers and provides copy-paste fix commands.

Scan Your Headers Now

Frequently Asked Questions

What are HTTP security headers?

HTTP security headers are response headers that instruct browsers to enable security features. They protect against clickjacking, XSS, protocol downgrade attacks, MIME sniffing, and information leakage — all with zero performance cost.

What is Content-Security-Policy (CSP)?

CSP controls which resources the browser is allowed to load. A properly configured CSP prevents XSS attacks by blocking inline scripts and unauthorized external resources.

How do I add security headers on Apache?

Add Header always set directives to your .htaccess file. See the complete Apache configuration above for all recommended headers.

How do I test my security headers?

Use AI QA Monkey's free security scanner for a comprehensive check with copy-paste fix commands, or run curl -I https://yourdomain.com to view headers manually. The scanner checks all 10 recommended headers and flags missing or misconfigured ones.

Check Your Website Right Now

Run a free automated security scan — 75 checks in 60 seconds. No signup required.

Run Free Security Scan →