feat(security): allow analytics subdomain to iframe the site #79

Merged
tudor merged 1 commits from feat/allow-analytics-iframe-embed into main 2026-07-21 21:52:35 +00:00
Owner

What

Replace X-Frame-Options: SAMEORIGIN with a CSP frame-ancestors directive so analytics.schoolcompare.co.uk (Umami heatmap/recorder) can embed the site in an iframe, while every other origin stays blocked.

Why

X-Frame-Options cannot allow a specific sibling subdomain — ALLOW-FROM is deprecated and ignored by modern Chrome/Safari. CSP frame-ancestors is the modern replacement and supersedes X-Frame-Options when both are present, so the old header is dropped to avoid a conflicting/most-restrictive result.

Changes

  • nextjs-app/next.config.js — swap the header for Content-Security-Policy: frame-ancestors 'self' https://analytics.schoolcompare.co.uk.
  • nextjs-app/DEPLOYMENT.md — update the documented nginx snippet to match.

Backend API (frame-ancestors 'none') is left untouched — the API should never be framed.

Deploy verification

The live reverse proxy must not still add X-Frame-Options, or the browser sees both and the most-restrictive wins. After deploy, confirm:

curl -sI https://schoolcompare.co.uk | grep -iE 'frame-ancestors|x-frame'

Expect only the frame-ancestors CSP and no X-Frame-Options.

🤖 Generated with Claude Code

## What Replace `X-Frame-Options: SAMEORIGIN` with a CSP `frame-ancestors` directive so **analytics.schoolcompare.co.uk** (Umami heatmap/recorder) can embed the site in an iframe, while every other origin stays blocked. ## Why `X-Frame-Options` cannot allow a specific sibling subdomain — `ALLOW-FROM` is deprecated and ignored by modern Chrome/Safari. CSP `frame-ancestors` is the modern replacement and supersedes `X-Frame-Options` when both are present, so the old header is dropped to avoid a conflicting/most-restrictive result. ## Changes - `nextjs-app/next.config.js` — swap the header for `Content-Security-Policy: frame-ancestors 'self' https://analytics.schoolcompare.co.uk`. - `nextjs-app/DEPLOYMENT.md` — update the documented nginx snippet to match. Backend API (`frame-ancestors 'none'`) is left untouched — the API should never be framed. ## Deploy verification The live reverse proxy must not still add `X-Frame-Options`, or the browser sees both and the most-restrictive wins. After deploy, confirm: ``` curl -sI https://schoolcompare.co.uk | grep -iE 'frame-ancestors|x-frame' ``` Expect only the `frame-ancestors` CSP and **no** `X-Frame-Options`. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
tudor added 1 commit 2026-07-21 21:51:35 +00:00
feat(security): allow analytics subdomain to iframe the site
PR Checks / Frontend Typecheck + Tests (pull_request) Successful in 1m2s
PR Checks / Backend Smoke (pull_request) Successful in 7s
PR Checks / Build Backend (no push) (pull_request) Successful in 11s
PR Checks / Build Frontend (no push) (pull_request) Successful in 48s
PR Checks / Build Pipeline (no push) (pull_request) Successful in 10s
PR Checks / AI Code Review (Claude) (pull_request) Successful in 8s
9556595800
Replace X-Frame-Options: SAMEORIGIN with a CSP frame-ancestors directive
so analytics.schoolcompare.co.uk (Umami heatmap/recorder) can embed the
site while all other origins stay blocked. X-Frame-Options cannot allow a
specific sibling subdomain (ALLOW-FROM is deprecated/ignored by modern
browsers), so frame-ancestors is the correct replacement.

Also update the nginx snippet in DEPLOYMENT.md to match, so the reverse
proxy doesn't re-inject a conflicting X-Frame-Options header.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
tudor merged commit 2f038285f6 into main 2026-07-21 21:52:35 +00:00
Sign in to join this conversation.
No Reviewers
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: tudor/school_compare#79