Using Subresource Integrity (SRI) in Vite with @small-tech/vite-plugin-sri
A few weeks ago I created a Subresource Integrity (SRI) plugin called @small-tech/vite-plugin-sri for Vite.
What is SRI and why should I care?
SRI is important if you don’t trust the place you’re loading resources (scripts and styles) from.
In your HTML file, you provide the hash of each external resource you’re loading. The browser then guarantees that the resource that’s loaded is the one you expected (or it doesn’t load it).
SRI was introduced on the Big Web because site owners don’t trust Content Delivery Networks (CDNs)1. On the Small Web (see What is the Small Web), we don’t trust any server, not even the one our app is being loaded from. So we use SRI for all external resources loaded by our apps.2
How do I use it?
Just add the plugin to your vite.config.js
file, like this:
import { defineConfig } from 'vite'
import sri from '@small-tech/vite-plugin-sri'
export default defineConfig({
// …
plugins: [sri()]
})
And run your build:
npx vite build
Is this for Vite only?
This plugin is specifically for Vite but Jonas Kruckenberg has a generic plugin for Rollup called rollup-plugin-sri that does the same thing, and which mine was inspired by.
Like this? Fund us!
Small Technology Foundation is a tiny, independent not-for-profit.
We exist in part thanks to patronage by people like you. If you share our vision and want to support our work, please become a patron or donate to us today and help us continue to exist.
-
I talk more about what could happen if a CDN does not support SRI in Skypack: Backdoor as a Service?. ↩︎
-
So what about the initial index HTML file that’s served? Surely a malicious server could just serve anything it wants there and all our SRI stuff becomes security/privacy theatre, as the root of our trust model is broken, no?
If we limit ourselves to the context of the browser, yes.
That’s why, for the Small Web, we need an out-of-band means (e.g., a browser extension) of verifying that the source of the initial index file is also what we expect it to be (e.g., by verifying the hash and signature embedded in the source).
Whether or not you need to do any of this, of course, depends on your threat model. For most people, I would consider it overkill as compromising a web host to such a degree to carry out a targetted phishing attack on someone is something I’d consider a state-level attack.
And yet this is the only way with a web app to truly ensure that the place you’re going to enter your all-important passphrase into is what you expect it to be. So, of course, we are going to support it. ↩︎