Guides
SPA

SPA

This plugin provides first-class support for Single Page Applications (SPAs).

Examples of SPAs include React, Vue, Svelte, etc.

The issue with SPA's

The issue with SPAs is that they don't have a server to generate a unique nonce for each request. This means you can't use nonce-based CSPs (opens in a new tab).

We solve this in a few different ways, mainly via hashing (opens in a new tab):

  • We hash any top level inline JS (Additional <scripts found in your index.html), for both build and dev mode
  • We hash all your app code for dev mode, so your CSP actually works
  • We add default CSP config for build mode and allow the option for SRI (opens in a new tab)

Installation

Usage

 
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import csp from "vite-plugin-csp-guard";
 
// https://vitejs.dev/config/
export default defineConfig({
  plugins: [
    react(),
    csp({
      dev: {
        run: true,  // Run the plugin in dev mode
      },   
      policy: {
        "script-src": ["'self'", "https://www.google-analytics.com"],    //Allow google analytics to run
        "font-src": ["'self'", "https://fonts.gstatic.com"],    //Allows fonts from Google to load
      },
      build:{
        sri: true
      }
    }),
  ],
});
 

Additional support

If you are using any pre-processors like (e.g. sass, etc) or tailwind. You will need to tell the plugin this, because these require additional support when running vite dev You can do this by adding the outlierSupport key to the plugin options.

 
import { defineConfig, PluginOption } from "vite";
import react from "@vitejs/plugin-react";
import csp from "vite-plugin-csp-guard";
 
// https://vitejs.dev/config/
export default defineConfig({
  plugins: [
    react(),
    csp({
      dev: {
        run: true,
        outlierSupport: ["less"], 
      },
    })
  ]
});
 

Caveats

If you are using a library that dynamically injects CSS into the page (e.g., styled-components, emotion, or MUI), you will need to set your style-src-elem policy to include 'unsafe-inline'.

The only alternative is to move to a server and use nonce-based CSPs.

We are actively working to find a solution to this issue (opens in a new tab), but there isn't much support for hash-based CSPs in those libraries yet.

⚠️

There are risks to using 'unsafe-inline' for your styles. However, most of these could potentially be mitigated by the rest of the CSP. Read more about this here (opens in a new tab)

Creating your policy

Need some help building your CSP policy? Check out our guide for creating a custom policy

Maintenance

Maintaining CSPs can be challenging as they are easy to get wrong and can break your site if not configured correctly.

  • Adding vite dev support via the run.dev flag is a great way to test your new third-party scripts before deploying them to production.
  • We are developing ESLint rules to help you catch common mistakes in your CSPs. Watch this space!