SecureStartKit
SecurityFeaturesPricingDocsBlogChangelog
Sign inBuy Now
Getting Started
Installation
Configuration
Deployment

Components

  • Hero
  • Pricing
  • Features

Features

  • Authentication
  • Payments
  • Emails
  • Database
  • Blog
  • Security Headers

Security Headers

Built-in HTTP security headers and how to add a Content Security Policy.

What's Included

Your template ships with production-ready security headers in next.config.ts. Every response from your app includes these headers automatically:

HeaderValueWhat it prevents
X-Frame-OptionsDENYClickjacking (your site can't be embedded in iframes)
X-Content-Type-OptionsnosniffMIME-type sniffing attacks
Referrer-Policystrict-origin-when-cross-originLeaking full URLs to third parties
X-DNS-Prefetch-ControlonN/A (performance, pre-resolves DNS)
Strict-Transport-Securitymax-age=63072000; includeSubDomains; preloadDowngrade attacks (forces HTTPS for 2 years)

These headers work out of the box with zero configuration.

Verifying Your Headers

After deploying, check your headers with any of these tools:

curl -I https://yourdomain.com

Or use securityheaders.com for a full report.

Adding a Content Security Policy (CSP)

A CSP header is not included by default because it requires tuning for your specific stack. A misconfigured CSP will silently break your site. We recommend adding one after you've finalized your third-party services.

When to add CSP

  • You've launched and know exactly which scripts, fonts, and APIs your app uses
  • You've removed or finalized your analytics, chat widgets, and other third-party tools
  • You want an A+ rating on securityheaders.com

Basic CSP (good starting point)

Add a Content-Security-Policy header to the securityHeaders array in next.config.ts:

const securityHeaders = [
  // ... existing headers ...
  {
    key: 'Content-Security-Policy',
    value: [
      "default-src 'self'",
      "script-src 'self' 'unsafe-inline' 'unsafe-eval'",
      "style-src 'self' 'unsafe-inline'",
      "img-src 'self' data: blob:",
      "font-src 'self'",
      "connect-src 'self'",
      "frame-src 'self'",
      "object-src 'none'",
      "base-uri 'self'",
      "form-action 'self'",
    ].join('; '),
  },
]

Adding third-party services

Extend each directive based on the services you use:

const cspDirectives = {
  'default-src': ["'self'"],
  'script-src': [
    "'self'",
    "'unsafe-inline'", // Required by Next.js
    "'unsafe-eval'",   // Required by Next.js dev mode, remove in production if possible
  ],
  'style-src': [
    "'self'",
    "'unsafe-inline'", // Required by Tailwind
  ],
  'img-src': [
    "'self'",
    'data:',
    'blob:',
  ],
  'font-src': ["'self'"],
  'connect-src': ["'self'"],
  'frame-src': ["'self'"],
  'object-src': ["'none'"],
  'base-uri': ["'self'"],
  'form-action': ["'self'"],
}

Then add sources for each service you use:

ServiceDirectives to update
Supabaseconnect-src: add your *.supabase.co URL. For Realtime, also add wss://*.supabase.co
Stripescript-src: add https://js.stripe.com. frame-src: add https://js.stripe.com. connect-src: add https://api.stripe.com
Google Fontsstyle-src: add https://fonts.googleapis.com. font-src: add https://fonts.gstatic.com
Google Analyticsscript-src: add https://www.googletagmanager.com. connect-src: add https://www.google-analytics.com
Umamiscript-src: add your Umami domain. connect-src: add your Umami domain
Vercel Analyticsscript-src: add https://va.vercel-scripts.com. connect-src: add https://vitals.vercel-insights.com

Example: full CSP with Supabase + Stripe

{
  key: 'Content-Security-Policy',
  value: [
    "default-src 'self'",
    "script-src 'self' 'unsafe-inline' https://js.stripe.com",
    "style-src 'self' 'unsafe-inline'",
    "img-src 'self' data: blob: https://*.supabase.co",
    "font-src 'self'",
    "connect-src 'self' https://*.supabase.co wss://*.supabase.co https://api.stripe.com",
    "frame-src 'self' https://js.stripe.com",
    "object-src 'none'",
    "base-uri 'self'",
    "form-action 'self'",
  ].join('; '),
}

Nonce-based CSP (advanced)

For stronger security, you can use nonces instead of 'unsafe-inline'. This requires Next.js middleware to generate a nonce per request:

  1. Create middleware.ts at the project root
  2. Generate a random nonce using crypto.randomUUID()
  3. Inject the nonce into your CSP header
  4. Pass the nonce to Next.js via <Script nonce={nonce} />

See the Next.js CSP docs for the full middleware setup.

Debugging CSP violations

CSP violations show up in the browser console as errors like:

Refused to load the script 'https://example.com/script.js'
because it violates the Content Security Policy directive: "script-src 'self'"

Tip: Start with Content-Security-Policy-Report-Only instead of Content-Security-Policy during development. This logs violations without actually blocking anything, so you can identify all required sources before enforcing the policy.

{
  key: 'Content-Security-Policy-Report-Only', // Switch to Content-Security-Policy when ready
  value: '...',
}

Additional Headers to Consider

These headers aren't included by default but are worth adding for specific use cases:

HeaderUse case
Permissions-PolicyDisable browser features you don't use (camera, microphone, geolocation)
Cross-Origin-Opener-PolicyIsolate your browsing context (set to same-origin if you don't use cross-origin popups)
Cross-Origin-Resource-PolicyPrevent other sites from loading your resources
// Example: disable unused browser features
{
  key: 'Permissions-Policy',
  value: 'camera=(), microphone=(), geolocation=()',
},