FAHADBIN SHAKIR

Loading essential experience000%

Web Security

CSP in Production Across Reverse Proxies and CDNs

How to keep one complete Content Security Policy authoritative while applications, proxies, hosting panels, and CDNs all participate in the response path.

Author: Fahad Bin Shakir · Published: · Updated: · 14 min read

Browser, edge, reverse proxy and origin protected by layered security policy barriers

Introduction

Content Security Policy is enforced from the response a browser finally receives. That response may pass through an application server, Passenger or another process manager, Apache or Nginx, a hosting control panel, a CDN, and a browser cache. Inspecting only the application code can therefore give a confident but incomplete answer about the live policy.

Multiple policies are not merged into a friendlier union. Browsers enforce each policy, so a resource must satisfy all of them. A short edge policy containing only upgrade-insecure-requests can coexist with a complete application policy, but it is still a second authority and makes ownership, diagnostics, and later changes harder. The clean production target is one intentionally managed complete policy.

Map every response writer before editing policy

Draw the path from client to edge and origin. For each layer, identify who can add, replace, append, normalize, or cache response headers. Include hosting switches such as Force HTTPS, security middleware, Apache Header directives, CDN transform rules, worker code, platform defaults, and stored redirect responses. A rule may exist outside the repository and still win in production.

Capture raw headers for the canonical document, an alternate host, an HTTP redirect, a static asset, an API response, a 404, and a generated route. Use a client that preserves repeated field lines. A browser network panel may present a combined value, while the operational question is how many policies were delivered and which layer produced each one.

curl --silent --show-error --dump-header - --output /dev/null https://example.com/
# Count field lines case insensitively; do not infer header count from a visually combined browser value.

Choose one authoritative enforcement layer

The application is often the best owner when routes have different dependencies, nonces are generated per response, or policy tests live with code. Apache or a CDN can be appropriate for a uniform static site, but the deployment process must version and validate that configuration with the application. The worst design is accidental split ownership where each layer contains part of the intended policy.

If infrastructure must own CSP, remove the application header in the same release plan. If the application owns it, disable any hosting or edge feature that injects another CSP and leave redirect logic independent. Never fix duplication by deleting a complete policy before proving that the remaining layer carries every required directive.

Understand why duplicate policies fail unexpectedly

Each delivered policy is enforced. A script allowed by one policy and blocked by another remains blocked. The effective behavior is therefore the intersection of permissions, not a last writer wins merge. This can produce confusing failures when an infrastructure rule adds a narrow default or when a stale CDN object retains an older policy.

Header libraries may also serialize multiple values into one comma separated field. That representation still contains multiple policies under the CSP grammar. Validate both the number of field lines and the parsed policy list. Do not compare only a substring such as upgrade-insecure-requests; confirm the complete expected directive set and that no independent second policy remains.

  • Check Content Security Policy and Report Only separately.
  • Search HTML for meta delivered policies as well as HTTP headers.
  • Inspect redirects and errors because platforms may apply different rules there.
  • Purge or bypass cached responses when verifying a policy ownership change.

Separate canonical redirects from browser policy

HTTP to HTTPS and alternate host normalization should have one clear owner as well. Preserve the path and query string, trust forwarded protocol headers only from known proxies, and test from outside the hosting network. A redirect loop often appears when the origin sees HTTP behind a TLS terminating proxy and does not recognize the forwarded scheme.

Keep redirect configuration narrow. It should not rewrite application routes, bypass process manager directives, or add an unrelated security policy as a side effect. On managed hosting, preserve generated Passenger or application routing blocks exactly and place a bounded idempotent redirect block where the platform permits.

Test the policy against real application dependencies

Inventory scripts, styles, fonts, images, media, workers, frames, forms, and connections before tightening directives. Exercise consent changes, analytics, contact forms, route navigation, media, downloads, and failure states. A policy that makes the homepage look correct can still block an API request or a lazy route chunk.

Use Report Only during a substantial policy redesign, filter extension noise, and avoid collecting sensitive full URLs in reports. For a known policy ownership correction, automated assertions should compare the final exact policy or required directives, count headers, and open representative routes in a browser console.

Make live header evidence part of closure

A local test proves the intended application response. Closure requires the public response after deployment and cache propagation. Record the final URL, status, redirect count, CSP header count, full policy, HSTS, MIME protection, framing control, referrer policy, permissions policy, and the time of observation. Repeat from HTTP, www, and a nested path with a query string.

Monitor for later drift. Hosting panel changes, proxy templates, CDN migrations, and emergency rules can reintroduce a second policy without touching the repository. A small scheduled header probe can alert when the policy count or digest changes, but the alert should lead to an ownership investigation rather than an automatic overwrite.

Deployment checklist

  • Inventory every application, server, hosting, and edge response writer.
  • Capture repeated raw headers across documents, redirects, assets, APIs, and errors.
  • Select one authoritative layer for the complete enforced policy.
  • Remove duplicate generation only as part of a verified handoff.
  • Keep canonical redirects independent and preserve application routing directives.
  • Exercise real scripts, styles, APIs, consent, forms, media, and route chunks.
  • Verify the public response after cache propagation from every host variant.
  • Monitor header count and policy digest for infrastructure drift.

Related portfolio and context

Primary references

Related Engineering Notes

View all Engineering Notes