Security Headers Cheat Sheet: Complete Reference Guide
A single page reference for every HTTP security header you should know. Each header includes a brief explanation, the recommended value, and copy-paste configuration examples for Apache, Nginx, and Node.js.
HTTP security headers are response headers that your web server sends alongside every page. They instruct the browser on how to handle content, which origins to trust, and which features to allow. Configuring them correctly is one of the most effective ways to harden your website against common attacks like cross-site scripting (XSS), clickjacking, and data injection.
This guide is designed as a quick reference. Each section covers a header or group of related headers with a brief explanation and ready to use configuration examples. If you need a deeper explanation of any single header, follow the links to the dedicated guides.
Quick reference table#
The table below lists every security header covered in this guide. Each entry shows what the header does in one line, its recommended value, and a severity rating that reflects how much impact a missing header has on your overall security posture.
Content-Security-PolicyCriticalControls which scripts, styles, and resources a page is allowed to load
default-src 'self'; script-src 'self'; style-src 'self'Strict-Transport-SecurityHighForces all connections to use HTTPS, preventing protocol downgrade attacks
max-age=63072000; includeSubDomains; preloadCross-Origin-Embedder-PolicyHighRequires cross-origin resources to opt in before your page can load them
require-corpCross-Origin-Opener-PolicyHighIsolates your browsing context so other origins cannot access your window object
same-originX-Frame-OptionsMediumPrevents your page from being embedded in iframes on other sites
DENYX-Content-Type-OptionsMediumStops browsers from guessing the content type of a response
nosniffCross-Origin-Resource-PolicyMediumControls which origins can load your resources in their pages
same-originReferrer-PolicyLowControls how much URL information is shared when navigating to other sites
strict-origin-when-cross-originPermissions-PolicyLowRestricts which browser features and APIs your page and embedded iframes can use
camera=(), microphone=(), geolocation=()Content-Security-Policy#
Content-Security-Policy (CSP) is the highest impact security header you can configure. It tells the browser exactly which sources of content are permitted on your page. Scripts, stylesheets, images, fonts, and network requests that do not match the policy are blocked automatically. This makes CSP the primary defense against cross-site scripting, where an attacker injects malicious scripts that the browser would otherwise execute without question.
A good starting policy restricts everything to your own origin and then opens up only the sources you actually need. The default-src directive sets the baseline, and specific directives like script-src and style-src override it for their respective resource types.
Header always set Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self'; img-src 'self'; font-src 'self'; connect-src 'self'; frame-ancestors 'none'"
add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self'; img-src 'self'; font-src 'self'; connect-src 'self'; frame-ancestors 'none'" always;
res.setHeader('Content-Security-Policy',
"default-src 'self'; script-src 'self'; style-src 'self'; " +
"img-src 'self'; font-src 'self'; connect-src 'self'; " +
"frame-ancestors 'none'"
);Most real applications will need to add trusted third party domains to specific directives. For example, if you load Google Fonts, you would add fonts.googleapis.com to style-src and fonts.gstatic.com to font-src. See the Content Security Policy deep dive for a full walkthrough of directives and common configurations.
Transport and encryption headers#
These headers ensure that browsers always connect to your site over HTTPS and that any leftover HTTP references on your pages are automatically upgraded to secure connections.
Strict-Transport-Security (HSTS)
HSTS tells the browser to only connect to your site over HTTPS for a specified period. Once a browser receives this header, it will refuse to make any unencrypted HTTP connection to your domain, even if the user types http:// in the address bar. The max-age value is in seconds. A value of 63072000 equals two years, which is the minimum recommended for HSTS preload submission.
Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
res.setHeader('Strict-Transport-Security', 'max-age=63072000; includeSubDomains; preload');Upgrade-Insecure-Requests
This header tells the browser to automatically upgrade any HTTP resource URLs on your page to HTTPS before making the request. It is useful during HTTPS migrations when some internal links or embedded content still reference HTTP URLs. Unlike HSTS, this header applies to individual resources on the page rather than the entire domain connection.
# Apache
Header always set Content-Security-Policy "upgrade-insecure-requests"
# Nginx
add_header Content-Security-Policy "upgrade-insecure-requests" always;
# Express
res.setHeader('Content-Security-Policy', 'upgrade-insecure-requests');Only enable HSTS preload when you are certain
Adding the preload directive and submitting your domain to the HSTS preload list is effectively permanent. Removing your domain from the list takes months. Only include preload if your entire domain and all subdomains are fully committed to HTTPS with no plans to revert.
Framing and isolation headers#
These headers control how your page interacts with other origins. They prevent clickjacking (where an attacker embeds your page in a hidden iframe to trick users into clicking things) and enable cross-origin isolation, which protects against memory-based side-channel attacks like Spectre.
X-Frame-Options
Controls whether your page can be loaded inside an iframe on another site. Setting this to DENY blocks all framing. Use SAMEORIGIN if your own site needs to embed itself.
# Apache
Header always set X-Frame-Options "DENY"
# Nginx
add_header X-Frame-Options "DENY" always;
# Express
res.setHeader('X-Frame-Options', 'DENY');Cross-Origin-Opener-Policy (COOP)
COOP isolates your browsing context from documents opened by your page or documents that opened your page. When set to same-origin, popups and tabs from other origins cannot access your page's window object.
# Apache
Header always set Cross-Origin-Opener-Policy "same-origin"
# Nginx
add_header Cross-Origin-Opener-Policy "same-origin" always;
# Express
res.setHeader('Cross-Origin-Opener-Policy', 'same-origin');Cross-Origin-Embedder-Policy (COEP)
COEP requires that every resource your page loads either comes from the same origin or explicitly opts in to cross-origin loading via CORS headers or the Cross-Origin-Resource-Policy header. Combined with COOP, this enables cross-origin isolation and unlocks high-resolution timers and SharedArrayBuffer.
# Apache
Header always set Cross-Origin-Embedder-Policy "require-corp"
# Nginx
add_header Cross-Origin-Embedder-Policy "require-corp" always;
# Express
res.setHeader('Cross-Origin-Embedder-Policy', 'require-corp');Cross-Origin-Resource-Policy (CORP)
CORP controls which origins are allowed to load your resources. Setting it to same-origin prevents other sites from embedding your images, scripts, or other assets. Use cross-origin if you intentionally serve public resources that other sites need to load.
# Apache
Header always set Cross-Origin-Resource-Policy "same-origin"
# Nginx
add_header Cross-Origin-Resource-Policy "same-origin" always;
# Express
res.setHeader('Cross-Origin-Resource-Policy', 'same-origin');Content and disclosure headers#
These headers control how the browser interprets content and what information it shares with third parties. They are lower severity individually, but together they close several information leakage and content confusion vectors.
X-Content-Type-Options
Browsers sometimes try to guess (or "sniff") the content type of a response by examining its contents, ignoring the declared Content-Type header. This can cause a file served as plain text to be executed as JavaScript. Setting nosniff forces the browser to respect the declared type.
# Apache
Header always set X-Content-Type-Options "nosniff"
# Nginx
add_header X-Content-Type-Options "nosniff" always;
# Express
res.setHeader('X-Content-Type-Options', 'nosniff');Referrer-Policy
When a visitor navigates from your page to another site, the browser sends a Referer header containing the URL they came from. Without a policy, this can leak sensitive path information, query parameters, or session tokens to third parties. The value strict-origin-when-cross-origin sends the full URL for same-origin requests but only the origin (domain) for cross-origin requests.
# Apache
Header always set Referrer-Policy "strict-origin-when-cross-origin"
# Nginx
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
# Express
res.setHeader('Referrer-Policy', 'strict-origin-when-cross-origin');Permissions-Policy
Permissions-Policy (formerly Feature-Policy) controls which browser features your page and any embedded iframes are allowed to use. Features include the camera, microphone, geolocation, and payment APIs. Setting a feature to an empty allowlist () disables it entirely.
# Apache
Header always set Permissions-Policy "camera=(), microphone=(), geolocation=(), payment=()"
# Nginx
add_header Permissions-Policy "camera=(), microphone=(), geolocation=(), payment=()" always;
# Express
res.setHeader('Permissions-Policy', 'camera=(), microphone=(), geolocation=(), payment=()');X-DNS-Prefetch-Control
Browsers sometimes prefetch DNS records for links on your page to speed up navigation. While this improves performance, it can leak information about which links are present on the page to your DNS resolver. Setting this to off disables this behavior.
# Apache
Header always set X-DNS-Prefetch-Control "off"
# Nginx
add_header X-DNS-Prefetch-Control "off" always;
# Express
res.setHeader('X-DNS-Prefetch-Control', 'off');Complete server configuration#
The following blocks include every header from this guide in a single copy-paste configuration for each server type. Add the block that matches your server, then adjust the Content-Security-Policy directive to fit your application's specific needs.
Sensible defaults
These are sensible defaults. You may need to adjust the Content-Security-Policy directive for your specific application. Start with these values, run a scan to verify, and then loosen individual directives only where your application requires it.
# Security Headers - Apache (.htaccess) <IfModule mod_headers.c> Header always set Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self'; img-src 'self'; font-src 'self'; connect-src 'self'; frame-ancestors 'none'" Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" Header always set X-Frame-Options "DENY" Header always set X-Content-Type-Options "nosniff" Header always set Referrer-Policy "strict-origin-when-cross-origin" Header always set Permissions-Policy "camera=(), microphone=(), geolocation=(), payment=()" Header always set Cross-Origin-Embedder-Policy "require-corp" Header always set Cross-Origin-Opener-Policy "same-origin" Header always set Cross-Origin-Resource-Policy "same-origin" Header always set X-DNS-Prefetch-Control "off" </IfModule>
# Security Headers - Nginx server block add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self'; img-src 'self'; font-src 'self'; connect-src 'self'; frame-ancestors 'none'" always; add_header Strict-Transport-Security "max-age=63072000; 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=(), payment=()" always; add_header Cross-Origin-Embedder-Policy "require-corp" always; add_header Cross-Origin-Opener-Policy "same-origin" always; add_header Cross-Origin-Resource-Policy "same-origin" always; add_header X-DNS-Prefetch-Control "off" always;
// Security Headers - Node.js/Express middleware
app.use((req, res, next) => {
res.setHeader('Content-Security-Policy',
"default-src 'self'; script-src 'self'; style-src 'self'; " +
"img-src 'self'; font-src 'self'; connect-src 'self'; " +
"frame-ancestors 'none'"
);
res.setHeader('Strict-Transport-Security',
'max-age=63072000; includeSubDomains; preload'
);
res.setHeader('X-Frame-Options', 'DENY');
res.setHeader('X-Content-Type-Options', 'nosniff');
res.setHeader('Referrer-Policy', 'strict-origin-when-cross-origin');
res.setHeader('Permissions-Policy',
'camera=(), microphone=(), geolocation=(), payment=()'
);
res.setHeader('Cross-Origin-Embedder-Policy', 'require-corp');
res.setHeader('Cross-Origin-Opener-Policy', 'same-origin');
res.setHeader('Cross-Origin-Resource-Policy', 'same-origin');
res.setHeader('X-DNS-Prefetch-Control', 'off');
next();
});FAQ#
How many security headers should my website have?
A well-configured website should have at least six to nine security headers. The essential set includes Content-Security-Policy, Strict-Transport-Security, X-Frame-Options, X-Content-Type-Options, Referrer-Policy, and Permissions-Policy. Sites that load cross-origin resources should also add Cross-Origin-Embedder-Policy, Cross-Origin-Opener-Policy, and Cross-Origin-Resource-Policy.
Which security headers are required vs optional?
No security header is technically required by the HTTP specification. However, Content-Security-Policy and Strict-Transport-Security are considered critical and high priority because they prevent the most common and damaging attacks. X-Frame-Options and X-Content-Type-Options are medium priority and safe to add on any site. Referrer-Policy and Permissions-Policy are lower priority but still recommended as part of a complete configuration.
Can I set security headers with HTML meta tags?
Only Content-Security-Policy supports a meta tag equivalent using the http-equiv attribute. All other security headers must be set as HTTP response headers at the server level. Even for CSP, the meta tag approach has limitations: it does not support report-uri or report-to directives, and it cannot use the frame-ancestors directive. Server level configuration is always preferred.
Where should I configure security headers?
Security headers should be configured at the server or CDN level so they are included in every HTTP response. For Apache servers, use .htaccess or the main configuration file. For Nginx, add them to your server block. For Node.js and Express, use middleware. If you use a CDN like Cloudflare or AWS CloudFront, configure headers at the edge for the most consistent coverage.
References
Related articles
Test Your Security Headers
Scan your website to see which headers are configured and which are missing.