Skip to main content
Site Architecture

CSP & Security Headers

Content Security Policy configuration, security headers, and troubleshooting CSP violations on ArgoBox

March 1, 2026

CSP & Security Headers

ArgoBox serves security headers via public/_headers, which Cloudflare Pages applies to all responses. The most complex of these is the Content-Security-Policy (CSP) header, which controls what resources the browser is allowed to load.

Header File

All security headers are defined in public/_headers under the /* catch-all rule. Cloudflare Pages reads this file at deploy time and applies the headers to matching routes.

Active Security Headers

Header Value Purpose
X-Content-Type-Options nosniff Prevents MIME-type sniffing
X-Frame-Options SAMEORIGIN Allows same-origin iframes (needed for F12 Console Audit)
X-XSS-Protection 1; mode=block Legacy XSS filter (browser support varies)
Referrer-Policy strict-origin-when-cross-origin Full referrer to same origin, origin-only to cross-origin
Permissions-Policy camera=(), microphone=(self), geolocation=() Disables camera/geo, allows mic (voice features)
Cross-Origin-Opener-Policy same-origin Isolates browsing context
Cross-Origin-Resource-Policy same-origin Restricts resource loading to same origin
HSTS max-age=31536000; includeSubDomains; preload Forces HTTPS for 1 year

Content Security Policy

The CSP header is a single line in public/_headers (line 192). Each directive controls a different resource type.

Current Directives

Directive Allowed Sources What It Controls
default-src 'self' Fallback for unlisted resource types
script-src 'self' 'unsafe-inline' data: static.cloudflareinsights.com cdn.jsdelivr.net JavaScript execution
style-src 'self' 'unsafe-inline' cdnjs.cloudflare.com fonts.googleapis.com CSS loading
font-src 'self' cdnjs.cloudflare.com fonts.gstatic.com Font file loading
img-src 'self' data: blob: https: Image loading (permissive — allows any HTTPS)
connect-src 'self' *.argobox.com argobox.com wss://*.argobox.com static.cloudflareinsights.com argobox.cloudflareaccess.com api.github.com XHR, fetch, WebSocket
frame-src 'self' *.argobox.com argobox.cloudflareaccess.com *.pages.dev Iframe sources
object-src 'none' Blocks Flash/Java applets
base-uri 'self' Prevents <base> tag hijacking

Why unsafe-inline Is Required

ArgoBox uses Astro's <script is:inline> pattern extensively for pages that need DOM manipulation with View Transitions compatibility. These emit literal inline <script> blocks in the HTML. Without 'unsafe-inline', all inline scripts and styles would be blocked.

A nonce-based approach would be more secure but requires SSR middleware to inject a unique nonce per request into both the CSP header and every <script>/<style> tag — significant complexity for a site behind Cloudflare Access authentication.

Adding New Third-Party Resources

When integrating a new external service, determine which CSP directives need updating:

Resource Type Directive Example
External JS library script-src cdn.jsdelivr.net
External CSS/fonts style-src + font-src fonts.googleapis.com + fonts.gstatic.com
API calls (fetch/XHR) connect-src api.github.com
Embedded iframes frame-src *.argobox.com
Images from CDN img-src Already allows https: broadly

Google Fonts requires TWO directives: fonts.googleapis.com in style-src (serves the CSS file) and fonts.gstatic.com in font-src (serves the actual WOFF2 font files).

Troubleshooting CSP Violations

CSP violations appear in the browser console as:

Refused to load the stylesheet 'https://fonts.googleapis.com/...'
because it violates the following Content Security Policy directive:
"style-src 'self' 'unsafe-inline' https://cdnjs.cloudflare.com".

Steps to Fix

  1. Identify the blocked resource from the console error message
  2. Determine the directive — the error message names it explicitly
  3. Add the domain to the relevant directive in public/_headers line 192
  4. Commit and push — CF Pages applies the new headers on next deploy
  5. Verify with a hard refresh (Ctrl+Shift+R) to bypass cache

Common Gotchas

  • Cache delaypublic/_headers has a 5-minute cache for admin pages. Wait or hard-refresh.
  • Wildcard subdomain*.argobox.com covers subdomains but NOT argobox.com itself (both must be listed in connect-src).
  • blob: for img-src — dynamically generated images (canvas exports, PDF previews) use blob: URLs that need explicit allowlisting.
  • WebSocketwss://*.argobox.com in connect-src covers secure WebSocket connections to ArgoBox subdomains.

X-Frame-Options: SAMEORIGIN

This header was changed from DENY to SAMEORIGIN to support the F12 Console Audit feature, which loads every page in a hidden same-origin iframe to capture console errors. The SAMEORIGIN value still prevents external sites from embedding ArgoBox pages.

Related

securitycspheaderscloudflare