From 50c5deee59852ae7191244ccbbf986280c73264c Mon Sep 17 00:00:00 2001 From: Domenic Denicola Date: Wed, 17 Jun 2020 06:36:31 -0700 Subject: [PATCH] Origin isolation: implement window.originIsolationRestricted See https://github.com/WICG/origin-isolation/issues/24 and https://github.com/WICG/origin-isolation/pull/30 for background, and https://github.com/whatwg/html/pull/5545 for the specification. Failing test expectations include: - We implement (3) from https://github.com/WICG/origin-isolation/issues/24 instead of (2) for now, so we fail getter-sandboxed-iframe. Tracking at https://crbug.com/1095653. - data: URLs are not [SecureContext] in Chromium (https://crbug.com/1095656) so getter-data-url fails. - Other failures are due to the lack of origin vs site-keying, which is now more directly observable. See bug 1067389. Bug: 1042415, 1067389 Change-Id: I20c2d3e3fec7a5c0f1d12c386999c32fe27b6a34 --- origin-isolation/getter-data-url.https.html | 38 +++++++++++++++++++ .../getter-data-url.https.html.headers | 1 + .../getter-removed-iframe.sub.https.html | 27 +++++++++++++ ...tter-removed-iframe.sub.https.html.headers | 1 + .../getter-sandboxed-iframe.sub.https.html | 30 +++++++++++++++ ...er-sandboxed-iframe.sub.https.html.headers | 1 + origin-isolation/insecure-http.sub.html | 5 +++ ...rent-no-child-bad-subdomain.sub.https.html | 7 +++- .../parent-no-child-yes-same.sub.https.html | 8 +++- ...rent-no-child-yes-subdomain.sub.https.html | 8 +++- ...d-yes-with-params-subdomain.sub.https.html | 8 +++- ...ild2-yes-children-different.sub.https.html | 5 +++ ...no-child2-yes-children-same.sub.https.html | 10 ++++- ...yes-child2-no-children-same.sub.https.html | 5 +++ .../parent-yes-child-no-same.sub.https.html | 9 ++++- ...rent-yes-child-no-subdomain.sub.https.html | 9 ++++- .../parent-yes-child-yes-same.sub.https.html | 9 ++++- ...ent-yes-child-yes-subdomain.sub.https.html | 9 ++++- ...hild2-no-children-different.sub.https.html | 5 +++ ...-no-child2-no-children-same.sub.https.html | 5 +++ ...ild2-yes-children-different.sub.https.html | 6 ++- ...no-child2-yes-children-same.sub.https.html | 5 +++ ...yes-child2-no-children-same.sub.https.html | 5 +++ ...ild2-yes-children-different.sub.https.html | 6 ++- ...es-child2-yes-children-same.sub.https.html | 5 +++ .../removing-iframes.sub.https.html | 8 +++- origin-isolation/resources/helpers.mjs | 33 ++++++++++++++++ .../resources/helpers.mjs.headers | 1 + .../resources/send-origin-isolation-header.py | 4 +- 29 files changed, 260 insertions(+), 13 deletions(-) create mode 100644 origin-isolation/getter-data-url.https.html create mode 100644 origin-isolation/getter-data-url.https.html.headers create mode 100644 origin-isolation/getter-removed-iframe.sub.https.html create mode 100644 origin-isolation/getter-removed-iframe.sub.https.html.headers create mode 100644 origin-isolation/getter-sandboxed-iframe.sub.https.html create mode 100644 origin-isolation/getter-sandboxed-iframe.sub.https.html.headers create mode 100644 origin-isolation/resources/helpers.mjs.headers diff --git a/origin-isolation/getter-data-url.https.html b/origin-isolation/getter-data-url.https.html new file mode 100644 index 00000000000000..da2c87b1270eb2 --- /dev/null +++ b/origin-isolation/getter-data-url.https.html @@ -0,0 +1,38 @@ + + +window.originIsolationRestricted for a data: URL + + + +
+ + diff --git a/origin-isolation/getter-data-url.https.html.headers b/origin-isolation/getter-data-url.https.html.headers new file mode 100644 index 00000000000000..ea3f6b335c7620 --- /dev/null +++ b/origin-isolation/getter-data-url.https.html.headers @@ -0,0 +1 @@ +Origin-Isolation: ?1 diff --git a/origin-isolation/getter-removed-iframe.sub.https.html b/origin-isolation/getter-removed-iframe.sub.https.html new file mode 100644 index 00000000000000..a1373468e22fea --- /dev/null +++ b/origin-isolation/getter-removed-iframe.sub.https.html @@ -0,0 +1,27 @@ + + +window.crossOriginIsolated for a removed frame + + + +
+ + diff --git a/origin-isolation/getter-removed-iframe.sub.https.html.headers b/origin-isolation/getter-removed-iframe.sub.https.html.headers new file mode 100644 index 00000000000000..ea3f6b335c7620 --- /dev/null +++ b/origin-isolation/getter-removed-iframe.sub.https.html.headers @@ -0,0 +1 @@ +Origin-Isolation: ?1 diff --git a/origin-isolation/getter-sandboxed-iframe.sub.https.html b/origin-isolation/getter-sandboxed-iframe.sub.https.html new file mode 100644 index 00000000000000..366fae6e5e9597 --- /dev/null +++ b/origin-isolation/getter-sandboxed-iframe.sub.https.html @@ -0,0 +1,30 @@ + + +window.originIsolationRestricted for a sandboxed frame + + + +
+ + diff --git a/origin-isolation/getter-sandboxed-iframe.sub.https.html.headers b/origin-isolation/getter-sandboxed-iframe.sub.https.html.headers new file mode 100644 index 00000000000000..ea3f6b335c7620 --- /dev/null +++ b/origin-isolation/getter-sandboxed-iframe.sub.https.html.headers @@ -0,0 +1 @@ +Origin-Isolation: ?1 diff --git a/origin-isolation/insecure-http.sub.html b/origin-isolation/insecure-http.sub.html index 1e78b13385727e..83df16af455133 100644 --- a/origin-isolation/insecure-http.sub.html +++ b/origin-isolation/insecure-http.sub.html @@ -16,4 +16,9 @@ // All isolation requests are ignored, since this is over insecure HTTP. // So both end up in the site-keyed agent cluster. testSameAgentCluster([self, 0]); + +// Has to be promise_test because we used promise_setup(). +promise_test(async () => { + assert_false("originIsolationRestricted" in window); +}, "The getter must not exist"); diff --git a/origin-isolation/parent-no-child-bad-subdomain.sub.https.html b/origin-isolation/parent-no-child-bad-subdomain.sub.https.html index ae55f5d83e10ad..cfa39aaee034b0 100644 --- a/origin-isolation/parent-no-child-bad-subdomain.sub.https.html +++ b/origin-isolation/parent-no-child-bad-subdomain.sub.https.html @@ -7,7 +7,11 @@
diff --git a/origin-isolation/parent-no-child-yes-same.sub.https.html b/origin-isolation/parent-no-child-yes-same.sub.https.html index 8e32649d3a2d23..ece3b9732a5acb 100644 --- a/origin-isolation/parent-no-child-yes-same.sub.https.html +++ b/origin-isolation/parent-no-child-yes-same.sub.https.html @@ -7,7 +7,11 @@
diff --git a/origin-isolation/parent-no-child-yes-subdomain.sub.https.html b/origin-isolation/parent-no-child-yes-subdomain.sub.https.html index 7f4a9413e35702..ab060e24f4976a 100644 --- a/origin-isolation/parent-no-child-yes-subdomain.sub.https.html +++ b/origin-isolation/parent-no-child-yes-subdomain.sub.https.html @@ -7,7 +7,11 @@
diff --git a/origin-isolation/parent-no-child-yes-with-params-subdomain.sub.https.html b/origin-isolation/parent-no-child-yes-with-params-subdomain.sub.https.html index 0208ac3e14c66e..e1459b9cc08a92 100644 --- a/origin-isolation/parent-no-child-yes-with-params-subdomain.sub.https.html +++ b/origin-isolation/parent-no-child-yes-with-params-subdomain.sub.https.html @@ -7,7 +7,11 @@
diff --git a/origin-isolation/parent-no-child1-no-child2-yes-children-different.sub.https.html b/origin-isolation/parent-no-child1-no-child2-yes-children-different.sub.https.html index c019ef2fe7dfd0..17ee8a678a63a7 100644 --- a/origin-isolation/parent-no-child1-no-child2-yes-children-different.sub.https.html +++ b/origin-isolation/parent-no-child1-no-child2-yes-children-different.sub.https.html @@ -11,6 +11,7 @@ insertIframe, testSameAgentCluster, testDifferentAgentClusters, + testOriginIsolationRestricted } from "./resources/helpers.mjs"; promise_setup(async () => { @@ -30,4 +31,8 @@ testDifferentAgentClusters([self, 1], "Parent to child2"); testDifferentAgentClusters([0, 1], "child1 to child2"); testDifferentAgentClusters([1, 0], "child2 to child1"); + +testOriginIsolationRestricted(self, false, "parent"); +testOriginIsolationRestricted(0, false, "child1"); +testOriginIsolationRestricted(1, true, "child2"); diff --git a/origin-isolation/parent-no-child1-no-child2-yes-children-same.sub.https.html b/origin-isolation/parent-no-child1-no-child2-yes-children-same.sub.https.html index 9ca18f8941b375..17b82bc09df5cb 100644 --- a/origin-isolation/parent-no-child1-no-child2-yes-children-same.sub.https.html +++ b/origin-isolation/parent-no-child1-no-child2-yes-children-same.sub.https.html @@ -7,7 +7,11 @@
diff --git a/origin-isolation/parent-no-child1-yes-child2-no-children-same.sub.https.html b/origin-isolation/parent-no-child1-yes-child2-no-children-same.sub.https.html index 2947e629bd51d7..f6955c55c25a86 100644 --- a/origin-isolation/parent-no-child1-yes-child2-no-children-same.sub.https.html +++ b/origin-isolation/parent-no-child1-yes-child2-no-children-same.sub.https.html @@ -11,6 +11,7 @@ insertIframe, testSameAgentCluster, testDifferentAgentClusters, + testOriginIsolationRestricted } from "./resources/helpers.mjs"; promise_setup(async () => { @@ -30,4 +31,8 @@ testDifferentAgentClusters([self, 1], "Parent to child2"); testSameAgentCluster([0, 1], "child1 to child2"); testSameAgentCluster([1, 0], "child2 to child1"); + +testOriginIsolationRestricted(self, false, "parent"); +testOriginIsolationRestricted(0, true, "child1"); +testOriginIsolationRestricted(1, true, "child2"); diff --git a/origin-isolation/parent-yes-child-no-same.sub.https.html b/origin-isolation/parent-yes-child-no-same.sub.https.html index aa1dd94682ea81..7edebe9bd88d96 100644 --- a/origin-isolation/parent-yes-child-no-same.sub.https.html +++ b/origin-isolation/parent-yes-child-no-same.sub.https.html @@ -7,7 +7,11 @@
diff --git a/origin-isolation/parent-yes-child-no-subdomain.sub.https.html b/origin-isolation/parent-yes-child-no-subdomain.sub.https.html index 5055d295d03711..f0cd3c481130cf 100644 --- a/origin-isolation/parent-yes-child-no-subdomain.sub.https.html +++ b/origin-isolation/parent-yes-child-no-subdomain.sub.https.html @@ -7,7 +7,11 @@
diff --git a/origin-isolation/parent-yes-child-yes-same.sub.https.html b/origin-isolation/parent-yes-child-yes-same.sub.https.html index 3d99486a3cb517..c4917819617fc9 100644 --- a/origin-isolation/parent-yes-child-yes-same.sub.https.html +++ b/origin-isolation/parent-yes-child-yes-same.sub.https.html @@ -7,7 +7,11 @@
diff --git a/origin-isolation/parent-yes-child-yes-subdomain.sub.https.html b/origin-isolation/parent-yes-child-yes-subdomain.sub.https.html index afc8f5b2acdf9e..fc5b19843cbe49 100644 --- a/origin-isolation/parent-yes-child-yes-subdomain.sub.https.html +++ b/origin-isolation/parent-yes-child-yes-subdomain.sub.https.html @@ -7,7 +7,11 @@
diff --git a/origin-isolation/parent-yes-child1-no-child2-no-children-different.sub.https.html b/origin-isolation/parent-yes-child1-no-child2-no-children-different.sub.https.html index 77a77d50a1c83f..1635bd63848a40 100644 --- a/origin-isolation/parent-yes-child1-no-child2-no-children-different.sub.https.html +++ b/origin-isolation/parent-yes-child1-no-child2-no-children-different.sub.https.html @@ -11,6 +11,7 @@ insertIframe, testSameAgentCluster, testDifferentAgentClusters, + testOriginIsolationRestricted } from "./resources/helpers.mjs"; promise_setup(async () => { @@ -30,4 +31,8 @@ testDifferentAgentClusters([self, 1], "Parent to child2"); testSameAgentCluster([0, 1], "child1 to child2"); testSameAgentCluster([1, 0], "child2 to child1"); + +testOriginIsolationRestricted(self, true, "parent"); +testOriginIsolationRestricted(0, false, "child1"); +testOriginIsolationRestricted(1, false, "child2"); diff --git a/origin-isolation/parent-yes-child1-no-child2-no-children-same.sub.https.html b/origin-isolation/parent-yes-child1-no-child2-no-children-same.sub.https.html index b3f18e8560f7f3..0f2f29025e7624 100644 --- a/origin-isolation/parent-yes-child1-no-child2-no-children-same.sub.https.html +++ b/origin-isolation/parent-yes-child1-no-child2-no-children-same.sub.https.html @@ -11,6 +11,7 @@ insertIframe, testSameAgentCluster, testDifferentAgentClusters, + testOriginIsolationRestricted } from "./resources/helpers.mjs"; promise_setup(async () => { @@ -30,4 +31,8 @@ testDifferentAgentClusters([self, 1], "Parent to child2"); testSameAgentCluster([0, 1], "child1 to child2"); testSameAgentCluster([1, 0], "child2 to child1"); + +testOriginIsolationRestricted(self, true, "parent"); +testOriginIsolationRestricted(0, false, "child1"); +testOriginIsolationRestricted(1, false, "child2"); diff --git a/origin-isolation/parent-yes-child1-no-child2-yes-children-different.sub.https.html b/origin-isolation/parent-yes-child1-no-child2-yes-children-different.sub.https.html index 8e7b4d3ee5c4b1..c830e1548c073a 100644 --- a/origin-isolation/parent-yes-child1-no-child2-yes-children-different.sub.https.html +++ b/origin-isolation/parent-yes-child1-no-child2-yes-children-different.sub.https.html @@ -9,8 +9,8 @@ diff --git a/origin-isolation/parent-yes-child1-no-child2-yes-children-same.sub.https.html b/origin-isolation/parent-yes-child1-no-child2-yes-children-same.sub.https.html index 260ac80d2ff4ae..dc157a9eef9125 100644 --- a/origin-isolation/parent-yes-child1-no-child2-yes-children-same.sub.https.html +++ b/origin-isolation/parent-yes-child1-no-child2-yes-children-same.sub.https.html @@ -11,6 +11,7 @@ insertIframe, testSameAgentCluster, testDifferentAgentClusters, + testOriginIsolationRestricted } from "./resources/helpers.mjs"; promise_setup(async () => { @@ -30,4 +31,8 @@ testDifferentAgentClusters([self, 1], "Parent to child2"); testSameAgentCluster([0, 1], "child1 to child2"); testSameAgentCluster([1, 0], "child2 to child1"); + +testOriginIsolationRestricted(self, true, "parent"); +testOriginIsolationRestricted(0, false, "child1"); +testOriginIsolationRestricted(1, false, "child2"); diff --git a/origin-isolation/parent-yes-child1-yes-child2-no-children-same.sub.https.html b/origin-isolation/parent-yes-child1-yes-child2-no-children-same.sub.https.html index ae54fcd02ea8e1..033fdd2827fddf 100644 --- a/origin-isolation/parent-yes-child1-yes-child2-no-children-same.sub.https.html +++ b/origin-isolation/parent-yes-child1-yes-child2-no-children-same.sub.https.html @@ -11,6 +11,7 @@ insertIframe, testSameAgentCluster, testDifferentAgentClusters, + testOriginIsolationRestricted } from "./resources/helpers.mjs"; promise_setup(async () => { @@ -30,4 +31,8 @@ testDifferentAgentClusters([self, 1], "Parent to child2"); testSameAgentCluster([0, 1], "child1 to child2"); testSameAgentCluster([1, 0], "child2 to child1"); + +testOriginIsolationRestricted(self, true, "parent"); +testOriginIsolationRestricted(0, true, "child1"); +testOriginIsolationRestricted(1, true, "child2"); diff --git a/origin-isolation/parent-yes-child1-yes-child2-yes-children-different.sub.https.html b/origin-isolation/parent-yes-child1-yes-child2-yes-children-different.sub.https.html index 775f753561b386..2c1f1341df5187 100644 --- a/origin-isolation/parent-yes-child1-yes-child2-yes-children-different.sub.https.html +++ b/origin-isolation/parent-yes-child1-yes-child2-yes-children-different.sub.https.html @@ -9,8 +9,8 @@ diff --git a/origin-isolation/parent-yes-child1-yes-child2-yes-children-same.sub.https.html b/origin-isolation/parent-yes-child1-yes-child2-yes-children-same.sub.https.html index a3b0939862ce4d..2de08307fcb79f 100644 --- a/origin-isolation/parent-yes-child1-yes-child2-yes-children-same.sub.https.html +++ b/origin-isolation/parent-yes-child1-yes-child2-yes-children-same.sub.https.html @@ -11,6 +11,7 @@ insertIframe, testSameAgentCluster, testDifferentAgentClusters, + testOriginIsolationRestricted } from "./resources/helpers.mjs"; promise_setup(async () => { @@ -31,4 +32,8 @@ testDifferentAgentClusters([self, 1], "Parent to child2"); testSameAgentCluster([0, 1], "child1 to child2"); testSameAgentCluster([1, 0], "child2 to child1"); + +testOriginIsolationRestricted(self, true, "parent"); +testOriginIsolationRestricted(0, true, "child1"); +testOriginIsolationRestricted(1, true, "child2"); diff --git a/origin-isolation/removing-iframes.sub.https.html b/origin-isolation/removing-iframes.sub.https.html index 2f01562b04cc83..3a6d91c447a972 100644 --- a/origin-isolation/removing-iframes.sub.https.html +++ b/origin-isolation/removing-iframes.sub.https.html @@ -1,6 +1,6 @@ -Parent is isolated, child1 is not isolated, child1 navigates to a different site, child2 gets inserted and is isolated, child1 navigates back +A non-isolated child at a given origin causes future children to also be non-isolated even after the iframe is removed @@ -11,6 +11,7 @@ insertIframe, testSameAgentCluster, testDifferentAgentClusters, + testOriginIsolationRestricted } from "./resources/helpers.mjs"; let frame1; @@ -22,6 +23,8 @@ // as is the child's non-request. So the parent ends up in the origin-keyed // agent cluster and the child ends up in the site-keyed one. testDifferentAgentClusters([self, 0], "Before"); +testOriginIsolationRestricted(self, true, "parent"); +testOriginIsolationRestricted(0, false, "child1"); promise_test(async () => { frame1.remove(); @@ -37,4 +40,7 @@ testDifferentAgentClusters([self, 1], "Parent to child3"); testSameAgentCluster([0, 1], "child2 to child3"); testSameAgentCluster([1, 0], "child3 to child2"); + +testOriginIsolationRestricted(0, false, "child2"); +testOriginIsolationRestricted(1, false, "child3"); diff --git a/origin-isolation/resources/helpers.mjs b/origin-isolation/resources/helpers.mjs index 4b742c2b6e731c..fd47a4f0c68c89 100644 --- a/origin-isolation/resources/helpers.mjs +++ b/origin-isolation/resources/helpers.mjs @@ -150,6 +150,32 @@ export function testDifferentAgentClusters(testFrames, testLabelPrefix) { } } +/** + * Creates a promise_test() to check the value of the originIsolationRestricted + * getter in the given testFrame. + * @param {Window|number} testFrame - Either self, or a frame index to test. + * @param {boolean} expected - The expected value for originIsolationRestricted. + * @param {string=} testLabelPrefix - A prefix used in the test names. This can + * be omitted if the function is only used once in a test file. + */ +export function testOriginIsolationRestricted(testFrame, expected, testLabelPrefix) { + const prefix = testLabelPrefix === undefined ? "" : `${testLabelPrefix}: `; + + if (testFrame === self) { + // Need to use promise_test() even though it's sync because we use + // promise_setup() in many tests. + promise_test(async () => { + assert_equals(self.originIsolationRestricted, expected); + }, `${prefix}originIsolationRestricted must equal ${expected}`); + } else { + promise_test(async () => { + const frameWindow = frames[testFrame]; + const result = await getOriginIsolationRestricted(frameWindow); + assert_equals(result, expected); + }, `${prefix}originIsolationRestricted must equal ${expected}`); + } +} + /** * Sends a WebAssembly.Module instance to the given Window, and waits for it to * send back a message indicating whether it got the module or got a @@ -189,6 +215,13 @@ export async function setBothDocumentDomains(frameWindow) { assert_equals(whatHappened, "document.domain is set"); } +async function getOriginIsolationRestricted(frameWindow) { + // This function is coupled to ./send-origin-isolation-header.py, which ensures + // that sending such a message will result in a message back. + frameWindow.postMessage({ command: "get originIsolationRestricted" }, "*"); + return waitForMessage(frameWindow); +} + function getIframeURL(hostname, header) { const url = new URL("send-origin-isolation-header.py", import.meta.url); url.hostname = hostname; diff --git a/origin-isolation/resources/helpers.mjs.headers b/origin-isolation/resources/helpers.mjs.headers new file mode 100644 index 00000000000000..cb762eff806849 --- /dev/null +++ b/origin-isolation/resources/helpers.mjs.headers @@ -0,0 +1 @@ +Access-Control-Allow-Origin: * diff --git a/origin-isolation/resources/send-origin-isolation-header.py b/origin-isolation/resources/send-origin-isolation-header.py index b0ba30fcd4939f..165fdaa30c20be 100644 --- a/origin-isolation/resources/send-origin-isolation-header.py +++ b/origin-isolation/resources/send-origin-isolation-header.py @@ -43,6 +43,8 @@ def main(request, response): } catch (e) { parent.postMessage(e.name, "*"); } + } else if (e.data.command === "get originIsolationRestricted") { + parent.postMessage(self.originIsolationRestricted, "*"); } // We could also receive e.data === "WebAssembly.Module message received", @@ -53,6 +55,6 @@ def main(request, response): e.source.postMessage("messageerror", "*"); }; - document.body.textContent = location.href; + document.body.append(location.href); """