HTTP Security Headers Explained
What each HTTP security header does, what attacks it prevents, and how to add it to your web server or CDN.
HTTP Security Headers Explained
HTTP security headers are instructions your web server sends to browsers. They tell the browser how to handle your site's content, which connections to trust, and which browser features to allow or deny. Misconfigured or missing headers are one of the most common web security gaps.
ElasticDomain checks for these headers on every full scan and in the standalone HTTP Header Analyzer tool.
Content-Security-Policy (CSP)
What it does: Whitelists which sources of scripts, styles, images, and other resources the browser is allowed to load. Unauthorized sources are blocked.
Attack it prevents: Cross-Site Scripting (XSS). Without CSP, an attacker who manages to inject a <script> tag into your page can run arbitrary JavaScript.
Example:
Content-Security-Policy: default-src 'self'; script-src 'self' https://cdn.example.com; img-src 'self' data:
Common issue: unsafe-inline and unsafe-eval directives undermine the protection. Avoid them if possible; they're often added as a quick fix for inline script errors but they defeat much of CSP's value.
How to add: Set as an HTTP response header in Nginx, Apache, Cloudflare, or via a CDN header rule.
HTTP Strict Transport Security (HSTS)
What it does: Tells browsers this domain should only ever be accessed over HTTPS. The browser caches this directive for the duration of max-age and refuses to make HTTP connections - even if the user types http:// manually.
Attack it prevents: SSL stripping / protocol downgrade attacks. Without HSTS, an attacker on the same network can intercept the initial HTTP request before the redirect to HTTPS.
Example:
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
| Directive | Meaning |
|---|---|
max-age=31536000 |
Remember for 1 year |
includeSubDomains |
Apply to all subdomains too |
preload |
Eligible for hardcoded browser preload list |
HSTS preload: You can submit your domain to the HSTS preload list (hstspreload.org) so browsers never attempt HTTP even on the very first visit. Requires max-age ≥ 31536000, includeSubDomains, and preload in the header.
X-Frame-Options
What it does: Controls whether your page can be embedded in a <frame>, <iframe>, or <object> on another site.
Attack it prevents: Clickjacking. An attacker creates a transparent overlay of your site inside an iframe on their own page and tricks users into clicking buttons on your site without knowing.
Values:
| Value | Meaning |
|---|---|
DENY |
No one can frame your page |
SAMEORIGIN |
Only your own domain can frame it |
ALLOW-FROM uri |
Deprecated - don't use |
Example:
X-Frame-Options: SAMEORIGIN
Note: CSP's frame-ancestors directive is the modern replacement and supports more granular control. X-Frame-Options is still worth setting for older browser compatibility.
X-Content-Type-Options
What it does: Tells the browser not to "sniff" the MIME type of a response - always use what the server declared in Content-Type.
Attack it prevents: MIME-type confusion attacks. Without this header, some browsers might execute a file as JavaScript even if it was downloaded as a plain text file, if the content looks like JavaScript.
The only valid value:
X-Content-Type-Options: nosniff
This is a simple, low-risk header to add. Every web server should send it.
Referrer-Policy
What it does: Controls how much information about the current page URL is included in the Referer header when the user navigates to another site.
Why it matters: Without it, the full URL of the page the user was on (including any query parameters like ?token=abc or [email protected]) is sent to the destination site.
Common values:
| Value | Referrer Sent |
|---|---|
no-referrer |
Nothing sent |
same-origin |
Full URL sent only to your own domain |
strict-origin |
Only origin (no path) sent cross-origin |
strict-origin-when-cross-origin |
Full URL same-origin; origin-only cross-origin (recommended) |
Example:
Referrer-Policy: strict-origin-when-cross-origin
Permissions-Policy
What it does: Controls which browser features and APIs your page (and any embedded iframes) can access - camera, microphone, geolocation, payment, USB, etc.
Why it matters: Restricts what JavaScript can do even if the page is compromised. An attacker who injects script into your page can't access the camera if Permissions-Policy denies it.
Example (deny everything):
Permissions-Policy: camera=(), microphone=(), geolocation=(), payment=()
Example (allow geolocation for your own origin only):
Permissions-Policy: camera=(), microphone=(), geolocation=(self)
How to Add Headers
Nginx
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;
Apache
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
Header always set X-Frame-Options "SAMEORIGIN"
Header always set X-Content-Type-Options "nosniff"
Cloudflare
Cloudflare → your domain → Rules → Transform Rules → Modify Response Header. Add each header as a static value.
Vercel / Next.js
In next.config.ts, use the headers() function to add security headers to all responses.
Checking Your Headers
Use the HTTP Header Analyzer tool in ElasticDomain:
- Tools → Header Analyzer
- Enter your URL
- Click Analyze
The analyzer fetches your live headers and grades each one - present and correctly configured (✅), present but weak (⚠️), or missing (❌).