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

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.

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-inlinewithout 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
| perspective | Design criteria | Verification points |
|---|---|---|
| Introduction stage | Start Report-Only | Violation event type |
| policy reduction | Minimize domain whitelist | Number of unnecessary allowed items |
| Script Control | apply nonce/hash | inline script blocking rate |
| Operations | Violation Report Monitoring | Policy 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
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.