trezy / next-safe

https://trezy.gitbook.io/next-safe/
BSD 3-Clause "New" or "Revised" License
170 stars 20 forks source link

Mitigations for being unable to use a nonce #5

Open alex-r89 opened 3 years ago

alex-r89 commented 3 years ago

Hi there,

I had a read of this and it seems like I am unable to use a nonce for my style-src (Im using CSS in JS (styled-components)). I believe this is also the case for 'script-src' - im seeing the same error.

I was therefore wondering, what would be the "next best" values for these? If I have to use 'unsafe-eval' or 'unsafe-inline' for these to get around this, is there any point in me using this package?

Apologies for asking this here, its not really an issue.

Thanks

SimeonGriggs commented 3 years ago

This package is terrific, thanks for putting it together.

But additionally yeah I'd like to see handling for inline Scripts (such as pushing window.dataLayer events) unless you've got a workaround for this?

trezy commented 3 years ago

TL;DR

There's not a good option for implementing strong CSP on a Next.js application until we can solve #23993.


Yeah, I should probably add something about this to the README. Unfortunately, nothing has changed since this past June. We still don't have access to a nonce or hashes when rendering headers, which means we can't handle inline scripts in any significant way.

However, I'm trying to connect with the Next team to solve that problem. In the meantime, your options for strong CSP in a Next application are:

  1. For the strongest CSP, put it behind a reverse proxy like Apache or nginx so you can you set your own headers.
  2. Use next-safe. next-safe sets strong CSP headers for everything except for inline scripts and styles, which prevents a lot of issues that could occur. Because it doesn't handle inline scripts, however, it misses out on one of the most valuable pieces of setting a strong CSP.
  3. Use a CSP <meta> tag, like @leerob has written about in the Next docs. This allows your application to set a stronger CSP than using next-safe, but it also exposes your application to MITM attacks from malicious scripts. If the user is using a browser extension with malicious code, for example, it could inject a script above the meta tag before the document is passed to the renderer, allowing that script to act like it came from your site and access domain-locked resources.
nibtime commented 2 years ago

Hi,

I played around with 'strict-dynamic' + hashes for static pages and Next 12, because it seems impossible to use nonces for static pages (build-time prerendered). I wrote a custom Head component that injects hashes of all Next.js framework scripts into a CSP meta tag in _document and then used edge middleware to inject CSP from pre-rendered meta tags into response headers before the page gets served.

I wrote a more detailed comment here: https://github.com/vercel/next.js/discussions/31402#discussioncomment-2063781

Code of my experiments: https://gist.github.com/nibtime/844b0286f3c73f30488118625d11a5d1

trezy commented 2 years ago

This is really interesting, @nibtime. We actually have #12 already for creating an edge middleware, we just haven't gotten around to doing it yet. I'm going to do a deeper dive into your code today to see what would be necessary to implement it directly into next-safe.

If you're game to pair on that work at some point, I'd love to do so. Feel free to join my Discord and hit me up. https://discord.gg/k3bth3f

nibtime commented 2 years ago

Hi @trezy

If you're game to pair on that work at some point, I'd love to do so. Feel free to join my Discord and hit me up.

Sure, I'd love that. I also just started with the CSP topic, the code at this point is mainly a verification for my understanding around CSP and Next and as a PoC if 'strict-dynamic' was possible with static pages at all in a feasible way. I will join your Discord some time.

I created a fresh issue (#36) with details towards implementing this.

I think this could really benefit from being properly packaged up, documented and e2e tested within next-safe, as this isn't something you would want to handle at the project level. I am also not inclined to make a own package, as I personally wouldn't want to see 100 different libs handling the same already confusing topic :)