Security Headers for ASP.Net and .Net CORE

Website report showing we received an A

For those who do not follow myself or Franziska Bühler, we have an open source project together called OWASP DevSlop in which we explore DevSecOps through writing vulnerable apps, creating pipelines, publishing proof of concepts, and documenting what we’ve learned on our YouTube Channel and our blogs. In this article we will explore adding security headers to our proof of concept website, This blog post is closely related to Franziska’s post OWASP DevSlop’s journey to TLS and Security Headers. If you like this one, read hers too. 🙂

Franziska Bühler and I installed several security headers during the OWASP DevSlop Show in Episode 22.1 and 2.2. Unfortunately we found out that .Net Core apps don’t have a web.config, so the next time we published it wiped out the beautiful headers we had added. Although that is not good news, it was another chance to learn, and it gave me great excuse to finally write my Security Headers blog post that I have been promising. Here we go!

Our web.config looked so…. Empty.

Just now, I added back the headers but I added them to the startup.cs file in my .Net Core app, which you can watch here. Special thanks to Damien Bod for help with the .Net Core twist.

If you want in-depth details about what we did on the show and what each security header means, you should read Franziska’s blog post. She explains every step, and if you are trying to add security headers for the first time to your web.config (ASP.Net, not .Net CORE), you should definitely read it.

The new code for ASP.Net in your web.config looks like this:

<! — Start Security Headers →
<add name=”X-XSS-Protection” value=”1; mode=block”/>
<add name=”Content-Security-Policy” value=”default-src ‘self’”/>
<add name=”X-frame-options” value=”SAMEORIGIN”/>
<add name=”X-Content-Type-Options” value=”nosniff”/>
<add name=”Referrer-Policy” value=”strict-origin-when-cross-origin”/>
<remove name=”X-Powered-By”/>
<! — End Security Headers →

Our new-and-improved Web.Config!

And the new code for my startup.cs (.Net CORE), looks like this (Thank you Damien Bod):

//Security headers make me happy
app.UseHsts(hsts => hsts.MaxAge(365).IncludeSubdomains());
app.UseReferrerPolicy(opts => opts.NoReferrer());
app.UseXXssProtection(options => options.EnabledWithBlockMode());
app.UseXfo(options => options.Deny());

app.UseCsp(opts => opts
.StyleSources(s => s.Self())
.StyleSources(s => s.UnsafeInline())
.FontSources(s => s.Self())
.FormActions(s => s.Self())
.FrameAncestors(s => s.Self())
.ImageSources(s => s.Self())
.ScriptSources(s => s.Self())
//End Security Headers

Our beautiful security headers!

In future episodes we will also add:

  • Secure settings for our cookies
  • X-Permitted-Cross-Domain-Policies: none
  • Expect-CT: (not currently supported by our provider)
  • Feature-Policy: camera ‘none’; microphone ‘none’; speaker ‘self’; vibrate ‘none’; geolocation ‘none’; accelerometer ‘none’; ambient-light-sensor ‘none’; autoplay ‘none’; encrypted-media ‘none’; gyroscope ‘none’; magnetometer ‘none’; midi ‘none’; payment ‘none’; picture-in-picture ‘none’; usb ‘none’; vr ‘none’; fullscreen *;

For more information on all of these security headers, I strongly suggest you read the OWASP Security Headers Guidance.

We now have good marks from all of the important places, https://securityheaders.com and, but hope to improve our score even further.

For more information, watch our show! Every Sunday from 1–2 pm EDT, on Mixer and Twitch, and recordings are available later on our YouTube channel.

Please use every security header that is available and applicable to you.

For content like this and more, check out my book, Alice and Bob Learn Application Security and my online community, We Hack Purple!

HSTS Preloading of all .Dev domains: Troubleshooting

I’ve been quietly planning out for the past little while, with the intent to announce it while at RSAC last week in San Francisco. My new site provides regular security content for a modest fee ($7/month), all created by yours truly, on the topics of DevSecOps, AppSec, Cloud Security, MFA, etc. Soon I will be releasing full length training courses on these topics, also at affordable prices.

** Our company website is now

That said, when I pointed my domain at (the place that is hosting my content), I followed the directions, and it did not work. The link worked, but the apex domain,, was throwing a security error. The instructions were to point the CNAME record for “www” to the Podia address for my content, no problem. Then forward the apex domain (no “www” at the front), to the www address for my site. I wasn’t sure why but the following error was thrown in all browsers.

HOW EMBARRASSING! I teach how to implement HSTS, then I can’t get it right? Ahh!

By this point I knew it was an HSTS problem, and that I was being pre-loaded, so I tried to remove my URL from being pre-loaded. Sounds easy right? Nope.

Being rejected by the HSTS Preload Page

At this point I felt I had to ask for help, people were clicking on the links from my presentations and getting this embarrassing error. Time to swallow my pride. I called GoDaddy, the ones who sold me the “.dev” domain name, and they had no idea. I called Podia, and they were also at a loss.

My sharing my feelings with the Chromium Dev Team.

They did not answer my accusatory tweet.

So then I did what I always do when I’m completely stuck; I asked my brilliant twitter followers.

Within 10 minutes someone pointed out that Google had purchased the entire “.dev” domain (I didn’t know that was possible) and decided to force pre-loading of the HSTS security header on all of the domains under .Dev. THAT was why I could not get my URL to stop being pre-loaded. This news surprised me because 1) shouldn’t GoDaddy have known this was the issue since they sold me the .dev domain? 2) forcing a security feature on everyone often leads to poor results and 3) apparently some people think that “.dev” means a site that is under development, when it actually means “for developers”. No one is going to buy a completely separate domain so they can host their dev stuff on it, internal to their own networks. That makes zero sense folks.

In summary, I bought a .dev because I thought that’s where all the cool kids were, but it turns out that the .dev addresses come with baggage. My emails from my new domain are too-often caught in spam filters, and now this HSTS situation… But I digress.

read a few articles on this topic, and I learned that the TLS handshake couldn’t be completed on the apex (my domain without the “www” at the front), because I had it forwarding to my www domain. HSTS forces you to complete the handshake. GoDaddy’s forwarding feature doesn’t complete it, it just forwards it directly, which is not enough for HSTS, it’s strict.

Once I knew what the problem was, then I had to figure out a way to hack around it. I’m stubborn and did not want to have to start all over with a new domain. No way.

Luckily a whole bunch of my followers had great ideas. Michael Buckbee was particularly helpful, helping me figure out that the APEX ( needed to terminate the TLS, so then I just needed to figure out how to do it. PS Thanks Michael!

This is where I turned to CloudFlare. No, this is not an advertisement for them, we aren’t affiliated (but if they want to buy a subscription to my site that would be cool!).

CloudFlare protects sites from DDOS and other internet problems, and in the process they *forward* your traffic. GREAT, I needed my traffic forwarded. And since they are a security company they terminate the TLS. PERFECT.

First I set up CloudFlare, which was super-simple. They have a free plan and I choose that one, so far so good.

Then I created a Page Rule to forward my Apex URL to my www URL, like so.

My CloudFlare Page Rule

And BOOM, is no longer broken, and I can post content for all to find. 😀

For content like this and more, check out my book, Alice and Bob Learn Application Security and my online community, We Hack Purple!