What Are HTTP Security Headers?
When a browser requests a website, the web server sends HTTP response headers alongside the HTML content. Security headers are special instructions within this response that tell the browser how to handle the received content. They function like security rules that the browser automatically enforces.
The principle is straightforward: instead of trusting that attackers will not inject malicious code, the server instructs the browser to block certain actions preemptively. Even if an attacker manages to inject malicious JavaScript into your page, a Content-Security-Policy can prevent that code from executing.
Security headers are set in the server configuration, not in your website's source code. This means you can improve your entire website's protection without changing a single line of HTML, CSS, or JavaScript. Configuration is done in .htaccess (Apache), nginx.conf (Nginx), or your hosting provider's control panel.
Content-Security-Policy (CSP): The Most Powerful Header
The Content-Security-Policy is the most comprehensive and effective security header. It precisely defines which sources the browser may load resources from: scripts, stylesheets, images, fonts, iframes, and more. A correctly configured CSP can virtually eliminate cross-site scripting attacks.
Basic CSP Configuration
A basic CSP looks like this: Content-Security-Policy: default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; This policy only allows resources from the own domain. External scripts are blocked. In practice, you must adapt the policy to your actual services: if you use an external font, its domain must be allowed in font-src.
Introducing CSP Gradually
An overly restrictive CSP can break website functionality. A gradual introduction is therefore recommended:
- Start with Content-Security-Policy-Report-Only instead of Content-Security-Policy. The browser reports violations but blocks nothing.
- Set up a report endpoint to collect and analyze violations.
- Adjust the policy until all legitimate resources are permitted.
- Only then switch to enforce mode.
- Monitor the CSP permanently, as every new script or plugin can violate the policy.
The directives 'unsafe-inline' and 'unsafe-eval' in script-src largely negate CSP's XSS protection. Where possible, use nonces or hashes for inline scripts instead. XICTRAQ detects these weaknesses and reports them as configuration deficiencies.
Strict-Transport-Security (HSTS)
HSTS instructs the browser to make all future connections to the website exclusively over HTTPS. Even if a user manually types http://, the browser automatically redirects to HTTPS without contacting the server. This prevents downgrade attacks and protects against man-in-the-middle attacks on insecure networks like public Wi-Fi.
The recommended configuration is: Strict-Transport-Security: max-age=31536000; includeSubDomains; preload. The max-age of 31536000 seconds equals one year. includeSubDomains protects all subdomains. The preload attribute enables inclusion in browsers' HSTS preload list, providing protection from the very first visit.
Only activate HSTS when HTTPS works flawlessly across your entire website. A misconfigured HSTS header can render your website unreachable for months, as the browser strictly enforces the max-age setting and does not allow fallback to HTTP.
X-Content-Type-Options
This header prevents browsers from guessing a file's MIME type, a process known as MIME sniffing. Without this header, an attacker could inject a JavaScript file disguised as an image that the browser would still execute as a script.
The configuration is straightforward: X-Content-Type-Options: nosniff. This header causes no compatibility issues and should be set on every website. It is the simplest entry point into the world of security headers.
X-Frame-Options: Protection Against Clickjacking
X-Frame-Options controls whether your website may be embedded in an iframe. In a clickjacking attack, an attacker invisibly embeds your website over a manipulated page. When the user clicks a seemingly harmless button, they actually perform an action on your website, such as a bank transfer or account setting change.
X-Frame-Options: DENY prevents all embedding. X-Frame-Options: SAMEORIGIN allows embedding only from the same domain. For most websites, DENY is the safer choice. If you need to embed your page in your own iframes, use SAMEORIGIN.
The more modern alternative is the frame-ancestors directive in CSP, which offers more flexible configuration options: Content-Security-Policy: frame-ancestors 'self' is equivalent to X-Frame-Options: SAMEORIGIN.
Referrer-Policy
When a user navigates from your website to another, the browser sends the full URL as referrer information by default. This can reveal sensitive data: internal URL structures, search parameters, or even session IDs in the URL.
Referrer-Policy: strict-origin-when-cross-origin is the recommended setting. When navigating within your domain, the full referrer is sent, which remains useful for your own analytics. When navigating to external sites, only the origin (domain without path) is transmitted. When switching from HTTPS to HTTP, no referrer is sent at all.
Permissions-Policy: Restricting Browser APIs
The Permissions-Policy (formerly Feature-Policy) controls which browser features your website may use. These include camera, microphone, geolocation, Payment API, USB access, and many other APIs. A strict Permissions-Policy ensures that compromised third-party scripts cannot access sensitive browser APIs.
Example: Permissions-Policy: camera=(), microphone=(), geolocation=(), payment=() completely disables camera, microphone, geolocation, and Payment API. If your website needs a specific API, allow it selectively: Permissions-Policy: geolocation=(self).
Configuring Security Headers: Apache and Nginx
Apache Configuration (.htaccess)
Header set X-Content-Type-Options "nosniff"
Header set X-Frame-Options "SAMEORIGIN"
Header set Referrer-Policy "strict-origin-when-cross-origin"
Header set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
Header set Permissions-Policy "camera=(), microphone=(), geolocation=()"
Header set Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:;"Nginx Configuration
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 Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" 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'; img-src 'self' data:;" always;The 'always' keyword in Nginx ensures headers are also sent with error responses (404, 500, etc.). Without 'always', headers are only appended to successful responses (2xx, 3xx).
Common Security Header Mistakes
- Overly permissive CSP: A CSP with 'unsafe-inline' and 'unsafe-eval' offers minimal XSS protection
- Missing includeSubDomains in HSTS: Without this attribute, subdomains remain vulnerable to downgrade attacks
- Duplicate headers: Some servers send the same header multiple times with different values, leading to unpredictable behavior
- Headers only on the homepage: Security headers must be set on all pages, not just selected ones
- Using outdated headers: X-XSS-Protection is considered deprecated and can even open security holes in certain browsers. Use a CSP instead.
Security Headers and SEO Impact
Security headers also have indirect effects on search engine optimization. Google favors secure websites and considers HTTPS as a ranking signal. A correctly configured HSTS policy signals to search engines that your website is permanently accessible via HTTPS. Faulty configurations can lead to browser warnings that deter visitors and increase bounce rates.
Furthermore, a strict CSP protects against attacks that could manipulate your website and inject harmful content. Websites affected by malware are flagged by Google with a warning in search results, drastically reducing traffic. Good security headers are therefore not just a security measure but also an SEO measure. More on technical SEO in our post on automated SEO monitoring.
Monitoring Security Headers Continuously
One-time configuration of security headers is not sufficient. Server updates, hosting migrations, CDN configuration changes, or new services can cause headers to be accidentally removed or weakened. Without continuous monitoring, you only notice when it is too late.
The XICTRAQ security module checks your headers at configurable intervals and evaluates not just their existence but also configuration quality. A CSP with 'unsafe-inline' receives a lower rating than a strictly configured policy. You receive concrete improvement recommendations and are immediately notified when something changes.
Integration into comprehensive website monitoring means security header data can be viewed in context with other metrics. When headers suddenly disappear after a server update, XICTRAQ correlates this with the timing of the change and provides the information you need for quick resolution.
Frequently Asked Questions About Security Headers
Which security headers should I implement first?
Can security headers break my website?
Do I need security headers if I use HTTPS?
How do I check which security headers my website has?
How often do security header recommendations change?
Do security headers affect website performance?
This article is based on data from: (Google), (Scott Helme).