Notes

Why You Should Add Security Headers to Your Site

What HTTP security headers are, what functions they serve, and how

3 min read

Why You Should Add Security Headers to Your Site

Security headers are tags the server attaches to every page that give direct instructions to the browser. They don't just improve security: they also tell the browser which features it is allowed to use. Without them, the browser decides everything on its own. With them, you're the one in charge. And a well-kept site is not just secure: it's also worth knowing if it loads fast (Why run a speed test?) and that search engines understand it, for example through schema markup (Schema markup: what it is and how it can help your website).

Types of Security Headers and Their Functions

There are several types, and each one has a specific purpose. Here are some of the most important ones:

Content-Security-Policy

This header defines the approved sources from which the browser can load content on your site. By specifying the sources you want to allow, you protect visitors from a variety of issues, including XSS attacks (someone injecting their own code into your page). They need to be configured properly: they decide which content is loaded and which is blocked.

<IfModule mod_headers.c>
Header set Content-Security-Policy "upgrade-insecure-requests"
</IfModule>

Strict-Transport-Security (HSTS)

The Strict-Transport-Security header tells browsers that the site should only be opened over HTTPS (the encrypted version of HTTP). Always a secure, encrypted connection: visitor data privacy, protected.

<IfModule mod_headers.c>
Header set Strict-Transport-Security "max-age=31536000; includeSubDomains"
</IfModule>

X-Xss-Protection (XSS attack protection)

This header stops the page from loading when a Cross-Site Scripting attack is detected. One more layer of defense against the same threat.

<IfModule mod_headers.c>
Header set X-Xss-Protection "1; mode=block"
</IfModule>

X-Frame-Options

X-Frame-Options specifies which sites are allowed to embed your website within a frame (a page loaded inside another). This cuts off "clickjacking" attacks: hiding your page behind a button on another site to trick the person clicking it. Its simplicity makes it an excellent option to implement without complications.

<IfModule mod_headers.c>
Header set X-Frame-Options "SAMEORIGIN"
</IfModule>

X-Content-Type-Options

This header only accepts one valid value and prevents browsers from trying to guess the content type of a response in a way different from what the server declared. Fewer unwanted downloads and fewer risks with the content uploaded by users.

<IfModule mod_headers.c>
Header set X-Content-Type-Options "nosniff"
</IfModule>

Referrer-Policy

The referrer policy tells the browser what origin information it should provide when clicking links to other sites. Useful for limiting the amount of data transmitted with each click.

<IfModule mod_headers.c>
Header set Referrer-Policy "strict-origin-when-cross-origin"
</IfModule>

Permissions-Policy

This policy lets you disable or enable certain web platform features, such as geolocation, both on your site and on the pages you embed. Fine-grained control over how browser features run.

<IfModule mod_headers.c>
Header set Permissions-Policy "geolocation=self"
</IfModule>

How to Check Your Security Headers

If you've already configured security headers on your site and want to check whether they're valid, you can use the external tool securityheaders.com to do so.

My Custom Code

Here's the code I use on my WordPress installations, in the .htaccess file (the Apache server configuration file).

This would be the basic code:

# Start Security Headers
<IfModule mod_headers.c>
Header set Content-Security-Policy "upgrade-insecure-requests"
Header set Strict-Transport-Security "max-age=31536000; includeSubDomains"
Header set X-Xss-Protection "1; mode=block"
Header set X-Frame-Options "SAMEORIGIN"
Header set X-Content-Type-Options "nosniff"
Header set Referrer-Policy "strict-origin-when-cross-origin"
Header set Permissions-Policy "geolocation=self"
</IfModule>
# End Security Headers

And this is the code, a bit more complete:

# Security HttpHeaders
<IfModule mod_headers.c>
Header set Content-Security-Policy "upgrade-insecure-requests"
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" env=HTTPS
Header set X-Xss-Protection "1; mode=block"
Header set X-Frame-Options "SAMEORIGIN"
Header set X-Content-Type-Options "nosniff"
Header set Referrer-Policy "strict-origin-when-cross-origin"
Header set Permissions-Policy "geolocation=self"
Header set Access-Control-Allow-Origin "*"
Header set Access-Control-Allow-Methods "GET,POST"
Header set Access-Control-Allow-Headers "Content-Type, Authorization"
Header set Cross-Origin-Embedder-Policy "unsafe-none; report-to='default'"
Header set Cross-Origin-Embedder-Policy-Report-Only "unsafe-none; report-to='default'"
Header set Cross-Origin-Opener-Policy "unsafe-none"
Header set Cross-Origin-Opener-Policy-Report-Only "unsafe-none; report-to='default'"
Header set Cross-Origin-Resource-Policy "cross-origin"
Header set X-Permitted-Cross-Domain-Policies "none"
</IfModule>