diff --git a/_headers b/_headers new file mode 100644 index 0000000..0d75eed --- /dev/null +++ b/_headers @@ -0,0 +1,22 @@ +# Response headers for everything flield.com serves. Cloudflare reads this +# file at deploy time and does not serve it. Every page is static, has no +# form, and talks to nothing but its own origin, so the policy can say +# exactly that. +# +# The one exception is Cloudflare Web Analytics, which the dashboard +# injects at the edge as a script from static.cloudflareinsights.com that +# then posts to cloudflareinsights.com. Both hosts are allowed below; drop +# them if analytics is ever turned off. +# +# script-src carries 'unsafe-inline' because the app is one long inline +# script and the document pages each have one too. A nonce would need a +# server to mint it, and there is none. What the policy still buys is that +# no script from any other host runs, no page can be re-based, nothing +# embeds a plugin, and no form posts anywhere. img-src allows data: for +# the favicon the app redraws on every load and blob: for the exported +# frames; worker-src covers the vendored GIF encoder's worker. +/* + X-Content-Type-Options: nosniff + Referrer-Policy: strict-origin-when-cross-origin + Permissions-Policy: camera=(), microphone=(), geolocation=(), payment=(), usb=() + Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline' https://static.cloudflareinsights.com; style-src 'self' 'unsafe-inline'; img-src 'self' data: blob:; worker-src 'self' blob:; connect-src 'self' https://cloudflareinsights.com; font-src 'self'; object-src 'none'; base-uri 'self'; form-action 'self'