Add Security Headers on Cloudflare Pages
cloudflare pages securitySecuring 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:
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:
- Content-Security-Policy: Prevents XSS attacks by specifying which sources are allowed to load content.
- X-Content-Type-Options: Stops the browser from MIME-sniffing a response away from the declared content type.
- X-Frame-Options: Protects against click-jacking by preventing the site from being framed.
- X-XSS-Protection: In older browsers this enables the XSS filter in the browser.
- Referrer-Policy: Controls how much referrer information is included with requests.
- Permissions-Policy: Controls access to browser features like the camera and microphone.
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.
- First thing you need to know is that any javascript you place in a ‘/functions’ folder Cloudflare Pages will run it using workers.
- Second thing you need to know is that if you create a ‘/functions/_middleware.js’ file that it’ll run that middleware on all requests, even requests for your static content.
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
- MDN Web Docs: Content Security Policy (CSP)
- Cloudflare Documentation: Headers
- Cloudflare Documentation: Middleware