From ca2f7e4d78125c30fb7bc38634ce647e2549293a Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 10 Jul 2026 12:08:05 +0000 Subject: [PATCH] Auto-allow the ?dn parked domain as a CSP frame-ancestor MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Masked-forwarded parked domains (Porkbun frameset, e.g. moshscript.com) iframe moshcoding.com/?dn=, but the CSP frame-ancestors only listed the domains in FRAME_ANCESTORS, so any domain not hand-added there was blocked by the browser and rendered blank. The framed request carries its own ?dn, so trust it to iframe just its own tenant page — new parked domains now work without editing FRAME_ANCESTORS each time. 'self' + the env list still apply; the dn is hostname-validated before being added. Co-Authored-By: Claude Opus 4.8 --- middleware.ts | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/middleware.ts b/middleware.ts index f0c050e..7ffcc4f 100644 --- a/middleware.ts +++ b/middleware.ts @@ -4,9 +4,19 @@ import { NextRequest, NextResponse } from "next/server"; // e.g. moshcode.sh). Read at RUNTIME so FRAME_ANCESTORS env changes take effect // on redeploy without a code edit. 'self' lets the app frame itself; no other // origin can (anti-clickjacking). -function frameAncestors(): string { +function frameAncestors(req: NextRequest): string { const parked = (process.env.FRAME_ANCESTORS || "https://moshcode.sh").split(/\s+/).filter(Boolean); - return ["'self'", ...parked].join(" "); + const allow = ["'self'", ...parked]; + + // Auto-allow the parked domain currently being rendered. A masked-forwarded + // domain frames moshcoding.com/?dn=, so the frame request carries its + // own ?dn; trust it to iframe just its own tenant page. This means new parked + // domains work without hand-editing FRAME_ANCESTORS for each one. + const dn = (req.nextUrl.searchParams.get("dn") || "").trim().toLowerCase(); + if (dn.length <= 253 && /^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?(?:\.[a-z0-9](?:[a-z0-9-]*[a-z0-9])?)+$/.test(dn)) { + allow.push(`https://${dn}`, `https://www.${dn}`); + } + return allow.join(" "); } // Redirect www.moshcoding.com → https://moshcoding.com (apex, permanent). @@ -21,7 +31,7 @@ export function middleware(req: NextRequest) { return NextResponse.redirect(url, 308); } const res = NextResponse.next(); - res.headers.set("Content-Security-Policy", `frame-ancestors ${frameAncestors()}`); + res.headers.set("Content-Security-Policy", `frame-ancestors ${frameAncestors(req)}`); // Referral attribution: a ?ref= visit drops a 90-day cookie (first-touch // — the first ref a visitor arrives with sticks). Signup/waitlist read it so