Automations and webhooks for the AT Protocol airglow.run

CSP blocks Cloudflare's injected analytics script #11

Closed tyb.there-hugo.dev
Closed opened by tyb.there-hugo.dev

Problem #

lib/security-headers.ts:27 sets script-src 'self' 'nonce-...'. The Cloudflare Web Analytics beacon is injected without a nonce, so the browser blocks it and logs CSP errors. Low priority.

Seen in the session #

In https://www.youtube.com/watch?v=5MnT-ZgbBIc:

  • CSP console errors from about 1:16 onward.

Fix direction #

Either allow the beacon's origin in script-src or turn off Cloudflare's automatic injection.

Details: docs/brainstorms/2026-10-17-graze-conference-automation-feedback.md (B7).

Queued: the loop will work on this version of the issue.

loop:queued cid=bafyreienbloszvz6v4q2qmhgfm4pgjmf2xirxewvy7ytfuyvis6j7mhmqy

Working on this, attempt 1.

loop:claim run=contribute-20261026-145357-3my32eynx6522 branch=loop/3my32eynx6522 attempt=1 issue=11

fix(security): allow Cloudflare Web Analytics beacon in CSP

Cloudflare injects its Web Analytics beacon (https://static.cloudflareinsights.com/beacon.min.js) without a nonce, so the nonce-only script-src blocked it and the browser logged CSP errors. The CSP in lib/security-headers.ts now allowlists https://static.cloudflareinsights.com in script-src, and https://cloudflareinsights.com in connect-src so the beacon can report. Same-origin /cdn-cgi/rum is already covered by 'self'.

Verification #

  • New test in lib/security-headers.test.ts checks that script-src includes the beacon's script origin, that connect-src includes its reporting origin, and that script-src still has no 'unsafe-inline'. The existing nonce tests still pass.
  • pnpm run check and pnpm run test pass (165 files, 2589 tests).
  • I did not check this in a browser behind Cloudflare. The origins come from Cloudflare's documented CSP requirements for Web Analytics.

Acceptance criteria #

Decisions the owner can reverse #

  • I took the "allowlist the origin" route, not "turn off Cloudflare's automatic injection". If you don't want the analytics, turn off automatic injection in the Cloudflare dashboard (Web Analytics → site settings) and revert this commit.
  • The allowlist is a host source, not a nonce or hash, so any script served from static.cloudflareinsights.com would be allowed. Inline scripts still need the nonce.

Review: https://tangled.org/exosphere.site/airglow/compare/main...loop/3my32eynx6522

loop:pushed run=contribute-20261026-145357-3my32eynx6522 sha=0b47adfe259b8f057fcc800892e7d49778331c01

Merge. The branch adds https://static.cloudflareinsights.com to script-src and https://cloudflareinsights.com to connect-src in the default CSP. That is the issue's first fix direction, and it matches the origins Cloudflare documents for Web Analytics under a CSP. Check and tests pass.

What I checked:

  • I read the code in lib/security-headers.ts. The policy has no 'strict-dynamic', so browsers still honour the new host source next to the nonce. The beacon is an external <script src>, so the new host source covers it without loosening inline scripts: 'unsafe-inline' is still absent from script-src. A route that sets its own CSP (e.g. api/favicon/[domain].ts) still keeps it. No other CSP in the repo needed changing.
  • The new test in lib/security-headers.test.ts parses each directive and checks both origins plus the missing 'unsafe-inline'. The existing nonce and override tests are untouched.
  • Scope: two files, only what the issue asks. No migrations, no followup.
  • I ran pnpm run check: format, lint and types all pass. I ran pnpm run test: 165 files, 2589 tests, all pass.
  • Not checked: whether the beacon actually loads behind Cloudflare. Like the contributor, I had no way to test that in a browser.

loop:verdict run=review-20261026-150041-3my32eynx6522 sha=0b47adfe259b8f057fcc800892e7d49778331c01 verdict=merge

Merged main into the branch: 7d5638668d5f141546088f80bd3f8dcde6984349.

loop:carry from=0b47adfe259b8f057fcc800892e7d49778331c01 sha=7d5638668d5f141546088f80bd3f8dcde6984349

Merged onto main as c88b677f128dd97b558a9421b8f5c3f94c56d39e.

loop:merged sha=c88b677f128dd97b558a9421b8f5c3f94c56d39e head=7d5638668d5f141546088f80bd3f8dcde6984349

Sign up or Sign in to add to the discussion.