Security Headers

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.

SiteSecurityScore Team·12 min read·Updated Apr 3, 2026
Developer workstation with code editor open showing server configuration for HTTP security headers

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-PolicyCritical

Controls which scripts, styles, and resources a page is allowed to load

Recommended:default-src 'self'; script-src 'self'; style-src 'self'
Strict-Transport-SecurityHigh

Forces all connections to use HTTPS, preventing protocol downgrade attacks

Recommended:max-age=63072000; includeSubDomains; preload
Cross-Origin-Embedder-PolicyHigh

Requires cross-origin resources to opt in before your page can load them

Recommended:require-corp
Cross-Origin-Opener-PolicyHigh

Isolates your browsing context so other origins cannot access your window object

Recommended:same-origin
X-Frame-OptionsMedium

Prevents your page from being embedded in iframes on other sites

Recommended:DENY
X-Content-Type-OptionsMedium

Stops browsers from guessing the content type of a response

Recommended:nosniff
Cross-Origin-Resource-PolicyMedium

Controls which origins can load your resources in their pages

Recommended:same-origin
Referrer-PolicyLow

Controls how much URL information is shared when navigating to other sites

Recommended:strict-origin-when-cross-origin
Permissions-PolicyLow

Restricts which browser features and APIs your page and embedded iframes can use

Recommended: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.

Apache (.htaccess)
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'"
Nginx
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;
Node.js / Express
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.

Apache (.htaccess)
Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"
Nginx
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
Node.js / Express
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.

All servers
# 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.

All servers
# 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.

All servers
# 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.

All servers
# 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.

All servers
# 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.

All servers
# 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.

All servers
# 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.

All servers
# 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.

All servers
# 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.

Apache (.htaccess)
# 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>
Nginx server block
# 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;
Node.js / Express middleware
// 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

Was this helpful?

Test Your Security Headers

Scan your website to see which headers are configured and which are missing.