Repository navigation
nonce tag in __vitePreload (CSP) #9719
Copy link
Copy link
Closed
Labels
p3-minor-bugAn edge case that only affects very specific usage (priority)An edge case that only affects very specific usage (priority)
Description
Description
I am trying to migrate or default tooling from Webpack to Vite.
The main issue is nonce security police.
Actually, we handle it using __webpack_nonce__
https://webpack.js.org/guides/csp/
I can't interact with the preload function to change it.
vite/packages/vite/src/node/plugins/importAnalysisBuild.ts
Lines 58 to 103 in 0571232
| function preload( | |
| baseModule: () => Promise<{}>, | |
| deps?: string[], | |
| importerUrl?: string | |
| ) { | |
| // @ts-ignore | |
| if (!__VITE_IS_MODERN__ || !deps || deps.length === 0) { | |
| return baseModule() | |
| } | |
| return Promise.all( | |
| deps.map((dep) => { | |
| // @ts-ignore | |
| dep = assetsURL(dep, importerUrl) | |
| // @ts-ignore | |
| if (dep in seen) return | |
| // @ts-ignore | |
| seen[dep] = true | |
| const isCss = dep.endsWith('.css') | |
| const cssSelector = isCss ? '[rel="stylesheet"]' : '' | |
| // @ts-ignore check if the file is already preloaded by SSR markup | |
| if (document.querySelector(`link[href="${dep}"]${cssSelector}`)) { | |
| return | |
| } | |
| // @ts-ignore | |
| const link = document.createElement('link') | |
| // @ts-ignore | |
| link.rel = isCss ? 'stylesheet' : scriptRel | |
| if (!isCss) { | |
| link.as = 'script' | |
| link.crossOrigin = '' | |
| } | |
| link.href = dep | |
| // @ts-ignore | |
| document.head.appendChild(link) | |
| if (isCss) { | |
| return new Promise((res, rej) => { | |
| link.addEventListener('load', res) | |
| link.addEventListener('error', () => | |
| rej(new Error(`Unable to preload CSS for ${dep}`)) | |
| ) | |
| }) | |
| } | |
| }) | |
| ).then(() => baseModule()) | |
| } |
I'm already injecting the preload tags manually, JavaScript and CSS files.
Suggested solution
A way to inject nonce value simular to webpack.
Alternative
No response
Additional context
Example Application
Nextcloud apps
Nextcloud is modular, and allow the users to install a variety of apps.
These apps can inject scripts in many parts of nextcloud.
For secure reasons, we use CSP to prevent malicious script injections.
Content-Security-Policy: default-src 'none';base-uri 'none';manifest-src 'self';script-src 'nonce-cHQ...bz0=';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self' data:;connect-src 'self';media-src 'self';frame-src 'self';frame-ancestors 'self';form-action 'self'Validations
- Follow our Code of Conduct
- Read the Contributing Guidelines.
- Read the docs.
- Check that there isn't already an issue that request the same feature to avoid creating a duplicate.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
p3-minor-bugAn edge case that only affects very specific usage (priority)An edge case that only affects very specific usage (priority)
Activity
vinicius73 commentedon Aug 23, 2022
discussion related: #5218
dagda1 commentedon Sep 26, 2022
I have this problem also
[-]nonce tag in __vitePreload [/-][+]nonce tag in __vitePreload (CSP)[/+]VincentvD commentedon Sep 28, 2022
We're also facing this issue, coming from CRA/webpack. It would be awesome to have CSP nonce support in vite.
kmcc049 commentedon Oct 9, 2022
We are also facing this problem. ATM it makes verifying a CSP is correct very hard. We are forced to set unsafe-inline during development.
seth-seikosoft commentedon Nov 16, 2022
I'm just now running into this as well. I converted our apps to Vite a few months ago and I love using it, it's SO FAST.
I've done a little googling trying to figure out if there is a plugin that will do this and I haven't found anything.
Do we have any updates on this issue?
Carminepo2 commentedon Nov 19, 2022
Running into this issue too. I'm disabling all the dynamic import because I could not set the nonce token on the generated tags. Waiting for a solution
krossekrabbe commentedon Dec 27, 2022
Please address this, it is impossible to use a sane CSP without it.
tonymcneil commentedon Feb 21, 2023
We ended up doing this:
in vite.config.ts
All bundled script tags now get the placeholder
{SERVER-GENERATED-NONCE}which is replaced with a random value by the server on each request.ottopaulsen commentedon Mar 20, 2023
@tonymcneil Thanks for this, I also got it working for script tags. However, i tried the same trick for style tags, but it does not work. Do you know how to get this working also for style tags?
patrickglueck commentedon May 5, 2023
@ottopaulsen You can just go about it the same as for the script tags. Generic extendable example:
ulken commentedon May 16, 2023
@patrickglueck Building custom AD B2C layouts are we? 😅
patrickglueck commentedon May 16, 2023
@ulken That is absolutely correct :D
gregtwallace commentedon Oct 21, 2023
If you want an extendable example that only adds nonces on the appropriate tags, I modified the above examples to:
Preload tag is added to all style, script, and link tags but nonce is only added to style, script, and rel="stylesheet" links.
q7314568 commentedon Oct 26, 2023
does this work for vite react?i cant make it work for static file.
gregtwallace commentedon Oct 26, 2023
I am using it with Vite and React, yes:
https://github.com/gregtwallace/legocerthub-frontend/blob/master/vite.config.js
The snipet I posted doesn’t include any other plugins like react().
q7314568 commentedon Oct 27, 2023
Thanks for reply!
I try to run your repo,but didnt find where is the csp tag,
I put csp like the following:
<meta name="csp" http-equiv="Content-Security-Policy" content="default-src 'self'; font-src 'self' data:; script-src 'self'; style-src 'self' 'nonce-value'; img-src 'self' data:; connect-src 'self' %VITE_API_URL%;" data-rh="true" />and even with the setting in vite.config,the emotion and react/fontawsome still throw the error.
gregtwallace commentedon Oct 29, 2023
The script only injects the nonce into what’s in the html. Emotion injects styles using js which is not yet supported in Vite. For now I’m using unsafe-inline for styles.
q7314568 commentedon Oct 29, 2023
Finally i found a way to inject nonce value for emotion.js,thanks for your reply anyway.
tvongaza commentedon Oct 29, 2023
Mind sharing what you did @q7314568 ? Facing a similar problem with a different library and curious how you solved it.
gregtwallace commentedon Oct 30, 2023
I'm interested in your workaround too.
The only remotely sane way I've found is to add the emotion cache (https://emotion.sh/docs/@emotion/cache) with a placeholder string for nonce and then inline everything using https://github.com/richardtallent/vite-plugin-singlefile. Then the backend can replace the placeholder string in the inlined js inside index.html.
This is bad for a number of reasons and I've chosen to leave my app as unsafe-inline until Vite provides proper support to precompile the css and do a stylesheet import.
tvongaza commentedon Oct 30, 2023
The fix in #14653 seems closer to what I would expect to work. I've tried out a similar fix pulling the CSP nonce from a meta tag and it does work in my use case. The fix here is relatively small/simple, be nice if Vite would bring it in already.
q7314568 commentedon Oct 31, 2023
I mainly face the issue with emotion.js and react/fontawesome,the emotion.js can deal with the solution @gregtwallace offer,use cahce to inject nonce value to inline script/style.
About react/fontawesome,check https://fontawesome.com/docs/web/dig-deeper/security
use
disable the auto add,then import the style from node_module instead,
but the above solution only work for prod,so i change CSP rule by env variable,
dev still using unsafe-inline,and prod mode change to fixed nonce value.
i am also keeping my eyes on the feature @tvongaza metiond,still hope vite give us a way to cover both dev/prod for this.
gregtwallace commentedon Oct 31, 2023
Not sure what backend you all are using, but I ended up working around the issue last night.
While this required me doing some work to my backend server, it saved me from having to customize Vite. An alternative would be to manually edit the build after completion, but I opted for the on the fly modification to avoid the manual step.
see: gregtwallace/certwarden-backend@f127749
and: gregtwallace/certwarden-frontend@7ea6ec1
JohannesSchwegler commentedon Nov 13, 2023
I think I found a workaround without passing the nonce to vite directly. By adding the property 'script-dynamic' (https://content-security-policy.com/strict-dynamic/) to the script-src properties, everythings seems to work fine and I could remove the 'unsafe-inline' property.
Here is a short summary of my setup:
2.Replace the "nonce_by_nginx"-placeholder with a nonce on the server. I used the nginx_substituion_module for this.
subs_filter nonce_by_nginx $request_id;Hope this helps :)