ElMassimo / vite_ruby

⚡️ Vite.js in Ruby, bringing joy to your JavaScript experience
https://vite-ruby.netlify.app/
MIT License
1.28k stars 117 forks source link

Vite 5.2 meta tag to support new csp nonce tagging #444

Open tvongaza opened 5 months ago

tvongaza commented 5 months ago

Description 📖

Prior to Vite 5.2, it was not possible to define a strict CSP (Content Security Policy) for style-src-elem & script-src-elem directives as Vite would dynamically generate and insert these tags into the head but did not add a nonce value needed by the stricter CSP. This can be useful if you're trying to align your development and production CSPs to be similar in scope, hopefully catching early CSP issues.

In Vite 5.2 support for client side nonce tagging of assets was added. Generated script & style tags would get tagged with a nonce if a properly crafted meta tag is detected in the document. Unfortunately rails default csp_meta_tag is not the format Vite expects.

Rails generates:

<meta name="csp-nonce" content="RANDOM NONCE" />

Vite expects:

<meta property="csp-nonce" nonce="RANDOM NONCE" />

This PR adds a new helper vite_csp_meta_tag which generates a meta tag which Vite expects, allowing the dynamically added script and style tags to be properly have a nonce set. This in turn allows for a more strict CSP for those directives.

See: https://github.com/vitejs/vite/pull/16052/files https://vitejs.dev/guide/features.html#content-security-policy-csp

Background 📜

Using Rails and Vite prior to 5.2 did not allow a strict CSP.

The Fix 🔨

Make use Vite 5.2's new CSP tagging support with a properly crafted csp-nonce meta tag.

ElMassimo commented 5 months ago

Hi Tys!

Thanks for adding this feature.

It's unfortunate that Rails and Vite use different formats for this. I wonder if Vite's helper could be modified to support both, as it's possible that other frameworks use the same format as Rails.

tvongaza commented 5 months ago

It's unfortunate that Rails and Vite use different formats for this. I wonder if Vite's helper could be modified to support both, as it's possible that other frameworks use the same format as Rails.

I agree, it would be nice if Vite and Rails used the same format for the CSP meta tag. One approach would be to modify this look up to be a bit more liberal and look for the csp nonce meta tag via meta[property=csp-nonce] & meta[name=csp-nonce]. https://github.com/vitejs/vite/pull/16052/files#diff-dc569afbb42d4c723c76a7f70f5153a65f73c26e0ad350bd3cb5934367f8f615R388

However I think it is important to note that Rails is setting the nonce value in the content attribute, which is a minor security vulnerability which could lead to nonce exfiltration (see: https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/nonce#accessing_nonces_and_nonce_hiding & https://github.com/whatwg/html/issues/2369), and Rails instead should really be making use of the nonce attribute to protect against this. I've filed a hackerone report to rails about it - it would be a breaking change for any libraries relying on it (ie Turbo looks for the csp nonce via the content attribute).

Vite should stay firm in only accessing the csp nonce via the nonce attribute to encourage best practices. They even call this out a few times in their PR:

tvongaza commented 4 months ago

The issue has bubbled through the HackerOne process and now exists as a Rails issue: https://github.com/rails/rails/issues/51580

Once fixed this would address the use of the nonce property. In the latest rails you can also pass options like csp_meta_tag(property: "csp-nonce"), which would generate a csp meta tag with both <meta name="csp-nonce" property="csp-nonce" nonce="RANDOM NONCE" />.

Alternatively, it may make sense to open a PR against Vite to look for csp-nonce meta tags with either the name or property set. I'll open a PR over there once the rails issue is addressed.

I think it makes sense to hold off on fixing it here until those issues work through their respective projects.

tvongaza commented 4 months ago

Rails PR address the content vs nonce change, requires a configuration tweak - https://github.com/rails/rails/pull/51729