Cybersecurity

Hardening Modern Web Apps: Implementing Content Security Policy (CSP) Headers and Strict CORS Rules in Next.js Middleware

Laurince Quijano
Laurince Quijano
July 23, 20267 min read
Hardening Modern Web Apps: Implementing Content Security Policy (CSP) Headers and Strict CORS Rules in Next.js Middleware

Security is often treated as an afterthought in modern web development until a data breach or Cross-Site Scripting (XSS) exploit occurs. As web applications consume dozens of external analytics tools, payment widgets, and third-party scripts, the attack surface expands exponentially.

Without strict HTTP security headers, malicious scripts injected via compromised NPM packages or third-party dependencies can silently steal session tokens, read local storage data, and exfiltrate user inputs.

To defend web applications at the infrastructure level, developers must enforce a Strict Content Security Policy (CSP) and robust Cross-Origin Resource Sharing (CORS) rules using Next.js Edge Middleware.

Here is a technical blueprint for securing Next.js applications against modern XSS and data exfiltration threats.


Understanding Content Security Policy (CSP)

A Content Security Policy is an HTTP response header that instructs the browser on which dynamic resources are permitted to load and execute.

By default, an unconfigured browser will execute any inline <script> tag or external JavaScript file requested by the DOM. A strict CSP restricts resource execution by defining allowed origins for: * script-src: Allowed JavaScript execution sources. * style-src: Permitted CSS stylesheets and inline styles. * img-src: Trusted image hosts and data URIs. * connect-src: Permitted API endpoints for fetch and WebSocket connections. * frame-ancestors: Controls whether your site can be embedded inside <iframe> tags (defending against Clickjacking).


Step-by-Step Implementation in Next.js Middleware

1. Dynamic Nonce Generation for Inline Scripts Modern frameworks like Next.js require inline hydration scripts to boot up. To allow these legitimate inline scripts while blocking unauthorized XSS injection, we generate a cryptographically secure random nonce (number used once) per request inside Edge Middleware.

typescript
import { NextResponse } from "next/server";
import type { NextRequest } from "next/server";

export function middleware(request: NextRequest) {
  // 1. Generate a random base64 nonce per request
  const nonce = Buffer.from(crypto.randomUUID()).toString("base64");

  // 2. Define the strict Content Security Policy
  const cspHeader = `
    default-src 'self';
    script-src 'self' 'nonce-${nonce}' 'strict-dynamic' https://www.googletagmanager.com;
    style-src 'self' 'unsafe-inline';
    img-src 'self' blob: data: https://laurincequijano.com;
    font-src 'self';
    object-src 'none';
    base-uri 'self';
    form-action 'self';
    frame-ancestors 'none';
    connect-src 'self' https://www.google-analytics.com;
    upgrade-insecure-requests;
  `.replace(/\s{2,}/g, " ").trim();

  // 3. Clone request headers and inject nonce for Server Components
  const requestHeaders = new Headers(request.headers);
  requestHeaders.set("x-nonce", nonce);
  requestHeaders.set("Content-Security-Policy", cspHeader);

  // 4. Construct response with security headers
  const response = NextResponse.next({
    request: {
      headers: requestHeaders,
    },
  });

  response.headers.set("Content-Security-Policy", cspHeader);
  response.headers.set("X-Frame-Options", "DENY");
  response.headers.set("X-Content-Type-Options", "nosniff");
  response.headers.set("Referrer-Policy", "strict-origin-when-cross-origin");
  response.headers.set("Permissions-Policy", "camera=(), microphone=(), geolocation=()");

  return response;
}

export const config = {
  matcher: [
    {
      source: "/((?!api|_next/static|_next/image|favicon.ico).*)",
      missing: [
        { type: "header", key: "next-router-prefetch" },
        { type: "header", key: "purpose", value: "prefetch" },
      ],
    },
  ],
};

2. Restricting API Origins with CORS in Next.js Routes When building API routes that process user requests or third-party webhooks, you must enforce explicit CORS checks to prevent unauthorized web domains from querying your backend:

typescript
import { NextResponse } from "next/server";

const ALLOWED_ORIGINS = [
  "https://laurincequijano.com",
  "https://app.laurincequijano.com",
];

export async function POST(request: Request) {
  const origin = request.headers.get("origin");

  // Verify origin domain against allowed list
  if (origin && !ALLOWED_ORIGINS.includes(origin)) {
    return new NextResponse(
      JSON.stringify({ error: "CORS Policy: Origin forbidden" }),
      { status: 403, headers: { "Content-Type": "application/json" } }
    );
  }

  const response = NextResponse.json({ success: true, message: "Request processed securely" });

  if (origin && ALLOWED_ORIGINS.includes(origin)) {
    response.headers.set("Access-Control-Allow-Origin", origin);
    response.headers.set("Access-Control-Allow-Methods", "POST, OPTIONS");
    response.headers.set("Access-Control-Allow-Headers", "Content-Type, Authorization");
  }

  return response;
}

Core Security Headers Breakdown

Header NameRecommended ValueProtection Goal
Content-Security-Policydefault-src 'self'; script-src 'nonce-...'Blocks unauthorized XSS & script exfiltration
X-Frame-OptionsDENYPrevents Clickjacking attacks via <iframe>
X-Content-Type-OptionsnosniffBlocks MIME-type sniffing exploits
Referrer-Policystrict-origin-when-cross-originProtects sensitive URL params in outbound links
Permissions-Policycamera=(), microphone=()Disables hardware API access unless explicitly granted

By layer-protecting your application with Edge Middleware nonces, CSP directives, and strict CORS filters, you ensure your web applications meet enterprise compliance standards while safeguarding user data against modern security threats.

Laurince Quijano
Written By

Laurince Quijano

Full-Stack Architect

Award-winning Web Developer with 10+ years of experience. Specializing in enterprise Next.js performance, custom Magento plugins, API integrations, and Technical SEO infrastructure.

Need premium developer consulting?

Let's discuss how we can build API split checkouts, dynamic Next.js interfaces, or speed audits for your business.

Get in Touch