Missing Content-Security-Policy & Permissions-Policy Headers on Cloudflare Pages Deployment

Hi everyone, I'm experiencing an issue where my Content-Security-Policy (CSP) and Permissions-Policy headers are not being applied correctly when deploying my site on Cloudflare Pages. (https://securityheaders.com/?q=dashio.net&followRedirects=on) Context: My project is built using Nuxt with the nuxt-security module. I was not able to use Nuxt Security itself to define my headers because I walked into issues with the following logs:
14:17:25.561 :sparkles: Compiled Worker successfully
14:17:26.817 Found _routes.json in output directory. Uploading.
14:17:26.829 Validating asset output directory
14:17:30.138 Deploying your site to Cloudflare's global network...
14:17:32.510 Parsed 23 valid header rules.
14:17:32.511 Found invalid header lines:
14:17:32.511 Ignoring line 18 as it exceeds the maximum allowed length of 2000.
14:17:32.511 Ignoring line 39 as it exceeds the maximum allowed length of 2000.
14:17:32.511 Ignoring line 60 as it exceeds the maximum allowed length of 2000.
14:17:32.511 Ignoring line 81 as it exceeds the maximum allowed length of 2000.
14:17:32.511 Ignoring line 102 as it exceeds the maximum allowed length of 2000.
14:17:32.511 Ignoring line 123 as it exceeds the maximum allowed length of 2000.
14:17:32.511 Ignoring line 144 as it exceeds the maximum allowed length of 2000.
14:17:32.511 Ignoring line 165 as it exceeds the maximum allowed length of 2000.
14:17:32.511 Ignoring line 187 as it exceeds the maximum allowed length of 2000.
14:17:32.511 Ignoring line 204 as it exceeds the maximum allowed length of 2000.
14:17:32.511 Ignoring line 225 as it exceeds the maximum allowed length of 2000.
14:17:32.511 Ignoring line 246 as it exceeds the maximum allowed length of 2000.
14:17:32.511 Ignoring line 267 as it exceeds the maximum allowed length of 2000.
14:17:32.512 Ignoring line 289 as it exceeds the maximum allowed length of 2000.
14:17:32.512 Ignoring line 349 as it exceeds the maximum allowed length of 2000.
14:17:32.512 Ignoring line 366 as it exceeds the maximum allowed length of 2000.
14:17:32.512 Ignoring line 392 as it exceeds the maximum allowed length of 2000.
14:17:34.044 Uploading... (99/295)
14:17:34.763 Uploading... (164/295)
14:17:34.766 Uploading... (230/295)
14:17:34.897 Uploading... (295/295)
14:17:34.898 :sparkles: Success! Uploaded 196 files (99 already uploaded) (1.24 sec)
14:17:34.898
14:17:35.475 :sparkles: Upload complete!
14:17:38.869 Success: Assets published!
14:17:41.389 Success: Your site was deployed!
14:17:25.561 :sparkles: Compiled Worker successfully
14:17:26.817 Found _routes.json in output directory. Uploading.
14:17:26.829 Validating asset output directory
14:17:30.138 Deploying your site to Cloudflare's global network...
14:17:32.510 Parsed 23 valid header rules.
14:17:32.511 Found invalid header lines:
14:17:32.511 Ignoring line 18 as it exceeds the maximum allowed length of 2000.
14:17:32.511 Ignoring line 39 as it exceeds the maximum allowed length of 2000.
14:17:32.511 Ignoring line 60 as it exceeds the maximum allowed length of 2000.
14:17:32.511 Ignoring line 81 as it exceeds the maximum allowed length of 2000.
14:17:32.511 Ignoring line 102 as it exceeds the maximum allowed length of 2000.
14:17:32.511 Ignoring line 123 as it exceeds the maximum allowed length of 2000.
14:17:32.511 Ignoring line 144 as it exceeds the maximum allowed length of 2000.
14:17:32.511 Ignoring line 165 as it exceeds the maximum allowed length of 2000.
14:17:32.511 Ignoring line 187 as it exceeds the maximum allowed length of 2000.
14:17:32.511 Ignoring line 204 as it exceeds the maximum allowed length of 2000.
14:17:32.511 Ignoring line 225 as it exceeds the maximum allowed length of 2000.
14:17:32.511 Ignoring line 246 as it exceeds the maximum allowed length of 2000.
14:17:32.511 Ignoring line 267 as it exceeds the maximum allowed length of 2000.
14:17:32.512 Ignoring line 289 as it exceeds the maximum allowed length of 2000.
14:17:32.512 Ignoring line 349 as it exceeds the maximum allowed length of 2000.
14:17:32.512 Ignoring line 366 as it exceeds the maximum allowed length of 2000.
14:17:32.512 Ignoring line 392 as it exceeds the maximum allowed length of 2000.
14:17:34.044 Uploading... (99/295)
14:17:34.763 Uploading... (164/295)
14:17:34.766 Uploading... (230/295)
14:17:34.897 Uploading... (295/295)
14:17:34.898 :sparkles: Success! Uploaded 196 files (99 already uploaded) (1.24 sec)
14:17:34.898
14:17:35.475 :sparkles: Upload complete!
14:17:38.869 Success: Assets published!
14:17:41.389 Success: Your site was deployed!
So the exceeding characters were the reason why I just switched to a manually created _headers file instead of letting the Security module create them for me. I'm using a _headers file inside the public/ directory to define security headers. The _headers file is structured like this:
/_scripts/*
cache-control: public, max-age=31536000, immutable

/_nuxt/*
cache-control: public, max-age=31536000, immutable

/*
Content-Security-Policy: default-src 'self'; script-src 'self' 'nonce-{{nonce}}' https://static.cloudflareinsights.com https://challenges.cloudflare.com; frame-src 'self' https://challenges.cloudflare.com; img-src 'self' data: https://*.dashio.net; connect-src 'self' https://*.cloudflare.com https://cloudflareinsights.com https://*.dashio.net https://*.supabase.co; style-src 'self' 'unsafe-inline'; font-src 'self' data:; object-src 'none'; script-src-attr 'none'; base-uri 'none'; form-action 'self'; upgrade-insecure-requests

Permissions-Policy: geolocation=(), microphone=(), camera=()
Referrer-Policy: no-referrer
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload;
X-Content-Type-Options: nosniff
X-Download-Options: noopen
X-Frame-Options: DENY
X-Permitted-Cross-Domain-Policies: none
X-XSS-Protection: 0
/_scripts/*
cache-control: public, max-age=31536000, immutable

/_nuxt/*
cache-control: public, max-age=31536000, immutable

/*
Content-Security-Policy: default-src 'self'; script-src 'self' 'nonce-{{nonce}}' https://static.cloudflareinsights.com https://challenges.cloudflare.com; frame-src 'self' https://challenges.cloudflare.com; img-src 'self' data: https://*.dashio.net; connect-src 'self' https://*.cloudflare.com https://cloudflareinsights.com https://*.dashio.net https://*.supabase.co; style-src 'self' 'unsafe-inline'; font-src 'self' data:; object-src 'none'; script-src-attr 'none'; base-uri 'none'; form-action 'self'; upgrade-insecure-requests

Permissions-Policy: geolocation=(), microphone=(), camera=()
Referrer-Policy: no-referrer
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload;
X-Content-Type-Options: nosniff
X-Download-Options: noopen
X-Frame-Options: DENY
X-Permitted-Cross-Domain-Policies: none
X-XSS-Protection: 0
Scan results for dashio.net
These are the scan results for dashio.net which scored the grade B.
1 Reply
nico
nicoOP3w ago
Shown (and somehow duplicated) _headers content in Dashboard:
/_scripts/*
cache-control: public, max-age=31536000, immutable
/_nuxt/*
cache-control: public, max-age=31536000, immutable
/*
Content-Security-Policy: default-src 'self'; script-src 'self' 'nonce-{{nonce}}' https://static.cloudflareinsights.com https://challenges.cloudflare.com; frame-src 'self' https://challenges.cloudflare.com; img-src 'self' data: https://*.dashio.net; connect-src 'self' https://*.cloudflare.com https://cloudflareinsights.com https://*.dashio.net https://*.supabase.co; style-src 'self' 'unsafe-inline'; font-src 'self' data:; object-src 'none'; script-src-attr 'none'; base-uri 'none'; form-action 'self'; upgrade-insecure-requests
Permissions-Policy: geolocation=(), microphone=(), camera=()
Referrer-Policy: no-referrer
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload;
X-Content-Type-Options: nosniff
X-Download-Options: noopen
X-Frame-Options: DENY
X-Permitted-Cross-Domain-Policies: none
X-XSS-Protection: 0

/_scripts/*
cache-control: public, max-age=31536000, immutable
/_nuxt/*
cache-control: public, max-age=31536000, immutable
/*
Referrer-Policy: no-referrer
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload;
X-Content-Type-Options: nosniff
X-Download-Options: noopen
X-Frame-Options: DENY
X-Permitted-Cross-Domain-Policies: none
X-XSS-Protection: 0
/_scripts/*
cache-control: public, max-age=31536000, immutable
/_nuxt/*
cache-control: public, max-age=31536000, immutable
/*
Content-Security-Policy: default-src 'self'; script-src 'self' 'nonce-{{nonce}}' https://static.cloudflareinsights.com https://challenges.cloudflare.com; frame-src 'self' https://challenges.cloudflare.com; img-src 'self' data: https://*.dashio.net; connect-src 'self' https://*.cloudflare.com https://cloudflareinsights.com https://*.dashio.net https://*.supabase.co; style-src 'self' 'unsafe-inline'; font-src 'self' data:; object-src 'none'; script-src-attr 'none'; base-uri 'none'; form-action 'self'; upgrade-insecure-requests
Permissions-Policy: geolocation=(), microphone=(), camera=()
Referrer-Policy: no-referrer
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload;
X-Content-Type-Options: nosniff
X-Download-Options: noopen
X-Frame-Options: DENY
X-Permitted-Cross-Domain-Policies: none
X-XSS-Protection: 0

/_scripts/*
cache-control: public, max-age=31536000, immutable
/_nuxt/*
cache-control: public, max-age=31536000, immutable
/*
Referrer-Policy: no-referrer
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload;
X-Content-Type-Options: nosniff
X-Download-Options: noopen
X-Frame-Options: DENY
X-Permitted-Cross-Domain-Policies: none
X-XSS-Protection: 0
What I've Tried: 1. Verified that _headers is included in the deployment (it's visible in the Cloudflare Pages build logs and dashboard as shown above). 2. Checked the security headers report using securityheaders.com, which still shows missing CSP and Permissions-Policy headers. 3. Confirmed that Cloudflare Pages does apply other headers (e.g., Strict-Transport-Security, X-Frame-Options, etc.). 4. Cleared Cloudflare Cache and redeployed multiple times. 5. Checked Firefox DevToolsNetwork tab → Security headers are missing in the final response. Questions: 1. Does Cloudflare Pages override or ignore certain headers from _headers? 2. Are there any known limitations when using _headers for CSP and Permissions-Policy? 3. Is there a recommended way to debug why these specific headers are not applied, even though others are? Any guidance would be greatly appreciated! Thanks in advance.

Did you find this page helpful?