HTTP Security Headers

June 15, 2022 • Blog
Share this article

The benefits of HTTP security headers

Modern web browsers (also referred to as user agent’s) support a number of protection mechanisms in the form of HTTP headers that can be used to enhance the security of web applications.

Developers are often not aware of these headers and their benefits. It is common to find applications not taking advantage of these headers. This blog post aims to discuss how HTTP headers can improve web security, outlining how the headers work and what their purpose is.


This header was introduced with the purpose of mitigating against clickjacking attacks.

X-Frame-Options is used to indicate whether the browser can render a page in an iframe, frame or object. The three possible values are:

    • DENY: The page cannot be rendered in a frame under any circumstance.
    • SAMEORIGIN: The page can only be displayed in a frame if the “framing” site is on the same origin.
    • ALLOW-FROM uri: The page can only be framed from a specific origin.

As the root cause of clickjacking is having a target site rendered in a frame by an attacking site, this header can be used to effectively mitigate such attacks. It is highly recommended to use X-Frame-Options instead of other protections against clickjacking. For example, in the past framebusting scripts were found to be insufficient in protecting against clickjacking.


MIME content sniffing is a security issue that arises when browsers try to guess the content of the files it renders. For instance, if an image file contains HTML tags in its comments and it was served with a content type not used for serving images, the browser will attempt to guess how to render the content. As soon as it sees the HTML elements it will be rendered as HTML, which can contain active content such as scripts, Flash, etc., turning an innocent image file into a potential threat. This header makes the browser load the content and display it if the content-type is the one expected.

X-Content-Type-Options has only one possible value: nosniff.

This header is supported by Internet Explorer and Chrome.

More information about MIME content sniffing can be found here.


Cross-Origin Resource Sharing (CORS), as the name states, allows websites to share content between themselves. It is common for modern websites to fetch content, such as scripts, style sheets and fonts, from third party sites.

This header allows the definition of third party websites that are permitted to access a given resource. It can be used as a mechanism to relax the restrictions imposed by Same Origin Policy, enabling sites to choose which origins are allowed to fetch its resources.

When sending “non-trivial” requests with XmlHttpRequest using verbs like PUT or DELETE, as well as containing Content-Type values other than application/x-www-form-urlencoded, multipart/form-data or text/plain, CORS plays an important role by checking whether or not the origin is authorised to perform such request.

The syntax for this header is:

Access-Control-Allow-Origin: uri

More information about CORS can be found here and here.


Modern browsers have built-in filters to protect against reflected cross-site scripting. The purpose of this header is to enable or disable the protection offered by the browser. This header was introduced by Microsoft in 2011 and is supported by modern versions of Internet Explorer and Chrome.

XSS-Protection can have the values of 0 and 1, to disable or enable the protection, respectively, as well as 1;mode=block and 1;report=uri. The former enables the protection and blocks the response instead of attempting to sanitise it. The latter also enables the filter and reports the incident to a URL via a POST request.

HTTP Strict Transport Security (HSTS)

With the increasing popularity of attacks such as sslstrip,FireSheep and other more sophisticated man-in-the-middle techniques, HSTS forms a strong countermeasure against MITM.

A server implements HSTS by setting the header Strict-Transport-Security with the appropriate expiration value and delivers the message over a HTTPS connection (for obvious reasons the header is ignored if delivered via clear text channel).

Values for Strict-Transport-Security are max-age, used to set the number of seconds in which the HSTS set up will be valid for that domain in the browser, and includeSubDomains, used to indicate that subdomains should also be covered.

The final result is that the browser turns any insecure (non-HTTPS) links in the application into secure ones. Moreover, in case the server certificate is invalid, the connection will not proceed. This header dramatically reduces the risk of man-in-the-middle attacks in the web.

HTTP Public Key Pinning

HTTP Public Key Pinning, or HPKP, is a security mechanism that replicates the functionality of certificate pinning, commonly used in mobile applications, in the world of web browsers. HPKP works based on a trust on first use model, ie the fingerprint of the server certificate gets cached locally and is considered trusted. Any subsequent connection attempts where the certificate does not match is automatically regarded as malicious.

The major benefit of certificate pinning lies on the assurance against impersonation of the client-server communication even in the case of fraudulent certificates issued by trusted but compromised certificate authorities. It is worth noting this scenario is not purely hypothetical and has happened in the past few years ago, with the Comodo hacker and Diginotar cases serving as a perfect illustration.

The web application can choose which certificate in the chain to pin: either the certificate of the root Certificate Authority, intermediate certificates or the leaf certificate (also known as end-entity). By pinning the root certificate, however, if an intermediate CA linked to the root CA gets compromised the pinning will be rendered useless as any certificates signed by the intermediate CA will be considered trusted. It is advised to pin certificates closer to the ones controlled by your organisation.

HPKP comes in the form of the header Public-Key-Pins and the syntax is a follows:

Public-Key-Pins: pin-sha256=hash; max-age=value; includeSubdomains; report_uri=url

pin-sha256: SHA-256 hash of one of the certificates in the certificate chain

max-age: the number of seconds in which the certificate pinning is considered valid

includeSubdomains: optional field to indicate whether or not subdomains should be included

report_uri: optional field containing the URL where violations of the policy will be reported

More info on HPKP can be found here.

Content Security Policy

Content Security Policy (CSP) is a security mechanism invented by Mozilla that gained significant popularity in the past year. This mechanism works as a whitelist and its purpose is to tighten how the browser loads resources such as scripts, fonts, images, CSS, media, applets, etc.

CSP is currently being touted as a very strong protection against cross-site scripting attacks. When correctly implemented, content security policy restricts the usage of inline Java Script, DOM event attributes such as onload, onclick, anchor tags that start with the “javascript://” URL scheme. Also, the usage of eval() is restricted. It mandates that scripts can only be loaded from a pre-defined URL.

In this manner, a XSS payloads such as <img src=x onerror=alert(1)> or <script src=; will not have any effect even if the application is vulnerable to cross-site scripting.

Currently there is no consensus as to how browsers need to be informed about CSP, but the Content-Security-Policy header is the most supported method.

The standard way the policy is sent from the application to the browser is by setting the header in the following manner:

Content-Security-Policy: policy

Writing CSP policies can be a complex task depending on the application. The following example from Mozilla illustrates the policy well:

Content-Security-Policy: default-src ‘self’; img-src *; media-src; script-src

The above policy says:

    • Images can be loaded from anywhere in the web
    • Media can only be loaded from and domains
    • Scripts can only be loaded from
    • default-src ‘self’ sets the value to other policies to the same domain as the application (hence, “self”). This directive establishes the default fallback to the other policies when they are not explicitly defined.

Just like with other security headers, violations of the policy can be reported with the use of the optional report-uri field.

There are many other nuances about Content Security Policy and we recommend looking further in the official standard to better understand all details about this mechanism.

Contact us

Speak with a Tesserent
Security Specialist

Tesserent is a full-service cybersecurity and secure cloud services provider, partnering with clients from all industries and all levels of government. Let’s talk.

Let's Talk
Tess head 8 min