Environment: server
Cumulative: false
Global: false

The +csp setting allows you to add and configure the CSP nonce, see Content Security Policy (CSP).

// pages/+config.ts
 
import type { Config } from 'vike/types'
 
export default {
  csp: { nonce: true }
} satisfies Config
 

If +csp.nonce is true, Vike generates a random string (the nonce value) for each HTTP request, stores it in pageContext.cspNonce, and appends it to <script> tags.

// Vike adds the nonce to each <script> it injects
<script nonce={pageContext.cspNonce}>
⚠️
The +csp setting is a beta feature: expect breaking changes in any minor version update. See #2665 - Stabilize +csp.

You can generate the nonce value yourself:

// pages/+csp.ts
 
import type { PageContextServer } from 'vike/types'
 
export default {
  async nonce(pageContext: PageContextServer) {
     return 'some-random-string'
  }
}

The following default CSP header is added to the HTTP response headers:

Content-Security-Policy: script-src 'self' 'nonce-${pageContext.cspNonce}'

This CSP header authorizes Vike's inline scripts (without having to open the door to all inline scripts via 'unsafe-inline').

To change the CSP header you can use the +headersResponse setting:

// pages/+headersResponse.ts
 
import type { PageContextServer } from 'vike/types'
 
export function headersResponse(pageContext: PageContextServer) {
  return {
    // Custom CSP header instead of Vike's default
    'Content-Security-Policy': `script-src 'self' 'nonce-${pageContext.cspNonce}'; img-src 'self'`
  }
}

You can also directly modify pageContext.headersResponse instead of using the +headersResponse setting.

Random string generation

If the crypto module is available, Vike uses it to generate a random string that serves as the CSP nonce:

import { randomBytes } from 'crypto'
 
// Generate a cryptographically secure nonce for Content Security Policy (CSP).
// Returns a base64url-encoded nonce string (URL-safe, no padding).
function generateNonce() {
  return randomBytes(16).toString('base64url')
}

If the crypto module isn't available (e.g. on some edge platforms), Vike falls back to:

function generateNonce() {
  return Math.random().toString(36).substring(2, 18)
}

pageContext.cspNonce

The nonce value is stored at pageContext.cspNonce.

You can directly set pageContext.cspNonce instead of using the +csp setting:

// pages/+onCreatePageContext.server.ts
// Environment: server
 
import type { PageContextServer } from 'vike/types'
 
export async function onCreatePageContext(pageContext: PageContextServer) {
  pageContext.cspNonce = 'some-random-string'
}

See: API > onCreatePageContext() hook

The +csp setting is merely a convenience to set the pageContext.cspNonce value.

PCI

Using a CSP nonce helps maintain PCI DSS compliance. Inline scripts are allowed only if they include the generated nonce (section 6.4.3 of PCI DSS 4.0.1). Avoid using 'unsafe-inline' in the CSP header's script-src, as it would violate PCI security requirements.

<!-- ❌ Not allowed -->
<script>alert('hello')</script>
 
<!-- ✅ Allowed -->
<script nonce="jy8W9w1ljXuO4Xq9rft15w">alert('hello')</script>

By generating a unique nonce for each request, Vike ensures that inline scripts remain secure and compliant.

See also