Add security headers

Hosted blogs on Micro.blog are scoring F over at securityheaders.com, which obviously is not a good sign. Can these be added system-wide according to the recommendations from that site, or can they be made available via a plugin or option? The Content Security Policy is a trickier one to get correct, but even having the rest of them active would greatly increase the score, and thus security for everyone.

I’m very much in favor of this proposal, but it should probably be opt-in, as most of the security headers can cause trouble for people if configured incorrectly.

Plug-ins can’t affect HTTP headers but can add metadata to a page, so your blog’s security could be improved by installing the Meta tags plug-in and pasting in a snippet like this:

<meta http-equiv="Content-Security-Policy" content="script-src 'self'">
<meta name="referrer" content="no-referrer">

Of course, the above is just an example. You would have to tweak the configuration to fit your blog.

Setting HTTP headers is also possible if your blog uses a custom domain and is put behind a reverse proxy like Cloudflare. But that’s definitely more work and not for everyone. :sweat_smile:

1 Like

@sod Is having these directives in metadata as secure as applying them at the server level though? If this makes them easily bypassed or, worse still, incorrectly configured, then would they not be best set up on the backend? If this isn’t a concern, do you know of a reference that explains how to configure all these headers within metadata?

As far as using a Cloudflare proxy, I’d think that also puts you at the whim of CF’s sometimes draconian network moderation. You then risk people not being able to access your site if you unknowingly run afoul of their algorithms for site safety. Same goes for using CF as a CDN these days—powerful service, no doubt, but with huge caveats.

There’s no difference in security, to my knowledge. Just different tactics to deliver the policies to the browser. There are, for example, five different ways to deliver the referrer policy.

Not all policies can be delivered via meta, though, so you won’t be able to fix everything with that approach.

When it comes to a reference, I think Mozilla’s mdn web docs is a good resource. Here’s Content-Security-Policy and Referrer-Policy.

You don’t need to use Cloudflare if you don’t want to. It was just to illustrate my point with a well-known (at least to web nerds) example of a reverse proxy solution. You can choose any provider or, if that’s more your jam, run open-source reverse proxy software on a machine in your closet. :blush:

1 Like

Another reason why I still believe it best—make it opt-in as you suggest—to apply these at the server level. In this day and age, the importance of security (even for static sites) cannot be understated.

My room gets hot enough in the summer without a server running in there. Think I’ll pass. :joy:

1 Like

There’s no difference in security, to my knowledge.

I think it is slightly more secure to set the security headers at the server level instead of the HTML, as in the latter approach, the markup payload needs to be downloaded and parsed before the security measures can be applied.

Still, having the headers at any level is much better than not.

1 Like

With the added benefit that all the headers can be applied at the server level, not just a portion.

I think the “F” rating makes it sound worse than it is. Micro.blog hosted blogs are mostly just static pages where not much can go wrong, but they do load scripts from plug-ins or Micro.blog itself in some cases.

If there’s a set of headers that will work for all blogs, I’m happy to configure them. Otherwise I think the meta tags are a good approach. The way hosted blogs are purposefully isolated from the dynamic part of the platform means it’s not possible to set per-blog HTTP headers.

Thanks for clarifying this, Manton. I’ll let @sod or @chrisd chime in, as they clearly know more about this than I do. :slight_smile:

That makes sense @manton, at least as it pertains to CSPs.

However, there are some standard best practice headers missing that should be uncontroversial. Namely:

  • Strict-Transport-Security: max-age=31536000; includeSubDomains to better enforce HTTPS
  • X-Frame-Options: SAMEORIGIN to prevent iframeing
  • X-Content-Type-Options: nosniff to prevent the browser from guessing MIME types, and only rely on the declared ones
  • Referrer-Policy: no-referrer-when-downgrade to prevent referrer metadata being shared over unencrypted HTTP
1 Like

I agree with you, @chrisd, except includeSubDomains might cause trouble, especially for customers who run their blog on a custom domain. If the blog is available at example.com they might have other HTTP-only services running at news.example.com, for example.

It should be rare nowadays, but we should probably avoid forcing people to update all their services to HTTPS.

As an obscure edge case, I can also imagine people wanting to legitimately iframe their blog (or parts of it) from other origins.

1 Like

This is what I usually set, server side:

Standard Security Headers (github.com)

ctx.response.headers.set("X-Powered-By", "Blood Sweat Tears");

:point_up_2: I love this, @rickcogley. :sweat_smile:

1 Like

haha, and more of that especially if you set the CORS headers :stuck_out_tongue_winking_eye: