Add Security Headers on Cloudflare Pages

Add Security Headers on Cloudflare Pages

cloudflare pages security

Securing Static Sites: Why It Matters

Wait! What? Securing a static site? Yup, even if your site only contains static content, it doesn’t mean you’re safe from vulnerabilities like Cross-Site Scripting (XSS) and others. This becomes an even bigger issue if you’ve added forms or other interactive elements. The good news is that securing your site is straightforward.

There are two primary methods for adding security headers to your Cloudflare Pages site:

  1. Create a _headers file
  2. Cloudflare functions middleware

Option 1: Create a _headers file

Cloudflare lets you create a ‘_headers’ file wherein you provide headers that should be set on all requests. Note that you can list multiple paths and Cloudflare will set the headers accordingly for that path. In the below example we’re just setting one path that matches all routes I.E. ‘/*’. This file needs to live at the root of path of the files you upload to Cloudflare. If using Hugo then you should save it at ‘static/_headers’.

/*
	Content-Security-Policy: default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; object-src 'none'; frame-ancestors 'none'; base-uri 'self';
	X-Content-Type-Options: nosniff
	X-Frame-Options: DENY
	X-XSS-Protection: 1; mode=block
	Referrer-Policy: strict-origin-when-cross-origin
	Permissions-Policy: camera=(), microphone=(), geolocation=()

Explanation of Headers:

You may have noticed that the ‘_headers’ file doesn’t provide a way to dynamically generate nonce values. If you need that level of security then see option 2 below.

Option 2: Cloudflare functions middleware

So you need to dynamically do something with your headers, such as generate nonce values? Well then you’ll need to create a piece of middleware to do that.

The below example shows how to generate nonce values for javascript files.

Important! If you still have a ‘_headers’ file then make sure to remove the Content-Security-Policy (CSP) from it since you can only declare that once and we want it to now come from our middleware. If you have duplicate CSP’s the browser will only honor the last one it receives.

/** Inserts a nonce into the requested HTML and response header if the HTML links to a javascript file. */
export async function onRequest(context) {

	// Initialize context.
	const { request, next } = context;

	// Generate nonce.
	const nonce = crypto.randomUUID();
	
	const response = await next();

	// Check if the requested item is a HTML file.
	if (response.headers.get("Content-Type")?.includes("text/html")) {

		// Get body of the HTML content being requested.
		let text = await response.text();
		
		// Insert nonce into script tags.
		text = text.replace(/<script([^>]*)>/g, `<script$1 nonce="${nonce}">`);
		
		// Set CSP headers with an nonce for the javascript files.
		response.headers.set("Content-Security-Policy", `script-src 'self' 'nonce-${nonce}'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; object-src 'none'; frame-src 'self'; frame-ancestors 'none'; base-uri 'self';`);

		return new Response(text, response);
	}
	
	return response;
}

Conclusion

Adding security headers to your Cloudflare Pages site is essential for protecting against common web vulnerabilities. Whether you choose to use a ‘_headers’ file or Cloudflare functions middleware, implementing these headers is a great step towards enhancing your static site’s security.

Cheers 🥂

Further reading and resources

More Articles