elk icon indicating copy to clipboard operation
elk copied to clipboard

feat: add security headers (with nuxt-security)

Open jviide opened this issue 2 years ago • 8 comments

This pull request adds the nuxt-security module to the setup, and using it to add several recommended security headers like Strict-Transport-Security and Referrer-Policy.

Personally the greatest interest lies in the Content-Security-Policy (CSP) header that can act as a good last line of defense against script injections and such. Unfortunately I couldn't find a current way to run Nuxt v3 without allowing 'unsafe-inline' in the script-src and style-src directives. In the ideal case hashes of inline scripts and styles (or per-request random nonces added to those inline elements) could be collected to get rid of the 'unsafe-inline's, realizing the full benefits of CSP. Maybe in the future!

Despite this I believe this could be a good starting point: the other headers and CSP directives still have their benefits.

In addition to the modified CSP headers, the following nuxt-security defaults have been disabled:

  • Cross-Origin-Embedder-Policy headers are disabled to allow cross-origin embeds.
  • Disabled rate limiter ~~& request size limiter~~, as I don't have enough information for possible proper values for them 🙂

jviide avatar Jan 12 '23 19:01 jviide

Review PR in StackBlitz Codeflow Run & review this pull request in StackBlitz Codeflow.

stackblitz[bot] avatar Jan 12 '23 19:01 stackblitz[bot]

Deploy Preview for elk-docs canceled.

Name Link
Latest commit 0809658b8021052b38f0b9476e59dbf78f18a7af
Latest deploy log https://app.netlify.com/sites/elk-docs/deploys/63c49ff7d11ae700086969da

netlify[bot] avatar Jan 12 '23 19:01 netlify[bot]

Deploy Preview for elk-zone ready!

Name Link
Latest commit 0809658b8021052b38f0b9476e59dbf78f18a7af
Latest deploy log https://app.netlify.com/sites/elk-zone/deploys/63c49ff70845fa00089f0433
Deploy Preview https://deploy-preview-1025--elk-zone.netlify.app
Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site settings.

netlify[bot] avatar Jan 12 '23 20:01 netlify[bot]

Hey @jviide

I am glad that you liked the module enough to recommend implementing it here!

I would recommend keeping two of these middlewares enabled as they were set with the values considered as secure (Rate Limiter has Twitter rate limitting, while request size limiter uses the values provided by Atlassian)

Baroshem avatar Jan 12 '23 22:01 Baroshem

@Baroshem Good points, and great to see you here! I re-enabled the request size limiter, as there doesn't seem to be any routes in Elk that would require large request payloads to pass.

As for the rate limit, enabling it makes sense, but in the context of Elk but I'm a bit worried about using the default rate limit of 150 tokens / hour for all routes. It seems it might be somewhat easily triggered in relatively normal scenarios - for example, multiple people behind a shared corporate IP opening a link to a post that's shared on a company channel. Or a burst of people behind a shared conference wi-fi opeing elk.zone during a talk about Elk 😉

How about enabling the rate limiter, but allowing a high but still limited amount of bursty requests? Like 600 tokens per minute or something to that effect.

jviide avatar Jan 13 '23 04:01 jviide

@jviide

Sounds good! Keep in mind that the rate limiter here is using memory-cache to store the IP's so for big application handling many many requests this may not be efficient.

At this point maybe it would be reasonable to disable this middleware and implement the same funtionality as a part of the infrastructure, not application itself by using a tool like Fail2Ban for example.

The built in rate limiter is aimed for smaller projects with less traffic.

What we can also do here is that we could try to implement another source of storage for the rate limiter so that the values are not stored in memory but somewhere else (maybe Redis?).

Let me know what you think about it 🙂

Baroshem avatar Jan 13 '23 05:01 Baroshem

@Baroshem I agree, rate limiting could be left to the infrastructure in this case. As far as I know Elk itself doesn't serve routes that need to be protected from stuff like password brute forcing attempts. As for denial of service protection, for example elk.zone is behind Cloudflare, which I assume takes care of DDoS protection. So I think leaving the rate limiting middleware off can be justified here 👍

jviide avatar Jan 13 '23 05:01 jviide

@jviide

Agree. If you will have some spare time, could you do a little research and create an issue in my repo for potential module improvements? I am always open for any feedback on what can be done better 😃

I would really appreciate it!

Baroshem avatar Jan 13 '23 06:01 Baroshem

I'm probably an idiot, but pnpm run dev after this commit on Mac OS will fail due to all requests after the first to http://localhost:5314/ being upgraded to https. Disabled nuxt-security and localhost dev started to work again.

osmaa avatar Jan 16 '23 17:01 osmaa

Interesting - I don't get it in same setup. Have you overridden NODE_ENV in any way?

danielroe avatar Jan 16 '23 17:01 danielroe

I haven't. The problem reproduces on a fresh clone of the repo and with both node 18 and 19 from Homebrew.

osmaa avatar Jan 16 '23 17:01 osmaa

hmm, apparently relatedly, also elk.zone is presenting me with security errors I haven't seen from previous versions. Clearly not the same issue as I have with dev, but also clearly to do with the new directives from nuxt-security... Browser: Safari 16.2 (17614.3.7.1.7, 17614)

image

osmaa avatar Jan 17 '23 11:01 osmaa

The Access-Control-Allow-Origin failures are likely not related to nuxt-security, but mas.to's CORS policy blocking those requests to the /nodeinfo/2.0 endpoint. These nodeinfo requests were added in these lines. Disabling nuxt-security also doesn't get rid of those errors.

jviide avatar Jan 18 '23 07:01 jviide

@osmaa Does the dev mode work for you again after https://github.com/elk-zone/elk/commit/3050350f25f7a25442bf015a2531c631b6e36331?

jviide avatar Jan 18 '23 07:01 jviide

yes it does! thank you. As for the CORS error, that indeed is unrelated and instead caused by https://github.com/elk-zone/elk/commit/2e7979817a539496925bb0b897fdee1165dfd133 which tries to fetch /nodeinfo/2.0, a GoToSocial-specific API that doesn't exist in Mastodon.

osmaa avatar Jan 18 '23 12:01 osmaa

Great 🙂 Thanks to @danielroe and @antfu for fixing the dev mode!

jviide avatar Jan 18 '23 12:01 jviide