HTTP security headers are directives sent by your server that instruct browsers on how to behave when handling your site's content. They are among the easiest security improvements to implement — often a single line of configuration — and they protect against a wide range of attacks including XSS, clickjacking, and protocol downgrade attacks. Most missing headers take under 5 minutes to add.

Content-Security-Policy (CSP)

CSP is the most powerful security header available. It tells the browser which sources of scripts, styles, images, fonts, and other resources are legitimate for your page. Anything not on the list is blocked — including inline scripts injected by XSS.

Content-Security-Policy: default-src 'self'; script-src 'self' 'nonce-{random}'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; object-src 'none'; base-uri 'self'; frame-ancestors 'none'

Key directives:

Start in report-only mode to avoid breaking your site:

Content-Security-Policy-Report-Only: default-src 'self'; report-uri /csp-report

Strict-Transport-Security (HSTS)

HSTS tells browsers to only ever connect to your site via HTTPS, eliminating the window of vulnerability between the first HTTP request and the HTTPS redirect.

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

The preload directive allows you to submit your domain to the HSTS preload list — browsers will enforce HTTPS even on the very first visit, before any header has been seen. This is the strongest possible protection. See our HSTS guide for full details.

X-Frame-Options

Prevents your page from being embedded in an iframe on another domain. This stops clickjacking attacks where an attacker overlays an invisible iframe of your site over their own page to trick users into clicking buttons.

X-Frame-Options: DENY

Use DENY unless your application needs to be embedded somewhere (in which case use SAMEORIGIN). Note: CSP's frame-ancestors directive supersedes this header in modern browsers, but X-Frame-Options provides backward compatibility.

X-Content-Type-Options

Prevents browsers from MIME-sniffing a response away from the declared Content-Type. Without this header, a browser might execute a JavaScript file served as text/plain, enabling content injection attacks.

X-Content-Type-Options: nosniff

There is only one valid value: nosniff. Always set it.

Referrer-Policy

Controls how much referrer information is sent when a user clicks a link from your page to another site. Without this header, the full URL (including path and query string) is sent in the Referer header — this can leak sensitive URL parameters like session tokens, user IDs, or search terms.

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

This sends the full URL for same-origin requests, but only the origin (no path or query) for cross-origin requests. For highly sensitive applications, use no-referrer.

Permissions-Policy

Formerly called Feature-Policy, this header controls access to browser features like camera, microphone, geolocation, and payment APIs. Disable everything your application does not use.

Permissions-Policy: camera=(), microphone=(), geolocation=(), payment=(), usb=()

An empty value (()) disables the feature for all origins. This limits the damage if your application is ever compromised — an attacker cannot silently activate a user's camera or microphone.

Cross-Origin-Opener-Policy (COOP)

Prevents other origins from getting a reference to your window via window.open() or clicking a link. This protects against cross-origin attacks that exploit shared browsing contexts and is required to isolate your page for high-resolution timers (needed for SharedArrayBuffer).

Cross-Origin-Opener-Policy: same-origin

Cross-Origin-Resource-Policy (CORP)

Controls which origins can load your resources. Prevents Spectre-style side-channel attacks where malicious pages load your resources to infer their content via timing.

Cross-Origin-Resource-Policy: same-origin

Quick Implementation Reference

Nginx — add to your server block:

add_header Strict-Transport-Security "max-age=31536000; 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;
add_header Content-Security-Policy "default-src 'self'; object-src 'none'; base-uri 'self'" always;

Flask (Python):

@app.after_request
def security_headers(response):
    response.headers['X-Frame-Options'] = 'DENY'
    response.headers['X-Content-Type-Options'] = 'nosniff'
    response.headers['Referrer-Policy'] = 'strict-origin-when-cross-origin'
    response.headers['Permissions-Policy'] = 'camera=(), microphone=(), geolocation=()'
    return response

Checking Your Headers

Inspect headers with:

curl -sI https://yoursite.com | grep -iE "security|frame|content-type|referrer|permissions|csp"

Or run a full scan with Shieldome, which checks all security headers and provides severity-rated findings with remediation guidance for every missing or misconfigured header.