Title: [291741] trunk
Revision
291741
Author
you...@apple.com
Date
2022-03-23 02:04:48 -0700 (Wed, 23 Mar 2022)

Log Message

Computation of Document siteForCookies is buggy in case document is created by window.open
https://bugs.webkit.org/show_bug.cgi?id=238202
<rdar://88979099>

Reviewed by John Wilander.

Source/WebCore:

For top level navigations, we need to use the security origin to compute siteForCookies as the document
may have the opener security origin.
Add a Document routine to handle this case.

Tests: http/tests/cookies/same-site/popup-from-iframe-same-site-with-post-form.html
       http/tests/cookies/same-site/popup-same-site-with-post-form.html

* dom/Document.cpp:
* dom/Document.h:
* loader/FrameLoader.cpp:

LayoutTests:

* http/tests/cookies/resources/testharness-helpers.js:
* http/tests/cookies/same-site/popup-from-iframe-same-site-with-post-form-expected.txt: Added.
* http/tests/cookies/same-site/popup-from-iframe-same-site-with-post-form.html: Added.
* http/tests/cookies/same-site/popup-same-site-with-post-form-expected.txt: Added.
* http/tests/cookies/same-site/popup-same-site-with-post-form.html: Added.
* http/tests/cookies/same-site/resources/popup-iframe.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (291740 => 291741)


--- trunk/LayoutTests/ChangeLog	2022-03-23 08:40:10 UTC (rev 291740)
+++ trunk/LayoutTests/ChangeLog	2022-03-23 09:04:48 UTC (rev 291741)
@@ -1,3 +1,18 @@
+2022-03-23  Youenn Fablet  <you...@apple.com>
+
+        Computation of Document siteForCookies is buggy in case document is created by window.open
+        https://bugs.webkit.org/show_bug.cgi?id=238202
+        <rdar://88979099>
+
+        Reviewed by John Wilander.
+
+        * http/tests/cookies/resources/testharness-helpers.js:
+        * http/tests/cookies/same-site/popup-from-iframe-same-site-with-post-form-expected.txt: Added.
+        * http/tests/cookies/same-site/popup-from-iframe-same-site-with-post-form.html: Added.
+        * http/tests/cookies/same-site/popup-same-site-with-post-form-expected.txt: Added.
+        * http/tests/cookies/same-site/popup-same-site-with-post-form.html: Added.
+        * http/tests/cookies/same-site/resources/popup-iframe.html: Added.
+
 2022-03-23  Razvan Caliman  <rcali...@apple.com>
 
         Web Inspector: Styles panel: Unwanted extra dash when autocompleting CSS variable names

Modified: trunk/LayoutTests/http/tests/cookies/resources/testharness-helpers.js (291740 => 291741)


--- trunk/LayoutTests/http/tests/cookies/resources/testharness-helpers.js	2022-03-23 08:40:10 UTC (rev 291740)
+++ trunk/LayoutTests/http/tests/cookies/resources/testharness-helpers.js	2022-03-23 09:04:48 UTC (rev 291741)
@@ -20,3 +20,72 @@
     return cookie.split(/;\s*/).sort().join("; ");
 }
 
+function with_iframe(url) {
+    return new Promise(function(resolve) {
+        var frame = document.createElement('iframe');
+        frame.src = ""
+        frame._onload_ = function() { setTimeout(() => resolve(frame), 0); };
+        document.body.appendChild(frame);
+    });
+}
+
+function loadPopupThenTriggerPost()
+{
+    let finish;
+    let promise = new Promise(resolve => finish = resolve);
+
+    clearKnownCookies();
+    document.cookie = LAX_DOM + "=1; SameSite=Lax; Max-Age=100; path=/";
+    document.cookie = NORMAL_DOM + "=1; Max-Age=100; path=/";
+    document.cookie = STRICT_DOM + "=1; SameSite=Strict; Max-Age=100; path=/";
+
+    const opener = window.open("http://127.0.0.1:8000/cookies/resources/post-cookies-to-opener.py")
+    window._onmessage_ = e => {
+        window._onmessage_ = e => {
+            opener.close();
+            finish(e.data);
+        };
+
+        const newDoc = opener.document;
+        var form = newDoc.createElement('form');
+        form.method = 'POST';
+        form.action = '';
+        var input = newDoc.createElement('input');
+        input.name = 'name';
+        input.value = 'value';
+        form.appendChild(input);
+        newDoc.body.appendChild(form);
+        form.submit();
+    };
+    return promise;
+}
+
+function openPopupAndTriggerPost(popupURL, callback)
+{
+    let finish;
+    let promise = new Promise(resolve => finish = resolve);
+
+    clearKnownCookies();
+    document.cookie = LAX_DOM + "=1; SameSite=Lax; Max-Age=100; path=/";
+    document.cookie = NORMAL_DOM + "=1; Max-Age=100; path=/";
+    document.cookie = STRICT_DOM + "=1; SameSite=Strict; Max-Age=100; path=/";
+
+    window.addEventListener("message", e => {
+        opener.close();
+        finish(e.data);
+    });
+
+    const opener = window.open(popupURL)
+    const newDoc = opener.document;
+    var form = newDoc.createElement('form');
+    form.method = 'POST';
+    form.action = '';
+    var input = newDoc.createElement('input');
+    input.name = 'name';
+    input.value = 'value';
+    form.appendChild(input);
+    newDoc.body.appendChild(form);
+    form.submit();
+
+    return promise;
+}

Added: trunk/LayoutTests/http/tests/cookies/same-site/popup-from-iframe-same-site-with-post-form-expected.txt (0 => 291741)


--- trunk/LayoutTests/http/tests/cookies/same-site/popup-from-iframe-same-site-with-post-form-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/http/tests/cookies/same-site/popup-from-iframe-same-site-with-post-form-expected.txt	2022-03-23 09:04:48 UTC (rev 291741)
@@ -0,0 +1,5 @@
+
+PASS popup opened as 'about:blank' from an iframe, then post navigation to 127.0.0.1, so samesite cookies are sent.
+PASS popup opened as '127.0.0.1' from an iframe, then post navigation to 127.0.0.1, so samesite cookies are sent.
+PASS popup loaded as '127.0.0.1' from an iframe, then post navigation to 127.0.0.1, so samesite cookies are sent.
+

Added: trunk/LayoutTests/http/tests/cookies/same-site/popup-from-iframe-same-site-with-post-form.html (0 => 291741)


--- trunk/LayoutTests/http/tests/cookies/same-site/popup-from-iframe-same-site-with-post-form.html	                        (rev 0)
+++ trunk/LayoutTests/http/tests/cookies/same-site/popup-from-iframe-same-site-with-post-form.html	2022-03-23 09:04:48 UTC (rev 291741)
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<script src=""
+<script src=""
+<script src=""
+<body>
+<script>
+promise_test(async t => {
+    const frame = await with_iframe("resources/popup-iframe.html");
+    const data = "" frame.contentWindow.openPopupAndTriggerPost("about:blank");
+    frame.remove();
+    assert_equals(data.http[LAX_DOM], "1", "lax");
+    assert_equals(data.http[NORMAL_DOM], "1", "normal");
+    assert_equals(data.http[STRICT_DOM], "1", "strict");
+}, "popup opened as 'about:blank' from an iframe, then post navigation to 127.0.0.1, so samesite cookies are sent.");
+
+promise_test(async t => {
+    const frame = await with_iframe("resources/popup-iframe.html");
+    const data = "" frame.contentWindow.openPopupAndTriggerPost("http://127.0.0.1:8000");
+    frame.remove();
+    assert_equals(data.http[LAX_DOM], "1", "lax");
+    assert_equals(data.http[NORMAL_DOM], "1", "normal");
+    assert_equals(data.http[STRICT_DOM], "1", "strict");
+}, "popup opened as '127.0.0.1' from an iframe, then post navigation to 127.0.0.1, so samesite cookies are sent.");
+
+promise_test(async t => {
+    const frame = await with_iframe("resources/popup-iframe.html");
+    const data = "" frame.contentWindow.loadPopupThenTriggerPost();
+    frame.remove();
+    assert_equals(data.http[LAX_DOM], "1", "lax");
+    assert_equals(data.http[NORMAL_DOM], "1", "normal");
+    assert_equals(data.http[STRICT_DOM], "1", "strict");
+}, "popup loaded as '127.0.0.1' from an iframe, then post navigation to 127.0.0.1, so samesite cookies are sent.");
+</script>
+</body>

Added: trunk/LayoutTests/http/tests/cookies/same-site/popup-same-site-with-post-form-expected.txt (0 => 291741)


--- trunk/LayoutTests/http/tests/cookies/same-site/popup-same-site-with-post-form-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/http/tests/cookies/same-site/popup-same-site-with-post-form-expected.txt	2022-03-23 09:04:48 UTC (rev 291741)
@@ -0,0 +1,5 @@
+
+PASS popup opened as 'about:blank', then post navigation to 127.0.0.1, so samesite cookies are sent.
+PASS popup opened as '127.0.0.1', then post navigation to 127.0.0.1, so samesite cookies are sent.
+PASS popup loaded as '127.0.0.1', then post navigation to 127.0.0.1, so samesite cookies are sent.
+

Added: trunk/LayoutTests/http/tests/cookies/same-site/popup-same-site-with-post-form.html (0 => 291741)


--- trunk/LayoutTests/http/tests/cookies/same-site/popup-same-site-with-post-form.html	                        (rev 0)
+++ trunk/LayoutTests/http/tests/cookies/same-site/popup-same-site-with-post-form.html	2022-03-23 09:04:48 UTC (rev 291741)
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<script src=""
+<script src=""
+<script src=""
+<script>
+promise_test(async t => {
+    const data = "" openPopupAndTriggerPost("about:blank");
+    assert_equals(data.http[LAX_DOM], "1", "lax");
+    assert_equals(data.http[NORMAL_DOM], "1", "normal");
+    assert_equals(data.http[STRICT_DOM], "1", "strict");
+}, "popup opened as 'about:blank', then post navigation to 127.0.0.1, so samesite cookies are sent.");
+
+promise_test(async t => {
+    const data = "" openPopupAndTriggerPost("http://127.0.0.1:8000");
+    assert_equals(data.http[LAX_DOM], "1", "lax");
+    assert_equals(data.http[NORMAL_DOM], "1", "normal");
+    assert_equals(data.http[STRICT_DOM], "1", "strict");
+}, "popup opened as '127.0.0.1', then post navigation to 127.0.0.1, so samesite cookies are sent.");
+
+promise_test(async t => {
+    const data = "" loadPopupThenTriggerPost();
+    assert_equals(data.http[LAX_DOM], "1", "lax");
+    assert_equals(data.http[NORMAL_DOM], "1", "normal");
+    assert_equals(data.http[STRICT_DOM], "1", "strict");
+}, "popup loaded as '127.0.0.1', then post navigation to 127.0.0.1, so samesite cookies are sent.");
+</script>

Added: trunk/LayoutTests/http/tests/cookies/same-site/resources/popup-iframe.html (0 => 291741)


--- trunk/LayoutTests/http/tests/cookies/same-site/resources/popup-iframe.html	                        (rev 0)
+++ trunk/LayoutTests/http/tests/cookies/same-site/resources/popup-iframe.html	2022-03-23 09:04:48 UTC (rev 291741)
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<script src=""
+<body>
+</body>

Modified: trunk/Source/WebCore/ChangeLog (291740 => 291741)


--- trunk/Source/WebCore/ChangeLog	2022-03-23 08:40:10 UTC (rev 291740)
+++ trunk/Source/WebCore/ChangeLog	2022-03-23 09:04:48 UTC (rev 291741)
@@ -1,3 +1,22 @@
+2022-03-23  Youenn Fablet  <you...@apple.com>
+
+        Computation of Document siteForCookies is buggy in case document is created by window.open
+        https://bugs.webkit.org/show_bug.cgi?id=238202
+        <rdar://88979099>
+
+        Reviewed by John Wilander.
+
+        For top level navigations, we need to use the security origin to compute siteForCookies as the document
+        may have the opener security origin.
+        Add a Document routine to handle this case.
+
+        Tests: http/tests/cookies/same-site/popup-from-iframe-same-site-with-post-form.html
+               http/tests/cookies/same-site/popup-same-site-with-post-form.html
+
+        * dom/Document.cpp:
+        * dom/Document.h:
+        * loader/FrameLoader.cpp:
+
 2022-03-22  Ben Nham  <n...@apple.com>
 
         Only show notification permission prompt on transient activation

Modified: trunk/Source/WebCore/dom/Document.cpp (291740 => 291741)


--- trunk/Source/WebCore/dom/Document.cpp	2022-03-23 08:40:10 UTC (rev 291740)
+++ trunk/Source/WebCore/dom/Document.cpp	2022-03-23 09:04:48 UTC (rev 291741)
@@ -9137,6 +9137,12 @@
     return m_elementsWithPendingUserAgentShadowTreeUpdates.contains(element);
 }
 
+bool Document::isSameSiteForCookies(const URL& url) const
+{
+    auto domain = isTopDocument() ? RegistrableDomain(securityOrigin().data()) : RegistrableDomain(siteForCookies());
+    return domain.matches(url);
+}
+
 } // namespace WebCore
 
 #undef DOCUMENT_RELEASE_LOG

Modified: trunk/Source/WebCore/dom/Document.h (291740 => 291741)


--- trunk/Source/WebCore/dom/Document.h	2022-03-23 08:40:10 UTC (rev 291740)
+++ trunk/Source/WebCore/dom/Document.h	2022-03-23 09:04:48 UTC (rev 291741)
@@ -1017,7 +1017,8 @@
     // URL. For the top-level document, it is set to the document's URL.
     const URL& siteForCookies() const { return m_siteForCookies; }
     void setSiteForCookies(const URL& url) { m_siteForCookies = url; }
-    
+    bool isSameSiteForCookies(const URL&) const;
+
     // The following implements the rule from HTML 4 for what valid names are.
     // To get this right for all the XML cases, we probably have to improve this or move it
     // and make it sensitive to the type of document.

Modified: trunk/Source/WebCore/loader/FrameLoader.cpp (291740 => 291741)


--- trunk/Source/WebCore/loader/FrameLoader.cpp	2022-03-23 08:40:10 UTC (rev 291740)
+++ trunk/Source/WebCore/loader/FrameLoader.cpp	2022-03-23 09:04:48 UTC (rev 291741)
@@ -3038,7 +3038,8 @@
         request.setIsSameSite(true);
         return;
     }
-    request.setIsSameSite(areRegistrableDomainsEqual(initiator->siteForCookies(), request.url()));
+
+    request.setIsSameSite(initiator->isSameSiteForCookies(request.url()));
 }
 
 void FrameLoader::loadPostRequest(FrameLoadRequest&& request, const String& referrer, FrameLoadType loadType, Event* event, RefPtr<FormState>&& formState, CompletionHandler<void()>&& completionHandler)
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to