mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-07 04:12:04 +00:00
docs(proxy): say that frame-ancestors governs framing
The comments still named X-Frame-Options DENY as what refuses the vault preview embed and claimed the serve route keeps a sandbox directive. A browser that reads the CSP's frame-ancestors 'self' ignores X-Frame-Options, and the document CSP deliberately carries no sandbox. No behaviour change.
This commit is contained in:
1 parent
aea9796170
commit
31997e3232
1 file changed
+15
-16
+15
-16
@@ -638,15 +638,14 @@ export function proxy(request: NextRequest) {
|
||||
response.headers.set(HEALTHLOG_PAGE_MARKER_HEADER, "1");
|
||||
}
|
||||
|
||||
// The document vault's decrypt-and-serve route is framed SAME-ORIGIN by
|
||||
// the document detail preview (an <iframe> for inline-class PDFs). The
|
||||
// blanket `X-Frame-Options: DENY` below would
|
||||
// refuse that embed, and the blanket page CSP would clobber the route's
|
||||
// own `Content-Security-Policy: sandbox` (middleware headers win over
|
||||
// route headers). Scope: exactly the `/original` path — list/detail API
|
||||
// routes keep the full DENY posture. The replacement CSP keeps the
|
||||
// sandbox (the served bytes are user-uploaded and must never script in
|
||||
// the app origin) and narrows framing to 'self' instead of dropping it.
|
||||
// The document vault's decrypt-and-serve route is framed SAME-ORIGIN by the
|
||||
// document detail preview (an <iframe> for inline-class PDFs). It gets a
|
||||
// document CSP, not the page CSP, which would replace the route's own CSP
|
||||
// (middleware headers win over route headers). Scope: exactly the
|
||||
// `/original` path; list/detail API routes keep the page posture. The
|
||||
// document CSP lets the user-uploaded bytes load nothing and permits only
|
||||
// same-origin framing (`frame-ancestors 'self'`); it carries no `sandbox`,
|
||||
// see the CSP note below.
|
||||
const isDocumentServeRoute =
|
||||
/^\/api\/documents\/inbound\/[^/]+\/original$/.test(pathname);
|
||||
|
||||
@@ -654,11 +653,10 @@ export function proxy(request: NextRequest) {
|
||||
// `/c/<token>/d/<id>` is the share analogue of the owner `/original` route:
|
||||
// it decrypts and serves a user-uploaded document that the clinician view
|
||||
// (`/c/<token>`) frames same-origin (an <iframe> for inline-class PDFs). It
|
||||
// needs the SAME narrow posture — SAMEORIGIN framing + a document CSP — and
|
||||
// NOT the `/c/` page posture, whose `X-Frame-Options: DENY` would refuse
|
||||
// the preview embed. Anchored to EXACTLY two dynamic segments so a
|
||||
// `/c/<token>` page, a `/c/<token>/d/<id>/extra`, or a `/c/<token>/dx/<id>`
|
||||
// lookalike never inherits the carve-out.
|
||||
// needs the SAME narrow posture (the document CSP) and NOT the `/c/` page
|
||||
// CSP, which is written for an app page. Anchored to EXACTLY two dynamic
|
||||
// segments so a `/c/<token>` page, a `/c/<token>/d/<id>/extra`, or a
|
||||
// `/c/<token>/dx/<id>` lookalike never inherits the carve-out.
|
||||
const isShareDocumentServeRoute = /^\/c\/[^/]+\/d\/[^/]+$/.test(pathname);
|
||||
|
||||
// Both serve routes take the narrow, document-only header posture.
|
||||
@@ -685,7 +683,8 @@ export function proxy(request: NextRequest) {
|
||||
response.headers.set("Cache-Control", "private, no-store");
|
||||
}
|
||||
|
||||
// Security headers
|
||||
// Security headers. Framing is refused by the CSP's `frame-ancestors`; a
|
||||
// browser that reads it ignores X-Frame-Options, kept for older ones.
|
||||
response.headers.set("X-Content-Type-Options", "nosniff");
|
||||
response.headers.set("X-Frame-Options", isServeRoute ? "SAMEORIGIN" : "DENY");
|
||||
response.headers.set("Referrer-Policy", "strict-origin-when-cross-origin");
|
||||
@@ -778,7 +777,7 @@ export function proxy(request: NextRequest) {
|
||||
// them.
|
||||
const csp = isServeRoute
|
||||
? // Vault serve route (owner `/original` OR share `/c/<token>/d/<id>`; see
|
||||
// the X-Frame-Options note above): the
|
||||
// the framing note above): the
|
||||
// response is a user-uploaded document, not an app page.
|
||||
// `default-src 'none'` — a served document may load nothing as if
|
||||
// it were a page — and `frame-ancestors 'self'` permits exactly the
|
||||
|
||||
Reference in new issue
Block a user