# Content Security Policy (CSP) in the Tanstack Start Supabase Turbo kit

> Learn how to secure your Tanstack Start application with Content Security Policy (CSP) using the Tanstack Start Supabase Turbo kit.

*Canonical: https://makerkit.dev/docs/tanstack-supabase/security/csp*

---

The Tanstack Start Supabase Turbo kit provides a secure way to include [CSP headers](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/CSP) in your application. The strict, nonce-based CSP is built in `apps/web/src/lib/csp.server.ts` and emitted from the global request middleware in `apps/web/src/start.ts`.

{% sequence title="Steps to configure CSP" description="Learn how to configure CSP in the Tanstack Start Supabase Turbo kit." %}

[How to enable a strict CSP](#how-to-enable-a-strict-csp)

[Making your application compliant with CSP](#making-your-application-compliant-with-csp)

[Adding a nonce to your application](#adding-a-nonce-to-your-application)

[Modifying the default CSP configuration](#modifying-the-default-csp-configuration)

{% /sequence %}

## How to enable a strict CSP

To enable a strict CSP, you need to set the following environment variable:

```bash
ENABLE_STRICT_CSP=true
```

By default, this setting is disabled due to the overhead required for development. While this is a bit advanced, it is recommended to enable it before going to production - or at some point in your development process.

Once enabled, the CSP headers will be automatically added to the response headers using the Tanstack Start middleware. 

## Making your application compliant with CSP

Enabling a strict CSP has a few consequences on your application - you will need to make sure your application is compliant with the CSP rules.

1. You will need to add the `nonce` to any third-party script tags or stylesheets you have in your application.
2. If you make external HTTP requests, you will need to add the domains to the default list of allowed domains (by default, only requests to your Supabase project are allowed).

## Adding a nonce to your application

The per-request nonce is generated by the security-headers middleware and exposed on the global Start context. TanStack Start also emits it as a `csp-nonce` meta tag, so framework-injected scripts are tagged automatically. Inside a route component you can read the current nonce from the router options:

```tsx
import { useRouter } from "@tanstack/react-router";

const nonce = useRouter().options.ssr?.nonce;
```

If you want to pass the nonce to a Script tag, you can do so by adding the `nonce` attribute to the script tag.

```tsx
<script nonce={nonce} src="https://example.com/script.js"></script>
```

## Modifying the default CSP configuration

To modify the CSP configuration, edit the `apps/web/src/lib/csp.server.ts` file. You may need to do this to allow safe external requests that your application makes.

Add the origins your application needs to the relevant arrays — for example `CONNECT_SRC_ORIGINS` for `fetch`/XHR/websocket endpoints, `IMG_SRC_ORIGINS` for external images, or `FRAME_SRC_ORIGINS` for embedded iframes. These are then merged into the directives built by `buildContentSecurityPolicy`.

```ts {% filename="apps/web/src/lib/csp.server.ts" %}
/**
 * Additional origins allowed for `connect-src` (XHR/fetch/websocket). Add API,
 * analytics, or webhook origins here when the strict CSP is enabled.
 */
const CONNECT_SRC_ORIGINS: string[] = [
  // Turnstile verification requests.
  'https://challenges.cloudflare.com',
  // Supabase API (auth/PostgREST/Storage) + Realtime websocket.
  ...(SUPABASE_ORIGIN && SUPABASE_WEBSOCKET_ORIGIN
    ? [SUPABASE_ORIGIN, SUPABASE_WEBSOCKET_ORIGIN]
    : []),
];

/**
 * Additional origins allowed for `img-src`.
 */
const IMG_SRC_ORIGINS: string[] = [
  // Supabase Storage images.
  ...(SUPABASE_ORIGIN ? [SUPABASE_ORIGIN] : []),
];
```
