
In short. A handful of response headers close whole classes of attack before any application code runs: framing, content-type sniffing, transport downgrade and script injection. They cost nothing to send, which is why their absence is the first thing an audit finds and the cheapest thing to fix.
HTTP security headers are the first line of defense for your website against common web attacks: XSS, clickjacking, MIME-sniffing, and traffic interception. Proper configuration takes minutes, yet it protects against most attacks from the OWASP Top 10.
Why Security Headers Matter
HTTP security headers are instructions for the browser that define security rules when interacting with your site. They protect against XSS, clickjacking, MITM, injection, and other attacks. Configuration takes minutes, and the effect is closing entire classes of vulnerabilities.
Check your current security headers using the Enterno.io Security Scanner.
Content-Security-Policy (CSP)
The most powerful security header. CSP controls where the browser can load resources from — scripts, styles, fonts, images, frames, and more:
Content-Security-Policy: default-src 'self'; script-src 'self' https://cdn.example.com; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' https://fonts.gstatic.com; frame-ancestors 'none'
Core CSP Directives
| Directive | What It Controls |
|---|---|
default-src | Default source for all resource types |
script-src | Where JavaScript can be loaded from |
style-src | Where CSS can be loaded from |
img-src | Where images can be loaded from |
font-src | Where fonts can be loaded from |
connect-src | Where AJAX/Fetch/WebSocket requests can be sent |
frame-src | Where iframes can be loaded from |
frame-ancestors | Who can embed your page in an iframe |
base-uri | Allowed URLs for the <base> tag |
form-action | Where forms are allowed to submit |
Source Values
'self'— current domain only'none'— completely disallowed'unsafe-inline'— inline scripts/styles are allowed (weakens protection)'unsafe-eval'— eval() is allowed (dangerous)'nonce-abc123'— elements with the specified nonce are allowed'strict-dynamic'— scripts loaded by trusted scripts are also trustedhttps:— any HTTPS sourcehttps://cdn.example.com— a specific domain
Report-Only Mode
Start with report-only mode to avoid breaking your site:
Content-Security-Policy-Report-Only: default-src 'self'; report-uri /csp-report
The browser will log violations but will not block resources.
Strict-Transport-Security (HSTS)
Forces the browser to always use HTTPS for your domain, even if the user types http://:
Strict-Transport-Security: max-age=63072000; includeSubDomains; preload
max-age=63072000— remember for 2 years (in seconds)includeSubDomains— apply to all subdomainspreload— add to browser preload lists (hstspreload.org)
Important: before enabling HSTS, make sure your entire site works over HTTPS. Once enabled, rolling it back is difficult — browsers will remember the directive.
X-Frame-Options
Protects against clickjacking — an attack where your site is embedded in an invisible iframe:
X-Frame-Options: DENY
| Value | Description |
|---|---|
DENY | Completely prevents embedding in an iframe |
SAMEORIGIN | Allowed only from the same domain |
ALLOW-FROM uri | Allowed from a specified URL (deprecated, not supported in Chrome) |
The modern replacement is the CSP directive frame-ancestors.
X-Content-Type-Options
Prevents the browser from "guessing" the MIME type of content (MIME-sniffing):
X-Content-Type-Options: nosniff
Without this header, the browser may interpret a text file as JavaScript and execute it — a classic XSS attack vector.
Referrer-Policy
Controls what information is sent in the Referer header when navigating to other sites:
Referrer-Policy: strict-origin-when-cross-origin
| Value | Description |
|---|---|
no-referrer | Referer is not sent at all |
origin | Only the domain is sent (no path) |
strict-origin-when-cross-origin | Full URL for same domain, only origin for others (recommended) |
same-origin | Referer only for same-domain requests |
no-referrer-when-downgrade | Do not send when navigating from HTTPS to HTTP |
Permissions-Policy
Controls access to browser APIs — camera, microphone, geolocation, fullscreen mode, and more:
Permissions-Policy: camera=(), microphone=(), geolocation=(self), fullscreen=(self)
Empty parentheses () completely disable the feature. (self) allows it only for the current domain.
X-XSS-Protection
Activates the browser's built-in XSS filter (deprecated, but useful for older versions of IE):
X-XSS-Protection: 1; mode=block
Modern browsers rely on CSP instead of this header, but it is still worth enabling for backward compatibility.
Cross-Origin Headers
Cross-Origin-Opener-Policy (COOP)
Cross-Origin-Opener-Policy: same-origin
Isolates the window context. Prevents attacks via window.opener from cross-site windows.
Cross-Origin-Resource-Policy (CORP)
Cross-Origin-Resource-Policy: same-origin
Prevents other sites from loading your resources (protection against hot-linking and data leaks).
Cross-Origin-Embedder-Policy (COEP)
Cross-Origin-Embedder-Policy: require-corp
All loaded resources must explicitly allow cross-site usage. Required for SharedArrayBuffer and high-precision timers.
Recommended Header Set
The minimum set of security headers for any website:
# Nginx
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" 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'" always;
# Apache (.htaccess)
Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"
Header always set X-Content-Type-Options "nosniff"
Header always set X-Frame-Options "SAMEORIGIN"
Header always set Referrer-Policy "strict-origin-when-cross-origin"
Header always set Permissions-Policy "camera=(), microphone=(), geolocation=()"
Header always set Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'"
How to Check Security Headers
Two tools show what you have: the security scanner grades the headers by severity, and the HTTP checker prints the full server response, missing headers included.
Summary
Security headers are the mandatory minimum protection for any website. Start with HSTS, X-Content-Type-Options, X-Frame-Options, and Referrer-Policy — they're simple and safe. Then add CSP, starting in Report-Only mode. Permissions-Policy and Cross-Origin headers provide advanced protection.