CSP & Security Headers
Content Security Policy configuration, security headers, and troubleshooting CSP violations on ArgoBox
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
- Identify the blocked resource from the console error message
- Determine the directive — the error message names it explicitly
- Add the domain to the relevant directive in
public/_headersline 192 - Commit and push — CF Pages applies the new headers on next deploy
- Verify with a hard refresh (Ctrl+Shift+R) to bypass cache
Common Gotchas
- Cache delay —
public/_headershas a 5-minute cache for admin pages. Wait or hard-refresh. - Wildcard subdomain —
*.argobox.comcovers subdomains but NOTargobox.comitself (both must be listed inconnect-src). blob:for img-src — dynamically generated images (canvas exports, PDF previews) useblob:URLs that need explicit allowlisting.- WebSocket —
wss://*.argobox.cominconnect-srccovers 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
- F12 Console Audit — automated console error detection using iframes
- Cloudflare Pages — deployment and hosting configuration