2 min read

CSP operation hardening guide

How to establish CSP policy step by step from Report-Only to Enforce conversion

CSP operation hardening guide thumbnail

Introduction

CSP is not a configuration that ends with a single line of security header. In the production environment, step-by-step hardening is necessary because third-party scripts, inline styles, and frame embedding requirements conflict. This article guides you through the practical process of moving from Report-Only to Enforcement.

CSP 운영 하드닝 가이드 커버
Wikimedia Commons 기반 무료 이미지

Problem definition

If CSP is applied hastily, normal functions may be broken, or conversely, problems may arise where policies are too loose and become ineffective.

  • It is not effective as it leaves unsafe-inline without a nonce/hash strategy.
  • The security surface continues to expand as external domain whitelists are neglected.
  • Since violation reports are not collected, the actual scope of blocking impact is unknown.

The answer is not to strictly block it all at once, but to converge after measurement. In Report-Only mode, you need to collect violation patterns and narrow down policies.

Key concepts

perspectiveDesign criteriaVerification points
Introduction stageStart Report-OnlyViolation event type
policy reductionMinimize domain whitelistNumber of unnecessary allowed items
Script Controlapply nonce/hashinline script blocking rate
OperationsViolation Report MonitoringPolicy change lead time

CSP is not a task for the security team alone. It is sustainable only when the front-end and marketing script operation staff become policy owners together.

Code example 1: CSP header generation

export function buildCspHeader(nonce: string) {
  return [
    "default-src 'self'",
    "script-src 'self' 'nonce-" + nonce + "' https://www.googletagmanager.com",
    "style-src 'self' 'unsafe-inline'",
    "img-src 'self' data: https:",
    "connect-src 'self' https://www.google-analytics.com",
    "frame-ancestors 'none'",
    "base-uri 'self'",
    "object-src 'none'",
  ].join("; ");
}

Code example 2: Next.js middleware application

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

export function middleware(req: NextRequest) {
  const nonce = crypto.randomUUID().replace(/-/g, "");
  const res = NextResponse.next();

  res.headers.set("Content-Security-Policy-Report-Only", buildCspHeader(nonce));
  res.headers.set("Report-To", '{"group":"csp","max_age":10886400,"endpoints":[{"url":"https://csp.8space.dev/report"}]}');

  return res;
}

Architecture flow

Mermaid diagram rendering...

Tradeoffs

  • Strict policies increase security, but increase the cost of maintaining third-party scripts.
  • If the Report-Only period is long, it is stable, but the actual blocking conversion may be delayed.
  • The nonce strategy is safe, but compatibility with the SSR/cache architecture must be additionally considered.

Cleanup

CSP hardening is a gradual convergence process. By reducing policies and switching to final enforcement based on violation reports, security strength can be increased without compromising service availability.

Image source

  • Cover: source link
  • License: OGL v1.0 / Author: Harland Quarrington
  • Note: After downloading the free license image from Wikimedia Commons, it was optimized to JPG at 1600px.

Comments