Useful HTTP headers

Summary of HTTP headers useful and fundamental for securing web pages, clients, and communication from malicious activities. HSTS, CORS, CSP, HPKP and many many others.

Set-Cookie: <name>=<value>[; <Max-Age>=<age>]
              [; expires=<date>]
                [; domain=<domain_name>]
                  [; path=<some_path>]
                    [; secure][; HttpOnly]
  • HttpOnly: any script can’t access cookie data, an empty string is returned.
  • secure: the cookie will/is server only under a secure connection

Other fields are auto-esplicative

The newer SameSite cookie header is explained here.

CORS Headers



  • Origin:
  • Access-Control-Allow-Origin: *
  • Access-Control-Allow-Methods: POST,GET
  • Access-Control-Allow-Headers: POST, GET, OPTIONS
  • Access-Control-Request-Method: POST,GET
  • Access-Control-Request-Headers: Content-Type

When a browser send a cross-origin XMLHttpRequest to a server that doesn’t respond with these headers, no access will be given to the response.

Let’s see an example:

Suppose web content on domain http://foo.example wishes to invoke content on domain http://bar.other. Code of this sort might be used within JavaScript deployed on foo.example:

var invocation = new XMLHttpRequest();
var url = 'http://bar.other/resources/public-data/';

function callOtherDomain() {
  if(invocation) {'GET', url, true);
    invocation.onreadystatechange = handler;

This will lead to a simple exchange between the client and the server, using CORS headers to handle the privileges:

Let us look at what the browser will send to the server in this case, and let’s see how the server responds:

GET /resources/public-data/ HTTP/1.1
Host: bar.other
User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.1b3pre) Gecko/20081130 Minefield/3.1b3pre
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Connection: keep-alive
Referer: http://foo.example/examples/access-control/simpleXSInvocation.html
Origin: http://foo.example

HTTP/1.1 200 OK
Date: Mon, 01 Dec 2008 00:23:53 GMT
Server: Apache/2.0.61
Access-Control-Allow-Origin: *
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive
Transfer-Encoding: chunked
Content-Type: application/xml

To note:

  • Origin header in the request from foo.example
  • *Access-Control-Allow-Origin: ** header in the response from bar.other


The Origin header clearly shows by whom the invocation has been done.

The domain bar.others answering with

Access-Control-Allow-Origin: *

has allowed anyone to include his content through cross-origin requests. If it would have restricted access only to foo.example then it would have sent back

Access-Control-Allow-Origin: http://foo.example

For more in depth and other cases than this “simple request”:

CSP or Content Security Policy

Its aim is to mitigate XSS and data injection attacks by differentiating instructions and content.

Content-Security-Policy: <policy> or X-Content-Security-Policy: <policy>

are sent by server to stipulate locations where scripts can be loaded. It also stipulate restrictions on which JavaScript function is allowed to use or not.

Alternatively, the <meta> element can be used to configure a policy, for example:

<meta http-equiv="Content-Security-Policy" content="default-src 'self'; img-src https://*; child-src 'none';">

CSP permits to specify domains that browser should consider to be valid sources of executable scripts. CSP can specify also the protocol to use like the encrypted HTTPS.


Are directives each of which describes the policy for a certain resource type or area.

A policy needs to include a default-src or script-src directive to prevent inline scripts from running, as well as blocking the use of eval().

A policy needs to include a default-src or style-src directive to restrict inline styles from being applied from a <style> element or a style attribute.

Content-Security-Policy: [directive] [source-expression]


  • Content-Security-Policy: default-src 'self' : All content must come from site’s own origin.
  • Content-Security-Policy: default-src 'self' * : allow a trusted domain and its subdomains.
  • Content-Security-Policy: default-src 'self'; img-src *; media-src; script-src : images can be included from any domain but media (audio/video) is restricted. All scripts must come from that domain.
  • Content-Security-Policy: default-src if you want all content to be loaded under SSL/TLS just set the default-src domain under HTTPS.
  • Content-Security-Policy: default-src 'self' *; img-src *: allow html and images but not Javascript. The tag script-src is not specified, so the default setting will follow default-src or “all must be loaded from the originating server”.

Other directives:

  • connect‑src
  • font‑src
  • frame‑src
  • img‑src
  • media‑src
  • object‑src
  • script‑src
  • style‑src

Source expressions:

  • none’ : Allows no resources.
  • self’: Allows resources from the host that served the page.
  • unsafe‑inline’: Allows resources embedded in the page, such as inline <script> elements, <style> elements, and javascript: URLs
  • unsafe‑eval’: Allows the use of the JavaScript eval function.

Further docs in ref:


This header is used by the server to indicate that the MIME types written in the Content-Type header should not be changed and be followed.

X-Content-Type-Options: nosniff

When a Content-Type is not specified, the browser take a guess on what type of content it has received. The directive nosniff just disable this behaviour.

Example: if the server sends a nosniff directive in response to a script tag, then the browser will ignore the response unless the MIME type matches application/javascript.


indicate if a browser should be allowed to render a page in an <iframe>, <frame> or <object>. This in order to avoid clickjacking attacks (also known as “User Interface redress attack, UI redress attack,”).

Possible directives:

X-Frame-Options: DENY
X-Frame-Options: SAMEORIGIN
X-Frame-Options: ALLOW-FROM
  • DENY : attempts to load page in a frame will fail also whed the page is loaded from the same site.
  • SAMEORIGIN: only allow page from the same origin to be loaded into the page itself.
  • ALLOW-FROM uri: the page can only be displayed in a frame on the specified origin.

Note: SAMEORIGIN and ALLOW-FROM doesn’t check if also their ancestors are in the same origin.

HSTS HTTP Strict Transport Security

protect websites against protocol downgrade attacks and cookie hijacking.

It tells the browser to only access the domain using secure HTTPS connections and never via HTTP. Note that the there will always be the firstconnection to a server on a standard unsecure port.

Strict-Transport-Security: max-age=31536000 ; includeSubDomains; preload

HPKP Public Key Pinning Extension

is a security mechanism which allow HTTPS websites to resist impersonation by attackers using mis-issued or fraudolent certificates.

The HTTPS web server serves a list of public key hashes and on subsequent connections clients expect the the server use one of those in the certificate chain. Its use must be wisely adopted because could easily make websites unavailable.


Public-Key-Pins: pin-sha256="d6qzRu9zOECb90Uez27xWltNsj0e1Md7GkYYkVoZWmM="; pin-sha256="E9CZ9INDbd+2eRQozYqqbQ2yXLVKB9+xcprMF+44U1g="; report-uri=""; max-age=10000; includeSubDomains

  • pin-sha256=”<sha256>: base64 encoded Subject Public Key Information fingerprint.
  • max-age=SECONDS: time that the browser should remember the rule.
  • includeSubDomains: (optional) apply to all subdomains.
  • report-uri=”<URL>: (optional) pin validation failures will be reported to the given URL.


This header enables the Cross-site scripting (XSS) filter in your browser.

X-XSS-Protection: 1; mode=block

  • 0 : filter disabled
  • 1 : filter enabled, browser will sanitize tha page
  • mode=block: rather than sanitize the browser will block the render of the page
  • report=”<url>”“: sanitize + report violation

Other header examples are

  • Referrer-Policy: no-referrer
  • Expect-CT: max-age=86400, enforce, report-uri=<url>
  • X-Permitted-Cross-Domain-Policies: none.