July 19, 2026
HTTP Security Headers: The Complete 2026 Guide with nginx & Apache Examples
Why Security Headers Matter
By Daniel Faegnell
4 min read
Why Security Headers Matter
HTTP security headers are directives sent by your web server that instruct browsers on how to behave when displaying your website. Adding them requires no changes to your application code — only web server configuration — yet they are one of the most effective defenses against a wide range of common web attacks, including Cross-Site Scripting (XSS), clickjacking, and content injection.
Many websites neglect security headers entirely. A scan of the top million websites consistently shows that the majority are missing at least some critical headers. This is a missed opportunity because these headers are free and easy to add.
HSTS — HTTP Strict Transport Security
HSTS is a header that tells browsers: never connect to this website over plain HTTP, no matter what. Once a browser has seen an HSTS header from your site, it will automatically upgrade any future HTTP requests to HTTPS — even if the user types "http://" in the address bar or clicks an HTTP link. This is one of the most important security headers you can add.
The header has three important parameters. The "max-age" value tells the browser how long (in seconds) to remember this policy — you should set this to at least one year (31536000 seconds). The "includeSubDomains" flag extends this protection to all your subdomains. The "preload" flag tells browsers that you want to be included in the HSTS preload list — a list baked directly into Chrome, Firefox, and other browsers so that even the very first visit to your site is protected.
On nginx, you add this header with the add_header directive inside your server block. On Apache, you use the Header directive inside a VirtualHost block. Always include the "always" keyword to ensure the header is sent even with error responses.
Before setting a long max-age, make absolutely certain that your entire site — including all subdomains — is working correctly over HTTPS. Setting HSTS with a long max-age and then discovering that a subdomain does not support HTTPS can lock users out for months.
CSP — Content Security Policy
Content Security Policy is the most powerful security header available, and also the most complex to configure correctly. It tells browsers exactly which sources of content are permitted to load on your page — scripts, stylesheets, images, fonts, and more. This is your primary defense against Cross-Site Scripting (XSS) attacks, where an attacker manages to inject malicious JavaScript into your page.
A CSP works by whitelisting trusted sources. For example, you might specify that scripts can only be loaded from your own domain and from Google Analytics, that stylesheets can only come from your own domain, and that images can come from anywhere over HTTPS. Any content that does not match these rules is blocked by the browser before it can execute.
The most effective way to implement CSP is gradually. Start by adding a "Content-Security-Policy-Report-Only" header rather than "Content-Security-Policy." This means the policy is not enforced — violations are reported to you but the content still loads. This lets you collect violation reports, identify all the legitimate third-party resources your site actually loads, and build your policy without breaking anything. After a week or two of collecting data, switch to the enforcing version.
One common pitfall is "unsafe-inline" — a directive that allows inline scripts and styles. While this makes it easy to implement CSP without breaking your site, it dramatically reduces the protection it offers, because most XSS attacks rely on injecting inline scripts. A better approach is to use "nonces" or "hashes" to allow specific inline scripts while blocking injected ones.
X-Frame-Options
The X-Frame-Options header controls whether your website can be embedded inside an iframe on another domain. This protects against clickjacking attacks, where an attacker puts your website in an invisible iframe overlaid on top of their own page. The visitor thinks they are clicking something on the attacker's page but is actually clicking on your site — potentially authorizing a transaction, clicking an "accept" button, or performing some other action without realizing it.
The recommended value is "SAMEORIGIN," which allows your site to be embedded in iframes only from pages on your own domain. "DENY" prevents embedding entirely. The older "ALLOW-FROM" option is deprecated and not supported by modern browsers.
Note that if you have a modern CSP configured, you can use the "frame-ancestors" CSP directive instead of X-Frame-Options — it offers more fine-grained control. However, for maximum compatibility across all browsers, it is a good practice to include both.
X-Content-Type-Options
This simple but important header has a single value: "nosniff." It prevents browsers from "MIME sniffing" — guessing what type of content a file contains based on its actual content rather than the declared Content-Type header.
MIME sniffing sounds harmless but can be exploited. If an attacker can get you to host a file that looks like HTML or JavaScript to a browser's content sniffer — even if you think it is an image or text file — the browser might execute it as a script. Adding "nosniff" tells browsers to always respect the declared content type and never guess.
Referrer-Policy
When a user clicks a link from your website to another site, browsers automatically include a "Referer" header (note the misspelling — it is historical) telling the destination site where the user came from. This can inadvertently leak sensitive information if your URLs contain session tokens, search queries, or other private data in the query string.
The Referrer-Policy header controls what information is sent. The recommended value "strict-origin-when-cross-origin" sends the full URL for same-origin requests (useful for your own analytics) but only sends the domain (not the full URL) for cross-origin requests. This protects sensitive URL parameters while preserving useful referrer information for your own site.
Permissions-Policy
Permissions-Policy (formerly called Feature-Policy) controls which browser features and APIs your page is allowed to use. This includes potentially sensitive capabilities like the camera, microphone, geolocation, payment request API, and more. By explicitly disabling features you do not use, you prevent third-party scripts (advertising networks, analytics, embedded content) from accessing those features even if they try.
Frequently Asked Questions
Will adding a CSP break my website? It might, initially. CSP blocks anything not explicitly allowed. If you have inline scripts, inline styles, or third-party resources you have not whitelisted, they will be blocked. The solution is to use Report-Only mode first and spend time collecting violation reports before switching to enforcement.
What is the Server header and should I hide it? The Server header reveals your web server software and version — for example, "nginx/1.24.0." This information is useful to attackers who want to target known vulnerabilities in specific software versions. You should suppress or genericize this header. In nginx, set "server_tokens off." In Apache, use "ServerTokens Prod."
Do these headers affect site performance? Negligibly. The headers add a few bytes to each HTTP response but have no meaningful impact on load time. The security benefits far outweigh any marginal overhead.
Should I add security headers to HTTP responses as well as HTTPS? Yes — configure them on both, but remember that HSTS should only be sent over HTTPS. Sending HSTS over HTTP is ignored and could cause confusion.
Originally published at fortifynet.com. Run a free 60-second security scan of your own site at fortifynet.com.
Originally published at https://fortifynet.com.