Back to docs
Recipe

Security Headers

Harden your Nimbus deployment with a minimal, high-signal header profile that blocks MIME confusion, clickjacking, and passive fingerprinting without breaking your app.

Overview

Security headers are the cheapest win in web hardening. A single misconfigured Content-Type header opens the door to MIME-sniffing attacks. Missing X-Frame-Options invites clickjacking. This recipe gives you a copy-paste baseline that works with Vercel, Cloudflare, or any reverse proxy.

The Profile

Apply these headers to every response. Order matters for middleware chains — place security headers before routing.

Content-Security-Policy:
  default-src 'self';
  script-src 'self';
  style-src 'self' 'unsafe-inline';
  img-src 'self' data: https:;
  connect-src 'self' https://api.getnimbus.net;
  frame-ancestors 'none';
  base-uri 'self';
  form-action 'self';

X-Content-Type-Options: nosniff
X-Frame-Options: DENY
Referrer-Policy: strict-origin-when-cross-origin
Permissions-Policy:
  camera=(),
  microphone=(),
  geolocation=(),
  interest-cohort=()

Strict-Transport-Security:
  max-age=63072000; includeSubDomains; preload

Vercel Edge

Drop this into middleware.ts at your project root. It runs on every request before your app renders.

export function middleware() {
  const headers = new Headers()
  headers.set('X-Content-Type-Options', 'nosniff')
  headers.set('X-Frame-Options', 'DENY')
  headers.set('Referrer-Policy', 'strict-origin-when-cross-origin')
  headers.set(
    'Strict-Transport-Security',
    'max-age=63072000; includeSubDomains; preload'
  )
  return new Response(null, { headers })
}

export const config = { matcher: '/((?!_next).*)' }

Testing

After deploying, validate with securityheaders.com or curl your domain and inspect the response headers. Aim for an A+ grade. If your app loads third-party scripts or frames, adjust CSP directives — never disable CSP entirely.

Next: explore CSP deep-dive for nonce-based script loading and reporting endpoints.