HTTP Headers That Protect Your Users

Learn about the HTTP headers that a server should set in order to improve security and best protect the user's privacy.

By default, a simple request to download something from a web server is fairly insecure. If a website owner wants to protect the privacy and security of their users, there are a number of settings that should be configured correctly.

Setting appropriate security headers is an important step that should not be overlooked. This article will explain the key security headers, why you should use them, and how to set them up for your server.

Web Security

If you just want to check your website to see if you have the headers configured correctly, enter your domain name here and run a free test.

When a web browser requests a page from a server it makes an HTTP request. The server responds with an HTTP response. In this response there is a header and a body. The body contains the information that is intended to be displayed to the user. The header contains hidden information that can be used to instruct the web browser to modify it's behavior when displaying the page. The following headers can be used to enhance security.

HTTP Strict Transport Security (HSTS)

When a webpage includes the "Strict-Transport-Security" header, it instructs the web browser that it should always use https instead of http. It will remember this preference and it will automatically upgrade any future connection attempts that don't use SSL encryption.

All websites should use SSL and should redirect unencrypted http connections to use https. For example, a user may type "validbot.com" into the URL bar and press enter. That initial request will go to the server, unencrypted. It will then get redirected to the https URL and get loaded over an encrypted connection. The goal of HSTS is to remove that initial unencrypted connection which could open a user up to certain types of attacks.

To set this header, you can add one of the following lines to your web server's configuration. If you don't use apache or nginx there will be similar way to do this.

Apache: Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"

Nginx: add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload;" always;

We have a more detailed explanation of the Strict Transport Security Header if you are interested in customizing the values for your website and we also have an explanation of the HSTS Test that ValidBot runs as part of a full site audit.

X-Frame-Options

A feature of HTML called the iframe allows web pages to embed other pages inside the original page, like picture-in-picture. The owners of the page that is being embedded may not want to permit this for a variety of reasons. One reason is to prevent a type of attack called "click-jacking".

Click-Jacking is a type of attack where a user is tricked into clicking a link or button that they would not have otherwise clicked. For example, if the target website is embedded inside an iframe, the attacking website could place a fake button on top of the "delete account" button. When the user clicks, they may unknowingly perform a destructive action.

To prevent your website from being embedded inside an iframe, include this header.

Apache: Header always set X-Frame-Options "SAMEORIGIN"

Nginx: add_header X-Frame-Options "SAMEORIGIN" always;

We have a more detailed explanation of the X-Frame-Options Header if you are interested in customizing the values for your website and we also have an explanation of the X-Frame-Options Test that ValidBot runs as part of a full site audit.

X-XSS-Protection

This is an obsolete header. If this HTTP response header is set, a web browser will sanitize or block the loading of a page if it detects a reflected cross-site scripting (XSS) attack.

A reflected XSS attack can happen if a website takes unsanitized user input and displays it on the page where another user could see it. For example, a website's URL may contain parameters such as www.example.com?search=socks, and then on the page it may show a search bar with "socks" reflected in the input box. If the website has not taken care to sanitize the value of the "search" parameter then an attacker could put malicious code in here and trick someone into loading the malicious URL. In this example, www.example.com?search=<script> ... </script> would cause the page to run any code that the attacker wants. This code can view any information and perform any action that the user could perform on their own, so it is very dangerous.

When the "X-XSS-Protection" header is set, and the browser detects executable code in the URL, it will automatically sanitize the webpage and prevent the attack from happening. In the past, this was a good option to enable, but in modern web browsers it can actually cause more harm than good. The current recommendations are to use a CSP header instead, and to explicitly disable this legacy header by using one of the following configuration lines on your server.

Apache: Header always set X-XSS-Protection "0"

Nginx: add_header X-XSS-Protection "0" always;

We have a more detailed explanation of the X-XSS-Protection Header if you are interested in customizing the values for your website and we also have an explanation of the X-XSS-Protection Test that ValidBot runs as part of a full site audit.

X-Content-Type-Options

This HTTP Response header tells the web browser that the Content-Type headers are deliberately set and should be followed. Without this, browsers may use MIME type sniffing to guess at the Content-Type. They may do this when the Content-Type header is missing or when it is thought to be incorrect. Since some types of content are executable, this can have some security consequences. For example, a user may upload a plain-text document but trick the browser into executing it as Javascript. This is an especially important header for websites that host user-generated content. The only valid value for this header is "nosniff".

Apache: Header always set X-Content-Type-Options "nosniff"

Nginx: add_header X-Content-Type-Options "nosniff" always;

We have a more detailed explanation of the X-Content-Type-Options Header and we also have an explanation of the X-Content-Type-Options Test that ValidBot runs as part of a full site audit.

Referrer-Policy

This HTTP response header determines how much information is put into the "Referer" request header when making additional requests for resources. This should be used to limit the amount of information shared with 3rd party resources and to prevent personally identifying information in the URL from being leaked.

For example, suppose that the user loads a page with the following URL: https://www.example.com?search=socks&userid=1234. If the page loads an image hosted on a 3rd party website, or if the user clicks a link to visit a 3rd party website, that other website may see the full URL in their referral logs and will know that this particular user searched for socks. This information leakage can be prevented.

To prevent any referrer information from being sent, use the following option:

Apache: Header always set Referrer-Policy "no-referrer"

Nginx: add_header Referrer-Policy "no-referrer" always;

The above example will also block referrer information in your own logs. If you need this information for analytics purposes you may want to choose other options. We have a more detailed explanation of the Referrer-Policy Header if you are interested in customizing the values for your website and we also have an explanation of the Referrer-Policy Test that ValidBot runs as part of a full site audit.

Content-Security-Policy (CSP)

A CSP is an extra layer of security that a website can use to protect its users from Cross Site Scripting and Data Injection attacks. It works by telling the browser which domains should be trusted as valid sources for content. This way, if an attacker manages to inject malicious scripts, images or other content into the website, they won't be executed or displayed.

The following basic example will block inline scripts and styles from being run or interpreted and it will also block content that is not loaded over an encrypted SSL connection.

Apache: Header always set Content-Security-Policy "default-src https:"

Nginx: add_header Content-Security-Policy "default-src https:" always;

This policy should be carefully considered to allow the content that you intend to load, but block everything else. If your website runs 3rd party analytics software or advertisements it can be difficult to create a CSP that permits all valid sources, but it should be done because it benefits the user by protecting their experience on your website.

Check out our CSP Wizard Tool that you can use to easily generate a CSP for your website.

We have a more detailed explanation of the Content-Security-Policy Header if you are interested in customizing the values for your website and we also have an explanation of the Content-Security-Policy Test that ValidBot runs as part of a full site audit.

Permissions-Policy (Feature-Policy)

This header allows a website to disable certain features of the web browser. By disabling certain features, a user's privacy can be protected from any 3rd party code that may be running on the website. For example, if the website runs advertisements it may want to disable the microphone, camera and GPS to prevent unscrupulous advertisers from spying on the user.

This header can also be used to enforce best practices and improve performance by blocking oversized images or preventing auto-playing videos, among other things.

This header has been renamed from "Feature-Policy" to "Permissions-Policy", but the old name has more browser support, so we recommend including both headers for now. In the example below, the camera, microphone and geolocation have been disabled.

Apache: Header always set Feature-Policy "camera 'none'; microphone 'none'; geolocation 'none'"

Header always set Permissions-Policy "camera=(), microphone=(), geolocation=()"

Nginx: add_header Feature-Policy "camera 'none'; microphone 'none'; geolocation 'none'" always;

add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;

We have a more detailed explanation of the Feature-Policy Header and Permissions-Policy Header if you are interested in customizing the values for your website. We also have an explanation of the Feature-Policy Test and Permissions-Policy Test that ValidBot runs as part of a full site audit.

FLoC

Federated Learning of Cohorts (FLoC) is a new technology invented by Google to assist advertisers in showing more targeted advertisements. Third-party cookies are already used for this purpose, but many web browsers and plugins now block 3rd party cookies. With FLoC, the web browser uses machine learning to place a user into a cohort based on the websites that the user visits. This cohort is made available to advertisers so that they can target ads.

FLoC can be disabled on your website by using the Permissions-Policy described in the previous section. This will prevent your website from being used to determine the user's cohort. Here is how to do it.

Apache: Header always set Permissions-Policy "interest-cohort=()"

Nginx: add_header Permissions-Policy "interest-cohort=()" always;

Expect-CT

This header allows a website to receive reports when there is an error with SSL Certificate Transparency (CT). Additionally, it allows a website to enforce CT requirements for older web browsers. Modern web browsers already enforce CT requirements, so this header is somewhat obsolete. ValidBot does not run tests against this header for this reason. However, if you wish to receive reports when a user's web browser encounteres a CT error, you can enable this header and receive reports.

Apache: Header set Expect-CT "max-age=86400, enforce, report-uri=\"https://www.example.com/ct_report\""

Nginx: add_header Expect-CT "max-age=86400, enforce, report-uri=\"https://www.example.com/ct_report\"" always;

For more information about this header, you can read the documentation on MDN Web Docs.

ValidBot can test your website

Scan Your Site

To verify that all of the above HTTP headers are set correctly, type your domain name into the box below and run a free ValidBot Test. Look in the "Server" section for your results. If you see any errors, you should fix them to ensure that your website is served using best practices and that you are doing everything that you can to protect your users.

If you have implemented all of these security headers then you should be well on your way to having a secure website that protects its users.