Http headers to improve your web app security

  • Philippe Savary

Modern browsers accept certain response headers so that you can enforce several security policies on the client side. This helps making your web app more secure.

There is a tool out there that will help you assess the general protection of your web application: Mozilla Observatory

The first time I've run the security test, the result was a bleak "D" (with "A+" being the best and "F" the worst). Not a particularly bad result, but no reason for celebration either. High profile sites like wikipedia (scored a "D" as well) are oviously perfectly fine with a result like this, but not us!

Screenshot of wikipedia score on observatory.mozilla.org

Wikipedia doesn't care about security headers

So what can we do?

The answer is to step up your security headers game! There are a few headers you'll have to implement in your web server configuration in order to tell the web browser running your web app what it is allowed to do and what not. Please be aware that this is no substitute for hardening your webserver security in general! Also don't think that all browsers will obey the rules you'll ask them to enforce. This is just a best practice that has been implemented to browsers in recent years. Older browsers will not support all of them.

The usual suspects:

Lets see what headers are usually not implemented by default:

  • Content Security Policy
  • X-Content-Type-Options
  • X-Frame-Options
  • X-XSS-Protection

Content Security Policy

This is a tough one to begin with. What it basically tells your browser is which external resources you'll allow it to load. This includes for example external fonts, external scripts (like Google analytics and tag manager), images and every asynchronous requests done by any script externally.
If you enforce this policy, you have to tell the browser exactly what you will allow it to load from external sources. This can get very tedious especially since google is doing all kinds of wizardry to 3rd party domains you'll sometimes don't even see in a debug window. So we've refrained from implementing it in our case (even though I've tried).

See this article if you are bold enough to try it yourself and won't fear a discussion with your friendly analytics specialist tracking the site.

For everything else on this policy I'll kindly ask you go to developer.mozilla.org


This header basically tells the browser not to assume the type of content by "sniffing out" the MIME type, but to strictly rely on the mime type sent via the response with the content-type header.

Be aware that the webserver not serves a correct mime type by default. E.g. if you cache/minify scripts/css and don't provide a content type in the response (just a file extension won't suffice). In that case that file would be rejected. Make sure your web app provides a content type header with the correct mime type in the response. If not possible, you can tell the webserver to deliver files from a certain path with a default mime type.

Documentation and details can be found here.


This header tells the the browser from which sources iframes can be shown in your web application. There is still some discussion on how web browsers should act when confronted with this header (rule is generally not enforced on frame ancestors) and yeah, it will be superceded by "Content-Security-Policy: frame-ancestors" (but is still recommended), Nevertheless, if you want to score a good result on mozilla observatory you should add it anyway.

Documentation and details can be found here.


This header tells the browser to enforce Cross-site Scripting (XSS) protection. This feature is enabled by default on modern browsers nowadays. But still: no harm done if you'll enforce it anyway (And it will give you a better rating too).

Documentation and details can be found here.


While not all security headers bring real value to the table, consider the "reputation value" a good rating on Mozilla Observatory can offer you in the next meeting with a CTO. It's like Google Page Speed but for security. Not all of it makes perfect sense, but if you don't wan't to answer inconvenient questions in the next security review, I recommend to cover all bases.

Tell us what you think