feat: csp nonce support
Description
This PR adds CSP nonce support for dev and build.
- In dev
- CSS imports in JS: If any script tag or
style/link[rel=stylesheet]tag has anonceattribute,@vite/clientwill inject the style tag with thatnoncevalue. - Injected
script/style/link[rel=stylesheet]tags bytransformIndexHtml: normal/post hook now can have access toctx.noncethat contains anonceattribute extracted from the HTML. Each plugins has the responsibility to inject the nonce tag if needed.
- CSS imports in JS: If any script tag or
- In build
- preload function: If any script tag or
style/link[rel=stylesheet]tag has anonceattribute, it will add the link tag with that nonce value. - nonce values in HTML: the value would be preserved for usecases like replacing the value in the middleware (e.g. nginx)
- preload function: If any script tag or
close #9719 close #11862
- Difference from
- #11864: read the value from
meta[property=csp-nonce]and use that when injecting style tag generated by CSS imports in JS- Requires a custom tag for declaring the nonce value. In my PR, Vite uses the nonce value that is already declared.
- Works with different nonce value for
script-srcandstyle-src. In my PR, that is not supported unless there's a style tag in the HTML. If we add a fallback to obtain the value frommeta[property=csp-nonce-style], we can support this case as well. - Doesn't handle injected tags by
transformIndexHtml. My PR handles that. - Doesn't handle preload function. My PR handles that.
- Works with backend integration. My PR also works.
- #11958: adds a new option
noncePlaceholderand inject that value in HTML when bundling- Adds a new option. In my PR, Vite uses the nonce value that is already declared.
- #11864: read the value from
- Things to consider
- nonce should be generated for each request. Preserving the nonce value of the input HTML might provoke a misusage of using a static value for nonce.
TODO
- [ ] Add a test case
- [ ] Warn if there's multiple nonce values
- [ ] Add docs
Additional context
This table (https://github.com/vitejs/vite/pull/11864#issuecomment-1716852907) was really helpful to think about the way to support CSP nonce. Thank you @justin-tay.
What is the purpose of this pull request?
- [ ] Bug fix
- [x] New Feature
- [ ] Documentation update
- [ ] Other
Before submitting the PR, please make sure you do the following
- [x] Read the Contributing Guidelines.
- [x] Read the Pull Request Guidelines and follow the PR Title Convention.
- [x] Check that there isn't already a PR that solves the problem the same way to avoid creating a duplicate.
- [x] Provide a description in this PR that addresses what the PR is solving, or reference the issue that it solves (e.g.
fixes #123). - [ ] Ideally, include relevant tests that fail without this PR but pass with it.
Hi,thanks for this PR,i really need this feature,
does this fix for vite react too?
my project is using CSR with vite react,am urgent need this.
Great PR! I hope this is considered by the Vite team. Looking forward to some sort of dev-side CSP for style sheets landing, this would get us one step closer in having our dev & production CSP files identical.
I think this is the most complete solution. What do you think about requiring the meta tag(s)? Essentially adding the meta tags is the configuration to inject the nonces. This prevents having to copy paste a bunch of nonces or placeholders in the .html file. Instead just editing 1 (or 2) meta tags updates everything accordingly. This also elminates the sniffing of existing elements other than the specific meta tags.
Default can be the specific nonce type, with fallback to unspecified version if the user does not want to separate them.
<meta property="csp.nonce" nonce="{some-val}" >
<meta property="csp.nonce.script" nonce="{some-other-val}" >
<meta property="csp.nonce.style" nonce="{some-val2}" >
that would be really awesome to get this in time before the upcoming 5.0 official release 😉
@q7314568 Without a non-static server, this PR won't be useful because you need to generate a nonce for each request.
@gregtwallace I think most of the case, there'll be only one script tag and one style tag. But I'll include this point in the team discussion. 👍
@ghiscoding This PR won't land in 5.0 as we're in the final phase of the release (kind a RC phase).
Thanks for the update @sapphi-red. As this does encourage better application security practices, I hope it is prioritized post 5.0 release. While it just applies to dev mode, being able to align our development CSP closer to production one forces our team to be more thoughtful about our CSP settings in production, along with letting us catch CSP errors earlier in the process. I know we have already been bit by a change which worked in dev, but our stricter production CSP caused an error.
As a rails user, add my vote for making use of the meta csp-nonce tag as it is standard in those installs. See rails docs here: https://api.rubyonrails.org/classes/ActionView/Helpers/CspHelper.html
Now that v5 is released, is there any updates on this security related improvement @sapphi-red ?
We continue to see folks running into this issue as building stricter CSPs becomes more common. Not being able to setup Vite development mode with the same nonce settings as production is the only blocker for folks to do so in many cases. I would hope a security related issue like this gets prioritized accordingly as we all try to build more secure web software together.
https://github.com/vitejs/vite/pull/11864#issuecomment-1857567464 https://github.com/vitejs/vite/discussions/5218#discussioncomment-7865651
I have been monitoring this thread and I'm curious about Vite's support for CSP nonces. While there is a workaround provided by @schamberg97 in this issue, I'd like to know if official support will be added in the near future before implementing the workaround.
Edit: I've been working on a workaround to inject a Content Security Policy (CSP) with a nonce value into each server-side render of my application. I'm dynamically importing my application based on browser support and injecting it into a script tag with the nonce, which works well for the compiled JavaScript.
However, I've encountered an issue with CSS files that are also being imported. These CSS files do not receive the nonce when they are loaded into the page. This means I need to add another middleware layer to add the nonce value to the CSS files once they are added to the page (which is after the module has been called)... is it possible to get an update on when this feature will be implemented into Vite? Thank you.
superseded by #16052