From 14686909771afddb61df9d8fc9a46eaeabb8df76 Mon Sep 17 00:00:00 2001 From: Ari Chivukula Date: Mon, 16 Sep 2024 17:23:11 -0700 Subject: [PATCH] [Partitioned Popins] Popin-Policy Response Header (Default none) Every top-frame response for a popin must include a Popin-Policy header that permits the popin's opener's top-frame-origin. This is to ensure popins cannot be opened in a partitioned context other than the one they are designed to. This CL requires the header to exist and permit access, whereas before omitting the header would permit access. Explainer: https://explainers-by-googlers.github.io/partitioned-popins/ I2P: https://groups.google.com/a/chromium.org/g/blink-dev/c/ApU_zUmpQ2g/ Bug: 340606651 Change-Id: I4577cefe3687c1cf0501a4c195161f1335d8023b Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5865610 Reviewed-by: Dana Fried Auto-Submit: Ari Chivukula Commit-Queue: Rakina Zata Amni Reviewed-by: Rakina Zata Amni Cr-Commit-Position: refs/heads/main@{#1356212} --- .../remote-context-helper/resources/executor-window.py | 8 +++++++- .../resources/partitioned-popins.close.html.headers | 1 + .../resources/partitioned-popins.cookies-popin.py | 1 + .../partitioned-popins.localStorage-popin.html.headers | 1 + .../partitioned-popins.permissions-popin.html.headers | 1 + .../resources/partitioned-popins.proxy-popin.html.headers | 1 + .../resources/partitioned-popins.recursive.html.headers | 1 + .../resources/partitioned-popins.request-header.http.py | 1 + .../partitioned-popins.request-header.initial.py | 1 + .../resources/partitioned-popins.request-header.js.py | 1 + .../resources/partitioned-popins.wait.html.headers | 1 + .../resources/popinContextType.html.headers | 1 + .../resources/popinContextTypesSupported.html.headers | 1 + 13 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 partitioned-popins/resources/partitioned-popins.close.html.headers create mode 100644 partitioned-popins/resources/partitioned-popins.localStorage-popin.html.headers create mode 100644 partitioned-popins/resources/partitioned-popins.permissions-popin.html.headers create mode 100644 partitioned-popins/resources/partitioned-popins.proxy-popin.html.headers create mode 100644 partitioned-popins/resources/partitioned-popins.recursive.html.headers create mode 100644 partitioned-popins/resources/partitioned-popins.wait.html.headers create mode 100644 partitioned-popins/resources/popinContextType.html.headers create mode 100644 partitioned-popins/resources/popinContextTypesSupported.html.headers diff --git a/html/browsers/browsing-the-web/remote-context-helper/resources/executor-window.py b/html/browsers/browsing-the-web/remote-context-helper/resources/executor-window.py index 733d36b15edcde..c971f8d413b2fb 100644 --- a/html/browsers/browsing-the-web/remote-context-helper/resources/executor-window.py +++ b/html/browsers/browsing-the-web/remote-context-helper/resources/executor-window.py @@ -24,9 +24,15 @@ def main(request, response): start_on = query.get("startOn") start_on_s = f"'{start_on[0]}'" if start_on else "null" + headers = [("Content-Type", "text/html")] + # We always permit partitioned popins to be loaded for testing. + # See https://explainers-by-googlers.github.io/partitioned-popins/ + if request.headers.get(b"Sec-Popin-Context") == b"partitioned": + headers.append((b'Popin-Policy', b"partitioned=*")) + # This sets a base href so that even if this content e.g. data or blob URLs # document, relative URLs will resolve. - return (status, [("Content-Type", "text/html")], f""" + return (status, headers, f""" diff --git a/partitioned-popins/resources/partitioned-popins.close.html.headers b/partitioned-popins/resources/partitioned-popins.close.html.headers new file mode 100644 index 00000000000000..783b6856418d29 --- /dev/null +++ b/partitioned-popins/resources/partitioned-popins.close.html.headers @@ -0,0 +1 @@ +Popin-Policy: partitioned=* diff --git a/partitioned-popins/resources/partitioned-popins.cookies-popin.py b/partitioned-popins/resources/partitioned-popins.cookies-popin.py index f5d94c3c5f1bf4..74024dd2f002b1 100644 --- a/partitioned-popins/resources/partitioned-popins.cookies-popin.py +++ b/partitioned-popins/resources/partitioned-popins.cookies-popin.py @@ -3,6 +3,7 @@ def main(request, response): id = request.GET[b'id'] headers = setNoCacheAndCORSHeaders(request, response) headers[0] = (b"Content-Type", b"text/html") + headers.append((b'Popin-Policy', b"partitioned=*")) cookies = readCookies(request) message = b"ReadOnLoad:" if cookies.get(b"first-party-strict") == id: diff --git a/partitioned-popins/resources/partitioned-popins.localStorage-popin.html.headers b/partitioned-popins/resources/partitioned-popins.localStorage-popin.html.headers new file mode 100644 index 00000000000000..783b6856418d29 --- /dev/null +++ b/partitioned-popins/resources/partitioned-popins.localStorage-popin.html.headers @@ -0,0 +1 @@ +Popin-Policy: partitioned=* diff --git a/partitioned-popins/resources/partitioned-popins.permissions-popin.html.headers b/partitioned-popins/resources/partitioned-popins.permissions-popin.html.headers new file mode 100644 index 00000000000000..783b6856418d29 --- /dev/null +++ b/partitioned-popins/resources/partitioned-popins.permissions-popin.html.headers @@ -0,0 +1 @@ +Popin-Policy: partitioned=* diff --git a/partitioned-popins/resources/partitioned-popins.proxy-popin.html.headers b/partitioned-popins/resources/partitioned-popins.proxy-popin.html.headers new file mode 100644 index 00000000000000..783b6856418d29 --- /dev/null +++ b/partitioned-popins/resources/partitioned-popins.proxy-popin.html.headers @@ -0,0 +1 @@ +Popin-Policy: partitioned=* diff --git a/partitioned-popins/resources/partitioned-popins.recursive.html.headers b/partitioned-popins/resources/partitioned-popins.recursive.html.headers new file mode 100644 index 00000000000000..783b6856418d29 --- /dev/null +++ b/partitioned-popins/resources/partitioned-popins.recursive.html.headers @@ -0,0 +1 @@ +Popin-Policy: partitioned=* diff --git a/partitioned-popins/resources/partitioned-popins.request-header.http.py b/partitioned-popins/resources/partitioned-popins.request-header.http.py index 440d9da94dde94..60a0fc2a28a438 100644 --- a/partitioned-popins/resources/partitioned-popins.request-header.http.py +++ b/partitioned-popins/resources/partitioned-popins.request-header.http.py @@ -3,6 +3,7 @@ def main(request, response): # Step 4 (partitioned-popins/partitioned-popins.request-header.tentative.https.window.js) headers = setNoCacheAndCORSHeaders(request, response) headers[0] = (b"Content-Type", b"text/html") + headers.append((b'Popin-Policy', b"partitioned=*")) message = request.GET[b'message'] message += b"HTTP(" message += request.headers.get(b"Sec-Popin-Context", b"missing") diff --git a/partitioned-popins/resources/partitioned-popins.request-header.initial.py b/partitioned-popins/resources/partitioned-popins.request-header.initial.py index 59e7e947876c81..f182ae3dee18a0 100644 --- a/partitioned-popins/resources/partitioned-popins.request-header.initial.py +++ b/partitioned-popins/resources/partitioned-popins.request-header.initial.py @@ -6,4 +6,5 @@ def main(request, response): message += b")-" headers = setNoCacheAndCORSHeaders(request, response) headers.append((b'Location', b"/partitioned-popins/resources/partitioned-popins.request-header.http.py?message=" + message)) + headers.append((b'Popin-Policy', b"partitioned=*")) return 302, headers, b'{"redirect": true}' \ No newline at end of file diff --git a/partitioned-popins/resources/partitioned-popins.request-header.js.py b/partitioned-popins/resources/partitioned-popins.request-header.js.py index 603891733fde7f..7878693b220af9 100644 --- a/partitioned-popins/resources/partitioned-popins.request-header.js.py +++ b/partitioned-popins/resources/partitioned-popins.request-header.js.py @@ -3,6 +3,7 @@ def main(request, response): # Step 5 (partitioned-popins/partitioned-popins.request-header.tentative.https.window.js) headers = setNoCacheAndCORSHeaders(request, response) headers[0] = (b"Content-Type", b"text/html") + headers.append((b'Popin-Policy', b"partitioned=*")) message = request.GET[b'message'] message += b"JS(" message += request.headers.get(b"Sec-Popin-Context", b"missing") diff --git a/partitioned-popins/resources/partitioned-popins.wait.html.headers b/partitioned-popins/resources/partitioned-popins.wait.html.headers new file mode 100644 index 00000000000000..783b6856418d29 --- /dev/null +++ b/partitioned-popins/resources/partitioned-popins.wait.html.headers @@ -0,0 +1 @@ +Popin-Policy: partitioned=* diff --git a/partitioned-popins/resources/popinContextType.html.headers b/partitioned-popins/resources/popinContextType.html.headers new file mode 100644 index 00000000000000..783b6856418d29 --- /dev/null +++ b/partitioned-popins/resources/popinContextType.html.headers @@ -0,0 +1 @@ +Popin-Policy: partitioned=* diff --git a/partitioned-popins/resources/popinContextTypesSupported.html.headers b/partitioned-popins/resources/popinContextTypesSupported.html.headers new file mode 100644 index 00000000000000..783b6856418d29 --- /dev/null +++ b/partitioned-popins/resources/popinContextTypesSupported.html.headers @@ -0,0 +1 @@ +Popin-Policy: partitioned=*