Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CSP support #11793

Open
pi0 opened this issue Sep 29, 2021 · 18 comments
Open

CSP support #11793

pi0 opened this issue Sep 29, 2021 · 18 comments

Comments

@pi0
Copy link
Member

pi0 commented Sep 29, 2021

Nuxt 2 implementation:

I guess we can try making an standard unjs package and use in nitro server + allow a pluggable approach for both middleware and app to declare other scripts to be included in CSP policy

Upstream: unjs/h3#336

@P4sca1
Copy link
Contributor

P4sca1 commented Oct 22, 2021

Would be great if the nuxt3 CSP implementation could support csp3 strict-dynamic (#7451) and automatically generate a csp nonce on every request that is easily accessible (#6811).

@Baroshem
Copy link
Contributor

Hey folks,

For anyone contributing to this issue. In my security module for nuxt there is a CSP configuration available. Let me know if you have some recommendations so that I could implement them as a part of the module :)

@tnabil
Copy link

tnabil commented Sep 27, 2023

Team, two years from when this issue was created, do we have a solution in place? The security module mentioned in some of the comments uses "unsafe-inline", so is definitely not a secure option. Even if we do not have an end-to-end solution, is there at least a way to ensure that all script tags are added dynamically so that we can layer a custom solution on top of that by, for example, manually calculating hashes?

@Tristan971
Copy link

Tristan971 commented Sep 27, 2023

Actually, there's some (albeit slow) progress on the vite side of things vitejs/vite#11864 which is quite important especially for the CSS part of it all

@tnabil
Copy link

tnabil commented Sep 27, 2023

@Tristan971 Had a quick look and it seems to be focused on the use of a nonce, which doesn't work for us, since we don't do SSR.

@Tristan971
Copy link

I fully understand your predicament, as we do CSR too here.

The problem is that you CAN already compute chunk files hashes during the build now, and then edit the rendered HTML via Nitro hooks during serving.
But most of the work going on in your app happens via JS in vite's applyStyles etc functions, and that isn't transitively trusted as far as I can tell, even with strict-dynamic.

For now I'm waiting to see what happens when vite has a solution at all, which will almost certainly be nonce-based, and then we can see if it's adaptable somehow to hashes, but I wouldn't hold my breath for it.

Alas, CSP support isn't in extremely high demand (or rather, we are all probably a bit too polite for our own good when asking for it), so we'll take what we can get until someone invests their own time in making things move forward.
Even if that means years of security compromises...

@tnabil
Copy link

tnabil commented Sep 27, 2023

Thanks @Tristan971. I'm not very hopeful that the nonce-based approach would work for hashes. If my understanding is correct, strict-dynamic allows script tags with a src attribute if they have the right nonce, but it doesn't allow that for hashes.
Looks like you've dabbled with vite and understand some of its inner workings. Where would be the best place for me to start if I wanted to customise the way those tags are rendered? I know you mentioned Nitro hooks, but have you come across any specific guides?

@dargmuesli
Copy link
Member

You could check out how nuxt-security adds nonces and adapt that for hashes: https://github.com/Baroshem/nuxt-security/blob/0d36fec295e9b8bb2d5749d3330ff88397fe8ac6/src/runtime/nitro/plugins/99-cspNonce.ts#L25

@Tristan971
Copy link

Tristan971 commented Sep 27, 2023

When I dabbled in that area, adding nonces like that wasn't enough (took a very similar approach at the time), due to the way styles are dynamically applied by Vite, but maybe I missed something back then.

Probably worth another look, or waiting for vite... will see

@tnabil
Copy link

tnabil commented Sep 29, 2023

Wanted to come back here and update everyone with my findings so far. I was planning to start looking at Nitro hooks to replace script tags with one that adds all libraries dynamically. I was also planning to look at Vite to see if there is a way to calculate hashes during build time and inject the output into the config that will drive the CSP header.

However, while I was doing the preparation work for this, I found out that none of it is necessary! Without listing any hashes in my CSP, I could use 'strict-dynamic' in the script-src directive and it just works. Nuxt must be really doing something right to make this work out of the box!

The only change I had to do was remove a script that was being inserted using app.head in nuxt.config.ts and replace that with a dynamic script using useHead where I declare the innerHTML attribte of the script as a string containing a script that dynamically adds a script element for each of the scripts I need, as described in the article I linked to earlier.

 script: [
    {
      innerHTML: `var scripts = [ 'some-library.js', 'another-library-url.js' ];
          scripts.forEach(function(scriptUrl) {
            var s = document.createElement('script');
            s.src = scriptUrl;
            s.async = false;
            document.head.appendChild(s);
          });`
    }
  ]

I must say I'm quite surprised by this behaviour, given that when I put my CSP into the csp-evaluator tool, it basically says that strict-dynamic without hashes will block all scripts, but I tested it and our code is working just fine. I will continue to test and update here with any further findings.

@tnabil
Copy link

tnabil commented Oct 9, 2023

Just a quick update that the behaviour I described above changed as soon as I started deploying to the actual environments (i.e. not locally). Unsurprisingly, I had to add a hash for the main block of JS code generated by Nuxt, but only one hash so far.

@tnabil
Copy link

tnabil commented Oct 13, 2023

Given I still need to specify at least one hash in my CSP, I would like to find a way to calculate that hash at build time so that I can use it in a later step in the build process to inject it into the configuration that will drive the CSP header. I looked at the approach used in nuxt-security as suggested by @dargmuesli but that is using Nitro hooks, which are runtime. According to the docs, I should be using a Nuxt hook, which is build time. I experimented with several hooks, but I cannot find any that is called after pre-rendering and that will give me access to the pre-rendered assets. Does anyone have any pointers or can suggest alternate approaches?

@danielroe
Copy link
Member

Yes, the Nuxt hook nitro:build:public-assets is likely what you want.

@tnabil
Copy link

tnabil commented Nov 2, 2023

Yes, the Nuxt hook nitro:build:public-assets is likely what you want.

Thanks @danielroe. I ended up using the render:response nitro hook. Admittedly, the code is getting a bit complicated now. One of our colleagues recently pointed out that nuxt-security has SSG support now here. This code looks a lot like ours, except that instead of adding a meta tag, we're using the hashes to update configuration specific to our hosting platform, which, understandably, would not be supported by the framework.
Another difference I noted is that we opted to replace all script tags with a src attribute with one inline script that dynamically adds the script tags to the body, whereas - without getting too deep into the code - nuxt-security looks to be keeping the script tags and adding the integrity attribute with the hashes to them.

@ademyalcin27
Copy link

Yes, the Nuxt hook nitro:build:public-assets is likely what you want.

Thanks @danielroe. I ended up using the render:response nitro hook. Admittedly, the code is getting a bit complicated now. One of our colleagues recently pointed out that nuxt-security has SSG support now here. This code looks a lot like ours, except that instead of adding a meta tag, we're using the hashes to update configuration specific to our hosting platform, which, understandably, would not be supported by the framework. Another difference I noted is that we opted to replace all script tags with a src attribute with one inline script that dynamically adds the script tags to the body, whereas - without getting too deep into the code - nuxt-security looks to be keeping the script tags and adding the integrity attribute with the hashes to them.

@tnabil
Does it support CSP for SPA mode ? or Is there a way for that?

@tnabil
Copy link

tnabil commented Jul 9, 2024 via email

@ademyalcin27
Copy link

Sorry, I only looked quickly at the code but never actually tested the next-security implementation, as we’re currently using our own custom implementation.

On Mon, 1 Jul 2024 at 5:25 PM, Adem Yalçın @.> wrote: Yes, the Nuxt hook nitro:build:public-assets is likely what you want. Thanks @danielroe https://github.com/danielroe. I ended up using the render:response nitro hook. Admittedly, the code is getting a bit complicated now. One of our colleagues recently pointed out that nuxt-security has SSG support now here https://github.com/Baroshem/nuxt-security/blob/0d36fec295e9b8bb2d5749d3330ff88397fe8ac6/src/runtime/nitro/plugins/02-cspSsg.ts. This code looks a lot like ours, except that instead of adding a meta tag, we're using the hashes to update configuration specific to our hosting platform, which, understandably, would not be supported by the framework. Another difference I noted is that we opted to replace all script tags with a src attribute with one inline script that dynamically adds the script tags to the body, whereas - without getting too deep into the code - nuxt-security looks to be keeping the script tags and adding the integrity attribute with the hashes to them. @tnabil https://github.com/tnabil Does it support CSP for SPA mode ? or Is there a way for that? — Reply to this email directly, view it on GitHub <#11793 (comment)>, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAVEQWL5CSVR2VZRSLLAWSTZKFRDZAVCNFSM6AAAAABKFWHUOCVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDEMBQGMYDCNBUGA . You are receiving this because you were mentioned.Message ID: @.>

Do you use SPA mode? and also do you have a chance to share your implementation in any case?

@tnabil
Copy link

tnabil commented Jul 11, 2024 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

8 participants