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

Add native support for SRI #2377

Open
Exelord opened this issue Mar 4, 2021 · 31 comments
Open

Add native support for SRI #2377

Exelord opened this issue Mar 4, 2021 · 31 comments
Labels
enhancement New feature or request has workaround p2-to-be-discussed Enhancement under consideration (priority)

Comments

@Exelord
Copy link

Exelord commented Mar 4, 2021

Is your feature request related to a problem? Please describe.
https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity

Describe the solution you'd like
Use https://github.com/JonasKruckenberg/rollup-plugin-sri by default to add tokens to the tags.

Describe alternatives you've considered
Guide, option

@underfin underfin added the enhancement New feature or request label Mar 5, 2021
@aral
Copy link

aral commented Mar 30, 2021

@Exelord Hey Maciej, were you able to get that SRI plugin to work in Vite 2 at all? I’ve tried adding it to plugins (and, later to just, build.rollupOptions.plugins) but all I’m seeing is crossorigin added to one of the script tags and no integrity hashes. (I’ve tried it with and without also incuding the @rollup/plugin-html as suggested in the docs.)

Update: I’ve now tried my index.html in the rollup-plugin-sri test suite and it passes so I’m going to answer my own question here and say that there is an issue while using that plugin with Vite (or Vite + Svelte) currently.

Also, I just noticed that I’m getting a non-warning warning in the output, which might be related:

rendering chunks (2)...The emitted file "index.html" overwrites a previously emitted file of the same name.

Vite config file:

import os from 'os'
import fs from 'fs'
import path from 'path'

import { defineConfig } from 'vite'
import svelte from '@sveltejs/vite-plugin-svelte'
import sri from 'rollup-plugin-sri'
import html from '@rollup/plugin-html'

const certDirectory = path.join(os.homedir(), '.small-tech.org', 'auto-encrypt-localhost')
const cert = fs.readFileSync(path.join(certDirectory, 'localhost.pem'))
const key = fs.readFileSync(path.join(certDirectory, 'localhost-key.pem'))

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [svelte()],
  server: {
    port: 444,
    https: {key, cert}
  },
  build: {
    outDir: 'dist',
    rollupOptions: {
      plugins: [html(), sri()]
    }
  }
})

(Although, as previously mentioned, same results when not including html plugin and when including sri and/or html and sri in root plugins array instead of build.rollupOptions.plugins as shown here.)

@Exelord
Copy link
Author

Exelord commented Mar 30, 2021

Hi Aral. Yeah, I had similar issue. I was not able to set it up on my own, that's why I raised this issue to handle SRI as a default Vite feature as it's not quite easy to do so independently, and it's definitely a core security feature.

Very curios if somebody had achieved that, though :)

@aral
Copy link

aral commented Mar 30, 2021

@Exelord Thanks! Looking into it further, it appears that Vite has a special hook for transforming the index HTML file: https://vitejs.dev/guide/api-plugin.html#transformindexhtml – I’m going to take a look at modifying the plugin to make use of it.

Also opened an issue there to track: JonasKruckenberg/rollup-plugin-sri#99

@aral
Copy link

aral commented Mar 30, 2021

Quick heads up: I’m rolling my own very simple Vite plugin. Will update once it’s ready.

@aral
Copy link

aral commented Mar 31, 2021

Hello again, it’s out :)

https://github.com/small-tech/vite-plugin-sri

Also note that Jonas is also working on getting his more generic/configurable rollup plugin that mine was inspired by working with Vite too. You can keep an eye on the progress of that here: JonasKruckenberg/rollup-plugin-sri#99

@patak-dev
Copy link
Member

@aral nice! @Exelord if everything you need from Vite to create this plugin is already available, let's close this issue. Consider sending the plugin to https://github.com/vitejs/awesome-vite once it is ready so others can discover it, and also share it in the #plugins channel in https://chat.vitejs.dev

@Exelord
Copy link
Author

Exelord commented Apr 1, 2021

Im also proposing to make it a default in Vite :) Its a core security feature which shouldn't be optional. The whole community can benefit from it.

@pepa-linha
Copy link

Is it possible generate SRI directly to manifest file? Not just change in index HTML file (which I don't use it).

@ElMassimo
Copy link
Contributor

@pepa-linha Created vite-plugin-manifest-sri, which might be useful for your use case.

@pepa-linha
Copy link

@ElMassimo Thanks, it looks good. (I created something similar, I have to modify the manifest more, because, for example, styles that are like input for Rollup are not generated in it)

@AdminHcat
Copy link

AdminHcat commented Sep 23, 2022

Im also proposing to make it a default in Vite :) Its a core security feature which shouldn't be optional. The whole community can benefit from it.

Just like the integrity option of VueCLI

@eloiqs
Copy link

eloiqs commented Feb 23, 2023

Hello, just wanted to let the team know: the workarounds mentionned in this thread are not ideal. None of them support integrity hashes on dynamically loaded modules.

This is blocking us from migrating from CRA to vite, as webpack-subresource-integrity (used internally by CRA) supports this, and it is a really important feature for us.

I think whatever native solution is brought into vite should have parity with webpack-subresource-integrity if possible, thanks 🙏 !

@bluwy bluwy added the p2-to-be-discussed Enhancement under consideration (priority) label Feb 24, 2023
@TimJohns
Copy link

"None of them support integrity hashes on dynamically loaded modules." - I may be in the process of making this general observation as well, but I am super-new to both Vite and Vue so I do think I'm still missing something in my understanding. I am adding my details to this thread in case others are observing something similar, looking for a little guidance myself, and offering to help, if I can.

Specifically, it appears to me that something (...probably the Vue plug in? Or vite itsef?) adds additional javascript content to the output .js files AFTER the transformIndexHtml has completed in the SRI plugins, even with enforce: 'post'. Since the SRI plugins compute the corresponding modules' Javascript files' hashes BEFORE this additional content is added, the hashes no longer represent the contents, and fail both SRI and CSP.

This appears to be the case empirically for both vite-plugin-sri and rollup-plugin-sri. I didn't actually try vite-plugin-manifest-sri, but by inspection it appears it will have the same issue.

In any case, certainly looking forward to figuring out a good way to support SRI and CSP with a statically generated single page Vue application. If anyone can help me understand and configure a build without the additional Javascript, I'd greatly appreciate it. Alternately, if there is a mechanism for ensuring that transformIndexHtml or some similar hook could run AFTER the .js files' final content is complete, I'll be happy to help update the plugins. I have so far been unable to locate where in vite or the vue plug-in this "extra code" is added, so if anyone on this thread already has that dialed in, guidance is appreciated.

And, bottom line: Thanks to everyone involved, with both Vite and the various existing SRI plug-ins; I appreciate what you have done here. Pinging for awareness, it looks like @estahn may take [over as maintainer]((JonasKruckenberg/rollup-plugin-sri#393) for @JonasKruckenberg, and @aral is already in this thread.

-Tim

@ElMassimo
Copy link
Contributor

ElMassimo commented Feb 28, 2023

@TimJohns I'm not sure vite-plugin-manifest-sri is susceptible to the problem you mentioned, as it uses writeBundle which is "the last hook of the output generation phase".

However, this plugin is meant to be used with a backend integration, and not for apps where Vite generates index.html as well.

@eloiqs
Copy link

eloiqs commented May 8, 2023

Has there been any discussions about this?

I'm thinking of trying to write a plugin for augmenting dynamic import capabilities, but it doesn't look like it would be possible.

As far as I know, the only way would be to inject a configurable document.createElement('script') based import() shim that would be able to know each bundles final contents, (or read a precomputed map of bundle ids to hashes), and include it on the script element. Anyways that's what webpack seems to be doing 😅.

From the plugin api docs it seems possible to rewrite import() statements to something else, but I can't tell if we'd have access to the bundles at that point. Can anyone advise?

@yoyo930021
Copy link
Contributor

In my case, The vite-plugin-sri and rollup-plugin-sri plugins are not work.

In transformIndexHtml generateBundle hooks, we get old content with script chunks.
Because the vite:build-import-analysis built-in plugin will override some content in generateBundle hook.
At the same time, the order of user-configured plugins cannot be later than that of built-in plugins.

...buildPlugins.post,

@yoyo930021
Copy link
Contributor

yoyo930021 commented Nov 30, 2023

In my case, The vite-plugin-sri and rollup-plugin-sri plugins are not work.

In transformIndexHtml generateBundle hooks, we get old content with script chunks. Because the vite:build-import-analysis built-in plugin will override some content in generateBundle hook. At the same time, the order of user-configured plugins cannot be later than that of built-in plugins.

...buildPlugins.post,

I make a plugin to resolve this problem
https://github.com/yoyo930021/vite-plugin-sri3

@marekdedic
Copy link

Hi,
it seems to me that both rollup-plugin-sri and vite-plugin-sri are inactive and haven't been updated in a long time - maybe that could be the motivation to include this as part of standard vite build? (I agree with somebody up the thread that there is basically no reason not to have SRI and it should be on by default...)

@patak-dev patak-dev moved this from Discussing to Later in Team Board Feb 21, 2024
@yoyo930021
Copy link
Contributor

yoyo930021 commented Feb 22, 2024

If the Vite team is interested, I'm willing to submit a PR by integrating the plugin.

@tsotimus
Copy link

Hey all, this seems a bit late - but this sort of ties into the whole CSP & SRI conversations that's happening here:

I've just released V1 of vite-plugin-csp-guard - Handles your CSP, and allows you to hash at dev and build time.
Check it out
Lots of documentation here, however planning to add more, especially when concerning SRI
Repo is here

Please check it out - any feedback is welcome!

@marekdedic
Copy link

FYI, vite-plugin-sri has been archived. So I feel the need to do this is even higher now.

@RockiRider does your plugin do SRI as well? The way I see it, CSP and SRI are orthogonal (though both useful!)

@marekdedic
Copy link

To continue, I'd be willing to help with this as well, @yoyo930021 also said they'd be willing to submit a PR.

As this discussion is long and hard to follow, let me tag a core team member - @bluwy, sorry if this is spam, but could you please chime in as to what Vite team thinks? If there are people willing to make a PR that would still be work for you, but I think we would appreciate an official stance on whether this should be part of Vite. Thanks!

@atomeon
Copy link

atomeon commented Oct 16, 2024

any updates or modern workarounds guys? 😅

@mutongwu
Copy link

for security reason, we should Have this feature, both for generated and dynamic chunks.

@neil-morrison44
Copy link

Also would like this in Vite for moving over one of the last wepback projects we've got.

The has workaround tag should probably be removed with the main 2 plugins that served as workarounds no longer being maintained

@tsotimus
Copy link

tsotimus commented Jan 4, 2025

An update for you all v2.0.0 of vite-plugin-csp-guard supports SRI.

Disclaimer There are some limitations though:

If you are lazy loading/code splitting, this is fine and the main index.js file will have an integrity hash and these lazy modules will load just fine - however these loaded modules that are added at runtime into the DOM cannot be marked by the integrity attribute.

For completeness it would be nice if this was possible, however since they are loaded in by the main index.js bundle which is already hashed, this is still better than nothing

Here are the api docs. Just needs some light config in the vite.config.ts and you should be good to go!

Try it out and let me know what you think!

threema-andre pushed a commit to threema-ch/threema-desktop that referenced this issue Jan 15, 2025
Moves SRI to the very end of the build
process (using the `closeBundle`
hook), as Vite transforms dynamic
imports after custom plugins are
allowed to run. See:
vitejs/vite#2377
@jeppeliisberg
Copy link

Due to SRI requirements by partners I am integrating with, I may be forced to move back to using Webpack after migrating to Vite just recently. I'm using Vite through the vite_rails ruby gem and the current workaround (https://github.com/ElMassimo/vite-plugin-manifest-sri) depends on an old branch of vite_rails that does not work for me. The author @ElMassimo says Vite should provide native support for SRI and for that reason won't fix/rebase, which I think is sensible.

I'm not in capacity to provide PR's or even guess about how this should be done, so unfortunately, I'm unable to contribute myself. I don't want this to come across as a rant - I just want to say that this may happen to others, and being able to pass a security scan to access APIs by certain vendors, maybe a showstopper for more people than just me.

Otherwise, thanks for a fantastic build tool!

@sapphi-red
Copy link
Member

I've checked how SRI works for ESM scripts and it seems we need to generate importmaps for it. The integrity attribute can be used for the top level module, but that script can contain import statements. So just having the integrity attributes set is not sufficient.
Import maps integrity proposal (WICG/import-maps#221, whatwg/html#10269) allows us to specify integrity for imports and is supported by Chrome 127+, Safari 18+ (not supported by Firefox yet).

@sapphi-red
Copy link
Member

I'm not sure about making this builtin as IIUC SRI only makes sense when you serve the HTML on your server and you serve assets on a different server you don't have full-control of.
But I think moving the generateBundle hook of the vite:build-import-analysis built-in plugin between these two plugins would be nice.

cssPostPlugin(config),
isBuild && buildHtmlPlugin(config),

Then a plugin can easily implement injecting the importmaps tags / integrity attributes.

@smotraghi-shopify
Copy link

I've checked how SRI works for ESM scripts and it seems we need to generate importmaps for it.

FWIW the approach taken by vite_ruby's experimental branch doesn't involve importmaps, but rather puts the digests on the preload tags. ElMassimo/vite_ruby@0b3142c#diff-676829207c8e38e54f9a846457fdacf4b034723561074343e2835252549b6035R86-R93 (NB i can't vouch that these digests are enforced)

@sapphi-red
Copy link
Member

sapphi-red commented Jan 31, 2025

FWIW the approach taken by vite_ruby's experimental branch doesn't involve importmaps, but rather puts the digests on the preload tags. ElMassimo/vite_ruby@0b3142c#diff-676829207c8e38e54f9a846457fdacf4b034723561074343e2835252549b6035R86-R93 (NB i can't vouch that these digests are enforced)

integrity attribute on modulepreload is supported by Chrome and Firefox (web platform test result). But this requires injecting preload tags before the dynamic import is called. Maybe we can add a polyfill for Firefox and older Chrome that adds integrity attribute by reading the import map, it's quite tricky to do though.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request has workaround p2-to-be-discussed Enhancement under consideration (priority)
Projects
Status: Later
Development

No branches or pull requests