DEV Community

Cover image for Frontend Security: Security Headers
Mads Stoumann
Mads Stoumann

Posted on • Updated on

Frontend Security: Security Headers

My previous articles about frontend security focused on script integrity and the Content Security Policy.

Now, It's time to look at what can be done server-side.

For these server-fixes, I'm going to use Cloudflare.

Cloudflare has a bunch of services — in their own words:

Cloudflare secures and ensures the reliability of your external-facing resources such as websites, APIs, and applications. It protects your internal resources such as behind-the-firewall applications, teams, and devices. And it is your platform for developing globally scalable applications.

They have a super-intuitive user-interface - and for most purposes, it's free!

You can find guides on their site on how to move your DNS records etc.

But maybe there's no need for you to use Cloudflare?

Before I continue, check your security-headers here:

Security Headers

If you have a red F, let's see how we can improve that with Cloudflare.

Now, the first thing to do on any server, is adding SSL (HTTPS).

In Cloudflare, go to SSL/TLS, select “Edge Certificates” and check the “Always use HTTPS” box.

Just below that, you'll see the “HTTP Strict Transport Security (HSTS)”-entry.

Click on “Change ”, accept the warnings, check “Enable HSTS”, set “Max Age Header” to (minimum) “1 month”, and check “No-Sniff Header”:

Cloudflare HSTS

UPDATE: To qualify for HSTS preloading, as mentioned in the comments, set Max-Age Header to "12 Months", and enable both "Apply HSTS policy to subdomains" and "Preload".

Now, go back to

If you had an F before, you should now have a D.

Cloudflare doesn't support the other headers out-of-the-box, but luckily they have something called Workers, where you can add them yourself.

Scott Helme has written an excellent article: The brand new Security Headers Cloudflare Worker

Because the article was written some time ago, you need to manually add the “Permissons-Policy” to Scott's list of “securityHeaders”:

let securityHeaders = {
  "Content-Security-Policy" : "upgrade-insecure-requests",
  "Strict-Transport-Security" : "max-age=1000",
  "X-Xss-Protection" : "1; mode=block",
  "X-Frame-Options" : "DENY",
  "X-Content-Type-Options" : "nosniff",
  "Referrer-Policy" : "strict-origin-when-cross-origin",
  "Permissions-Policy": "geolocation=(self \"https://your.domain\"), microphone=()"
Enter fullscreen mode Exit fullscreen mode

When set and done, deploy the worker, and head back to SecurityHeaders:

Security Headers Aplus

Wow! - from F to A+ in a matter of minutes.

Ongoing maintenance

Now, even if you've done all the things I suggest in these posts, you shouldn't rest on your laurels. Security is an ongoing activity — you need to test your site whenever a new script is added, update integrity-attributes, test SecurityHeaders etc. Whenever a new vulnerability is discovered, test again.

You can also use services like Probely or Detectify

These services will deep-scan your site and provide a “todo-list” of things, you potentially need to look into. Here's a screenshot from Detectify:


Starting from EUR 39 (Probely) and USD 50 (Detectify), these services will continuously monitor your site for security vulnerabilities.


The world of front-end is constantly expanding. It used to be simple enough to define our vocation: HTML, CSS and JavaScript — but does that include animation, email development, accessibility, SEO, tracking, performance engineering or ... security?

I'd argue that it doesn't hurt to know a bit about XSS attacks, Content Security Policy-configuration, or that SVG files can contain (harmful) scripts — but we would probably need a specific role for that, as it's a big and complex topic.

Every website should have a “Security Health-check” at least a couple of times per year. Whether or not it will be a frontend-job ... time will tell!

Top comments (8)

grahamthedev profile image
GrahamTheDev • Edited

Just a heads up for anyone who lands on this article.

Simply adding the HSTS security header is not very effective as your site is still vulnerable to downgrade attacks when a person first visits the site (or when the max age on the header has expired).

You need to go to this site and enter your site info to have HSTS preloading enabled to prevent this.

Be warned though, once you are on the HSTS preload list your site will not function over http under any circumstances so make sure you know what you are doing.

You are also then required to add "includeSubDomains; preload" to your HSTS header.

Finally a max age of 1000 is purely for testing, this should really be set to 2 years to be inline with current recommendations (two years is 63072000 seconds).

So your final header for HSTS should be:

Strict-Transport-Security: max-age=63072000; includeSubDomains; preload
Enter fullscreen mode Exit fullscreen mode

At that point you have configured this header correctly.

nunoloureiro profile image
Nuno Loureiro

You are very right with everything, except for one small detail that might make all the difference when you're evaluating risk.

You're saying that HSTS is not very effective because, on your very first visit with a browser, you're not protected? So, not being protected in one visit per browser in 2 years (assuming the max-age of 2 years), which might represent 99.9999% of the cases, is not being effective? :)

nunoloureiro profile image
Nuno Loureiro

2 more interesting (positive) notes:

  • If your domain is .app then HSTS is already preloaded by default.
  • when HSTS is set, all browser SSL/TLS warnings are upgraded into errors that cannot be bypassed to view the site
Thread Thread
grahamthedev profile image

I agree "not very effective" was probably a little heavy-handed, but "only 70% as effective" would probably be a fair assessment.

You are right, once you have been to the site you are protected...unless the server gets hacked.

Then the attacker simply sets your HSTS to 0 so it expires immediately the second someone visits the site and they can man-in-the-middle and downgrade attack to their hearts content (I make it sound easy, I am aware it is not!). It also the sort of attack that can go on for months because nobody checks their headers regularly....nobody :-P

HSTS preload means that even if that happened everyone is still protected, as well as protecting first time visitors.

Also bear in mind that once someone has successfully performed a man-in-the-middle attack an end user will likely never get the HSTS headers / meta tags that instruct the browser to upgrade insecure requests as the attacker will just strip them.

With about 20% of traffic to a typical site being new users that can soon add up!

As I said, not very effective unless you use preloading as that makes it impossible to access the site over http in nearly every major browser.

Obviously for 99% of websites none of the above is a major issue purely because they are not big enough targets to justify the effort.

But for the 1% where the risk is real HSTS must be preloaded or it is next to useless for protection.

P.S. Thanks for the interesting info about .app domains, never knew that...a good one to add to my "almost useless, mildly interesting geek facts" list I have in my head for special occasions…and I wonder why nobody wants to hang out anymore 🤣🤣🤣

madsstoumann profile image
Mads Stoumann • Edited

Thanks for the heads up! I've added an update, explaining how to achieve this in Cloudflare.

niyazpoyilan profile image
Niyaz Poyilan • Edited

My Google search just came to life through this post. This is something that i wanted for the past few days. Its a great post. Concise and helpful.
Also came across a tool called Mozilla Observatory

shostarsson profile image
Rémi Lavedrine

That's a great one.
I see very often website that go prod with bad configured headers.
I wrote something similar on a few years ago.

Happy to see another way to present it. :-)

madsstoumann profile image
Mads Stoumann

Cool, thanks for sharing.