Security headers and CSP on Cloudflare Pages.

This article describes the actual configuration this site ships, in a Cloudflare Pages _headers file, as a working example rather than a hypothetical one.

Where the configuration lives

Cloudflare Pages reads a plain-text _headers file from the build output and applies the rules it defines per matched path. Nomadrex.dev's file defines a site-wide rule for /*, plus narrower rules for /account/* and /assets/* that override or extend the defaults for those specific paths.

The site-wide Content-Security-Policy

The Content-Security-Policy header restricts what a page is allowed to load or execute, directive by directive:

Deliberately not present: a blanket 'unsafe-inline' in script-src. Any inline script must instead match an explicit hash listed in the policy, which means an attacker who manages to inject a different inline script (for example, through a content injection bug) cannot get it to execute, because it won't match the allowed hash.

Supporting headers

Path-specific overrides

The /account/* path adds Cache-Control: private, no-store, max-age=0 and a stricter Referrer-Policy: no-referrer, because account pages can contain session-specific content that should never be cached by a shared cache or leaked via referrer to an external link. The /assets/* path instead sets a long, immutable cache lifetime, since built asset filenames change when their content changes, so aggressive caching is safe there.

Why this is tested, not just configured

A header file is only useful if it stays correct as the site changes. This site's automated test suite asserts directly against the shipped _headers file — for example, confirming the script hash and third-party script domains are present and that 'unsafe-inline' never appears in script-src — so a future change that accidentally weakens the policy fails a test instead of shipping quietly.