CentercodePorygon
DittoPorygonAPI

Security Headers

HTTP security headers and CORS configuration

Safe

Overview

Apply security headers to protect against common web vulnerabilities. CORS, CSP, HSTS, and other headers are centralized in middleware.

What it is

HTTP response headers that protect against XSS, clickjacking, MIME sniffing, and other attacks.

Why we use it

Defense in depth - headers provide protection even if application code has vulnerabilities.

When to use

All responses. Configure createSecurityMiddleware() in proxy.ts or middleware.ts.

Key Features

  • CORS with origin validation and Vary header
  • Content Security Policy configuration
  • HTTPS enforcement with HSTS
  • Clickjacking prevention with X-Frame-Options

Quick Start

Configure Security Middleware

Configure security middleware with createSecurityMiddleware().

// Security middleware factory (proxy.ts or middleware.ts)
import { createSecurityMiddleware } from '@/middleware/security';

const security = createSecurityMiddleware({
  cors: {
    allowedOrigins: ['https://app.example.com'],
  },
  headers: {
    enableHSTS: process.env.NODE_ENV === 'production',
    csp: 'auto', // Uses strict in production, relaxed in dev
  },
});

export async function middleware(request: NextRequest) {
  return security.handle(request);
}

Patterns

CORS Configuration

Handle cross-origin requests securely.

// CORS is configured via createSecurityMiddleware
import { createSecurityMiddleware } from '@/middleware/security';

const security = createSecurityMiddleware({
  cors: {
    // Allowed origins for CORS requests
    allowedOrigins: ['https://app.example.com', 'https://admin.example.com'],
    // Methods allowed for CORS requests
    allowedMethods: 'GET, POST, PUT, DELETE, PATCH, OPTIONS',
    // Headers allowed for CORS requests
    allowedHeaders: 'Content-Type, Authorization',
    // Allow credentials (cookies, auth headers)
    allowCredentials: true,
    // Max age for preflight cache (24 hours)
    maxAge: 86400,
  },
});

// CORS headers are automatically applied to /api/* routes
// Preflight OPTIONS requests return 204 with proper headers
// Includes Vary: Origin header to prevent cache poisoning

Content Security Policy

Configure CSP directives.

// Content Security Policy (CSP) modes
// Configured in @/middleware/security via createSecurityMiddleware

const security = createSecurityMiddleware({
  headers: {
    // CSP mode: 'auto' | 'strict' | 'production' | 'development' | custom
    csp: 'auto',
    // Enable nonce-based CSP for stronger XSS protection
    enableNonce: true,
  },
});

// Production CSP directives (csp: 'production')
// default-src 'self';
// script-src 'self' 'unsafe-inline' 'unsafe-eval';
// style-src 'self' 'unsafe-inline';
// img-src 'self' data:;
// font-src 'self' data:;
// connect-src 'self';
// frame-src 'none';
// frame-ancestors 'none';
// object-src 'none';
// base-uri 'self';
// form-action 'self';
// upgrade-insecure-requests

Security Headers

Standard security headers applied.

// Security headers applied by createSecurityMiddleware
// Source: src/middleware/security-headers.ts

const securityHeaders = {
  // Prevent clickjacking
  'X-Frame-Options': 'DENY',

  // Prevent MIME type sniffing
  'X-Content-Type-Options': 'nosniff',

  // Enforce HTTPS (only when enableHSTS: true)
  'Strict-Transport-Security': 'max-age=63072000; includeSubDomains; preload',

  // Control referrer information
  'Referrer-Policy': 'strict-origin-when-cross-origin',

  // Disable browser features
  'Permissions-Policy': 'camera=(), microphone=(), geolocation=()',

  // Content Security Policy (varies by csp mode)
  'Content-Security-Policy': '...',
};

// Note: X-XSS-Protection is deprecated and not included
// Modern browsers use CSP for XSS protection instead

Watch Out

Overly permissive CORS (Allow-Origin: *)

Don't

// Overly permissive CORS - allows any origin
export async function OPTIONS(request: Request) {
  return new Response(null, {
    headers: {
      'Access-Control-Allow-Origin': '*', // Dangerous!
      'Access-Control-Allow-Methods': '*',
      'Access-Control-Allow-Headers': '*',
    },
  });
}

Do

// Use createSecurityMiddleware for CORS
import { createSecurityMiddleware } from '@/middleware/security';

const security = createSecurityMiddleware({
  cors: {
    allowedOrigins: ['https://app.example.com'],
    allowCredentials: true,
  },
});

// Middleware handles CORS automatically:
// - Validates origin against allowedOrigins
// - Returns 403 for unauthorized origins
// - Includes Vary: Origin to prevent cache poisoning
// - Supports development mode for localhost

Missing HTTPS enforcement

Don't

// Missing HTTPS enforcement
// Allows HTTP connections - vulnerable to MITM attacks

export async function GET(request: Request) {
  const data = await getData();
  return NextResponse.json({ ok: true, data });
  // No HSTS header - browser doesn't enforce HTTPS
}

Do

// HTTPS enforced with HSTS via createSecurityMiddleware
import { createSecurityMiddleware } from '@/middleware/security';

const security = createSecurityMiddleware({
  headers: {
    // Enable HSTS in production only
    enableHSTS: process.env.NODE_ENV === 'production',
  },
});

// Adds header: Strict-Transport-Security: max-age=63072000; includeSubDomains; preload
// Browser enforces HTTPS for 2 years including all subdomains
  • CSP bypasses via unsafe-inline
  • Missing Vary: Origin header

Related

Rate Limiting

Request throttling

Authentication

Session management

API Architecture

API patterns