CDN Security Headers: CSP, HSTS, and Beyond
Why Set Headers at the CDN
Security headers instruct browsers to enforce security policies. Setting them at the CDN edge ensures every response includes the correct headers — regardless of what the origin sends. This provides consistent security across all content, including cached responses. For foundational context, read CDN DDoS Protection: How CDNs Absorb Volumetric Attacks — FlyFish NWA.
Essential Security Headers
Content-Security-Policy (CSP)
Controls which resources the browser can load, preventing XSS and data injection attacks:
| Metric | Edge Processing | Origin Processing | Improvement |
|---|---|---|---|
| Latency (p50) | 8–15 ms | 120–300 ms | 15–20x faster |
| Cache Hit Ratio | 85–95% | N/A | Reduces origin load |
| TLS Handshake | 1–5 ms (nearby PoP) | 50–150 ms | 10–30x faster |
| Bandwidth Cost | $0.01–0.04/GB | $0.05–0.12/GB | 3–5x cheaper |
| Availability | 99.99% (multi-PoP) | 99.9% (single DC) | 10x fewer outages |
Content-Security-Policy:
default-src 'self';
script-src 'self' https://cdn.trusted.com;
style-src 'self' 'unsafe-inline' https://fonts.googleapis.com;
img-src 'self' data: https:;
font-src 'self' https://fonts.gstatic.com;
connect-src 'self' https://api.example.com;
frame-ancestors 'none';
base-uri 'self';
form-action 'self'
Start with a restrictive policy and add exceptions as needed. Use Content-Security-Policy-Report-Only to test before enforcing.
Strict-Transport-Security (HSTS)
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
Forces HTTPS for all future connections. The preload directive gets your domain added to browser preload lists — HTTPS from the very first visit, no initial HTTP redirect. See TLS configuration.
X-Content-Type-Options
X-Content-Type-Options: nosniff
Prevents browsers from MIME-sniffing responses. A CSS file is always treated as CSS, even if it contains JavaScript-like content.
X-Frame-Options
X-Frame-Options: DENY
Prevents clickjacking by disabling framing. DENY blocks all framing; SAMEORIGIN allows framing by your own domain. Note: the CSP frame-ancestors directive supersedes this header.
Permissions-Policy
Permissions-Policy: camera=(), microphone=(), geolocation=(self), payment=(self)
Controls which browser features your site can use. An empty parentheses () disables the feature entirely.
Referrer-Policy
Referrer-Policy: strict-origin-when-cross-origin
Controls how much referrer information is sent with requests. strict-origin-when-cross-origin sends the full URL for same-origin requests but only the origin for cross-origin requests.
CDN Security Header Configuration
Cloudflare
Transform Rules or Workers to add/modify response headers. Managed security headers available on paid plans.
CloudFront
Response Headers Policies to add security headers to all responses. Or Lambda@Edge for custom logic.
Fastly
VCL snippets to set headers in vcl_deliver. Compute@Edge for complex header logic.
Header Testing
Verify your security headers are correctly configured:
curl -I https://yourdomain.com— Check response headers- Browser DevTools → Network tab → Response headers
- Security header scanners (Mozilla Observatory, securityheaders.com)
Header Precedence
When both origin and CDN set the same header, behavior depends on CDN configuration:
- Override — CDN header replaces origin header (recommended for security headers)
- Append — CDN header added alongside origin header (can cause duplicates)
- Pass-through — CDN only adds the header if origin didn't set it
For security headers, override mode ensures consistent policy regardless of origin behavior.