CSP

CSP for Single Page Apps — React, Vue, Angular

Single-page apps make CSP harder because bundlers and frameworks sometimes use eval(), inject inline scripts, and load resources dynamically. Here is how to handle each framework.

React (Create React App / Vite)

CRA and Vite do not use eval() by default. A nonce-based CSP works if you are serving from a Node.js server. For static deployments (Netlify, Vercel, S3), use hashes for any inline scripts.

# Starting CSP for React on Vercel
Content-Security-Policy:
  default-src 'self';
  script-src 'self';
  style-src 'self' 'unsafe-inline';
  img-src 'self' data: https:;
  font-src 'self' data:;
  connect-src 'self' https://api.yourbackend.com;
  frame-ancestors 'none';
  object-src 'none';

The style-src 'unsafe-inline' is usually required for CSS-in-JS (styled-components, emotion). Use nonces or the strictDynamic approach to avoid it.

Next.js (App Router)

# Next.js with nonces — see our dedicated guide
Content-Security-Policy: default-src 'self'; script-src 'self' 'nonce-{nonce}' 'strict-dynamic'; style-src 'self' 'unsafe-inline';

Vue.js

Vue's template compiler does not use eval(). The runtime-only build is CSP-compatible. If you use the full build (including compiler), set script-src to allow eval:

# Vue runtime-only (recommended for production)
Content-Security-Policy: default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline';

# Vue full build (includes template compiler) — less secure
Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-eval';

Angular

Angular supports Trusted Types — the strictest CSP mode available:

# Angular with Trusted Types
Content-Security-Policy:
  default-src 'self';
  script-src 'self';
  style-src 'self' 'unsafe-inline';
  require-trusted-types-for 'script';
  trusted-types angular angular#unsafe-bypass;

Dynamic imports and code splitting

Webpack and Vite code splitting loads chunks dynamically. Add your CDN domain or use 'strict-dynamic' to allow script tags created by your trusted inline scripts:

script-src 'self' 'nonce-{nonce}' 'strict-dynamic';
# strict-dynamic propagates trust from your nonce to any script those scripts load
Generate your SPA CSP → CSPFixer