Title: [287209] releases/WebKitGTK/webkit-2.34
Revision
287209
Author
[email protected]
Date
2021-12-17 14:48:02 -0800 (Fri, 17 Dec 2021)

Log Message

Merge r281941 - [COOP] html/cross-origin-opener-policy/coop-navigate-same-origin-csp-sandbox.html WPT test is failing
https://bugs.webkit.org/show_bug.cgi?id=229716

Reviewed by Darin Adler.

LayoutTests/imported/w3c:

Rebaseline WPT test that is now passing.

* web-platform-tests/html/cross-origin-opener-policy/coop-navigate-same-origin-csp-sandbox-expected.txt:

Source/WebCore:

The COOP algorithm is relying on the response origin for some of the checks. We were computing the
response origin via `SecurityOrigin::create(response.url())`, which worked fine in most cases.
However, the response may contain a CSP header, which could set sandbox flags. If sandbox flags
are set, the response origin should be unique, not the origin of the response URL. This patch fixes
that.

No new tests, rebaselined existing WPT test.

* loader/DocumentLoader.cpp:
(WebCore::computeResponseOriginAndCOOP):
(WebCore::DocumentLoader::doCrossOriginOpenerHandlingOfResponse):
* loader/DocumentLoader.h:
(WebCore::DocumentLoader::contentSecurityPolicy const):
* loader/FrameLoader.cpp:
(WebCore::FrameLoader::didBeginDocument):
* page/csp/ContentSecurityPolicy.cpp:
(WebCore::ContentSecurityPolicy::copyStateFrom):
(WebCore::ContentSecurityPolicy::didReceiveHeaders):
* page/csp/ContentSecurityPolicy.h:
(WebCore::ContentSecurityPolicy::sandboxFlags const):

Modified Paths

Diff

Modified: releases/WebKitGTK/webkit-2.34/LayoutTests/imported/w3c/ChangeLog (287208 => 287209)


--- releases/WebKitGTK/webkit-2.34/LayoutTests/imported/w3c/ChangeLog	2021-12-17 22:41:39 UTC (rev 287208)
+++ releases/WebKitGTK/webkit-2.34/LayoutTests/imported/w3c/ChangeLog	2021-12-17 22:48:02 UTC (rev 287209)
@@ -1,3 +1,14 @@
+2021-09-02  Chris Dumez  <[email protected]>
+
+        [COOP] html/cross-origin-opener-policy/coop-navigate-same-origin-csp-sandbox.html WPT test is failing
+        https://bugs.webkit.org/show_bug.cgi?id=229716
+
+        Reviewed by Darin Adler.
+
+        Rebaseline WPT test that is now passing.
+
+        * web-platform-tests/html/cross-origin-opener-policy/coop-navigate-same-origin-csp-sandbox-expected.txt:
+
 2021-10-01  Yusuke Suzuki  <[email protected]>
 
         Disable new incumbent-window until it is fully implemented

Modified: releases/WebKitGTK/webkit-2.34/LayoutTests/imported/w3c/web-platform-tests/html/cross-origin-opener-policy/coop-navigate-same-origin-csp-sandbox-expected.txt (287208 => 287209)


--- releases/WebKitGTK/webkit-2.34/LayoutTests/imported/w3c/web-platform-tests/html/cross-origin-opener-policy/coop-navigate-same-origin-csp-sandbox-expected.txt	2021-12-17 22:41:39 UTC (rev 287208)
+++ releases/WebKitGTK/webkit-2.34/LayoutTests/imported/w3c/web-platform-tests/html/cross-origin-opener-policy/coop-navigate-same-origin-csp-sandbox-expected.txt	2021-12-17 22:48:02 UTC (rev 287209)
@@ -1,3 +1,3 @@
 
-FAIL coop-navigate-same-origin-csp-sandbox assert_equals: expected "Success: no opener" but got "Error: have opener"
+PASS coop-navigate-same-origin-csp-sandbox
 

Modified: releases/WebKitGTK/webkit-2.34/Source/WebCore/ChangeLog (287208 => 287209)


--- releases/WebKitGTK/webkit-2.34/Source/WebCore/ChangeLog	2021-12-17 22:41:39 UTC (rev 287208)
+++ releases/WebKitGTK/webkit-2.34/Source/WebCore/ChangeLog	2021-12-17 22:48:02 UTC (rev 287209)
@@ -1,3 +1,31 @@
+2021-09-02  Chris Dumez  <[email protected]>
+
+        [COOP] html/cross-origin-opener-policy/coop-navigate-same-origin-csp-sandbox.html WPT test is failing
+        https://bugs.webkit.org/show_bug.cgi?id=229716
+
+        Reviewed by Darin Adler.
+
+        The COOP algorithm is relying on the response origin for some of the checks. We were computing the
+        response origin via `SecurityOrigin::create(response.url())`, which worked fine in most cases.
+        However, the response may contain a CSP header, which could set sandbox flags. If sandbox flags
+        are set, the response origin should be unique, not the origin of the response URL. This patch fixes
+        that.
+
+        No new tests, rebaselined existing WPT test.
+
+        * loader/DocumentLoader.cpp:
+        (WebCore::computeResponseOriginAndCOOP):
+        (WebCore::DocumentLoader::doCrossOriginOpenerHandlingOfResponse):
+        * loader/DocumentLoader.h:
+        (WebCore::DocumentLoader::contentSecurityPolicy const):
+        * loader/FrameLoader.cpp:
+        (WebCore::FrameLoader::didBeginDocument):
+        * page/csp/ContentSecurityPolicy.cpp:
+        (WebCore::ContentSecurityPolicy::copyStateFrom):
+        (WebCore::ContentSecurityPolicy::didReceiveHeaders):
+        * page/csp/ContentSecurityPolicy.h:
+        (WebCore::ContentSecurityPolicy::sandboxFlags const):
+
 2021-10-02  Yusuke Suzuki  <[email protected]>
 
         Remove JSC hack after r283410

Modified: releases/WebKitGTK/webkit-2.34/Source/WebCore/loader/DocumentLoader.cpp (287208 => 287209)


--- releases/WebKitGTK/webkit-2.34/Source/WebCore/loader/DocumentLoader.cpp	2021-12-17 22:41:39 UTC (rev 287208)
+++ releases/WebKitGTK/webkit-2.34/Source/WebCore/loader/DocumentLoader.cpp	2021-12-17 22:48:02 UTC (rev 287209)
@@ -758,7 +758,7 @@
     return true;
 }
 
-static std::tuple<Ref<SecurityOrigin>, CrossOriginOpenerPolicy> computeResponseOriginAndCOOP(const ResourceResponse& response, const Document& document, const std::optional<NavigationAction::Requester>& requester)
+static std::tuple<Ref<SecurityOrigin>, CrossOriginOpenerPolicy> computeResponseOriginAndCOOP(const ResourceResponse& response, const Document& document, const std::optional<NavigationAction::Requester>& requester, ContentSecurityPolicy* responseCSP)
 {
     // Non-initial empty documents (about:blank) should inherit their cross-origin-opener-policy from the navigation's initiator top level document,
     // if the initiator and its top level document are same-origin, or default (unsafe-none) otherwise.
@@ -766,7 +766,9 @@
     if (SecurityPolicy::shouldInheritSecurityOriginFromOwner(response.url()) && requester)
         return std::make_tuple(makeRef(requester->securityOrigin()), requester->securityOrigin().isSameOriginAs(requester->topOrigin()) ? requester->crossOriginOpenerPolicy() : CrossOriginOpenerPolicy { });
 
-    return std::make_tuple(SecurityOrigin::create(response.url()), obtainCrossOriginOpenerPolicy(response, document));
+    // If the HTTP response contains a CSP header, it may set sandbox flags, which would cause the origin to become unique.
+    auto responseOrigin = responseCSP && responseCSP->sandboxFlags() != SandboxNone ? SecurityOrigin::createUnique() : SecurityOrigin::create(response.url());
+    return std::make_tuple(WTFMove(responseOrigin), obtainCrossOriginOpenerPolicy(response, document));
 }
 
 // https://html.spec.whatwg.org/multipage/browsing-the-web.html#process-a-navigate-fetch (Step 12.5.6)
@@ -779,8 +781,14 @@
     if (!m_frame->document() || !m_frame->document()->settings().crossOriginOpenerPolicyEnabled())
         return true;
 
-    auto [responseOrigin, responseCOOP] = computeResponseOriginAndCOOP(response, *m_frame->document(), m_triggeringAction.requester());
+    if (!response.httpHeaderField(HTTPHeaderName::ContentSecurityPolicy).isNull()) {
+        m_contentSecurityPolicy = makeUnique<ContentSecurityPolicy>(URL { response.url() }, nullptr);
+        m_contentSecurityPolicy->didReceiveHeaders(ContentSecurityPolicyResponseHeaders { response }, m_request.httpReferrer(), ContentSecurityPolicy::ReportParsingErrors::No);
+    } else
+        m_contentSecurityPolicy = nullptr;
 
+    auto [responseOrigin, responseCOOP] = computeResponseOriginAndCOOP(response, *m_frame->document(), m_triggeringAction.requester(), m_contentSecurityPolicy.get());
+
     // https://html.spec.whatwg.org/multipage/browsing-the-web.html#process-a-navigate-fetch (Step 12.5.6.2)
     // If sandboxFlags is not empty and responseCOOP's value is not "unsafe-none", then set response to an appropriate network error and break.
     if (responseCOOP.value != CrossOriginOpenerPolicyValue::UnsafeNone && frameLoader()->effectiveSandboxFlags() != SandboxNone) {

Modified: releases/WebKitGTK/webkit-2.34/Source/WebCore/loader/DocumentLoader.h (287208 => 287209)


--- releases/WebKitGTK/webkit-2.34/Source/WebCore/loader/DocumentLoader.h	2021-12-17 22:41:39 UTC (rev 287208)
+++ releases/WebKitGTK/webkit-2.34/Source/WebCore/loader/DocumentLoader.h	2021-12-17 22:48:02 UTC (rev 287209)
@@ -423,6 +423,7 @@
     bool lastNavigationWasAppInitiated() const { return m_lastNavigationWasAppInitiated; }
     void setLastNavigationWasAppInitiated(bool lastNavigationWasAppInitiated) { m_lastNavigationWasAppInitiated = lastNavigationWasAppInitiated; }
 
+    ContentSecurityPolicy* contentSecurityPolicy() const { return m_contentSecurityPolicy.get(); }
     std::optional<CrossOriginOpenerPolicy> crossOriginOpenerPolicy() const { return m_currentCoopEnforcementResult ? std::make_optional(m_currentCoopEnforcementResult->crossOriginOpenerPolicy) : std::nullopt; }
 
     bool isContinuingLoadAfterResponsePolicyCheck() const { return m_isContinuingLoadAfterResponsePolicyCheck; }
@@ -628,6 +629,7 @@
     ShouldOpenExternalURLsPolicy m_shouldOpenExternalURLsPolicy { ShouldOpenExternalURLsPolicy::ShouldNotAllow };
 
     std::unique_ptr<ApplicationCacheHost> m_applicationCacheHost;
+    std::unique_ptr<ContentSecurityPolicy> m_contentSecurityPolicy;
 
 #if ENABLE(CONTENT_FILTERING)
     std::unique_ptr<ContentFilter> m_contentFilter;

Modified: releases/WebKitGTK/webkit-2.34/Source/WebCore/loader/FrameLoader.cpp (287208 => 287209)


--- releases/WebKitGTK/webkit-2.34/Source/WebCore/loader/FrameLoader.cpp	2021-12-17 22:41:39 UTC (rev 287208)
+++ releases/WebKitGTK/webkit-2.34/Source/WebCore/loader/FrameLoader.cpp	2021-12-17 22:48:02 UTC (rev 287209)
@@ -749,7 +749,11 @@
         if (!dnsPrefetchControl.isEmpty())
             m_frame.document()->parseDNSPrefetchControlHeader(dnsPrefetchControl);
 
-        m_frame.document()->contentSecurityPolicy()->didReceiveHeaders(ContentSecurityPolicyResponseHeaders(m_documentLoader->response()), referrer(), ContentSecurityPolicy::ReportParsingErrors::No);
+        // The DocumentLoader may have already parsed the CSP header to do some checks. If so, reuse the already parsed version instead of parsing again.
+        if (auto* contentSecurityPolicy = m_documentLoader->contentSecurityPolicy())
+            m_frame.document()->contentSecurityPolicy()->didReceiveHeaders(*contentSecurityPolicy, ContentSecurityPolicy::ReportParsingErrors::No);
+        else
+            m_frame.document()->contentSecurityPolicy()->didReceiveHeaders(ContentSecurityPolicyResponseHeaders(m_documentLoader->response()), referrer(), ContentSecurityPolicy::ReportParsingErrors::No);
 
         if (m_frame.document()->url().protocolIsInHTTPFamily() || m_frame.document()->url().protocolIsBlob())
             m_frame.document()->setCrossOriginEmbedderPolicy(obtainCrossOriginEmbedderPolicy(m_documentLoader->response(), *m_frame.document()));

Modified: releases/WebKitGTK/webkit-2.34/Source/WebCore/page/csp/ContentSecurityPolicy.cpp (287208 => 287209)


--- releases/WebKitGTK/webkit-2.34/Source/WebCore/page/csp/ContentSecurityPolicy.cpp	2021-12-17 22:41:39 UTC (rev 287208)
+++ releases/WebKitGTK/webkit-2.34/Source/WebCore/page/csp/ContentSecurityPolicy.cpp	2021-12-17 22:48:02 UTC (rev 287209)
@@ -173,6 +173,17 @@
     m_httpStatusCode = headers.m_httpStatusCode;
 }
 
+void ContentSecurityPolicy::didReceiveHeaders(const ContentSecurityPolicy& other, ReportParsingErrors reportParsingErrors)
+{
+    SetForScope<bool> isReportingEnabled(m_isReportingEnabled, reportParsingErrors == ReportParsingErrors::Yes);
+    for (auto& policy : other.m_policies)
+        didReceiveHeader(policy->header(), policy->headerType(), ContentSecurityPolicy::PolicyFrom::HTTPHeader, String { });
+    m_referrer = other.m_referrer;
+    m_httpStatusCode = other.m_httpStatusCode;
+    m_upgradeInsecureRequests = other.m_upgradeInsecureRequests;
+    m_insecureNavigationRequestsToUpgrade.add(other.m_insecureNavigationRequestsToUpgrade.begin(), other.m_insecureNavigationRequestsToUpgrade.end());
+}
+
 void ContentSecurityPolicy::didReceiveHeader(const String& header, ContentSecurityPolicyHeaderType type, ContentSecurityPolicy::PolicyFrom policyFrom, String&& referrer, int httpStatusCode)
 {
     if (m_hasAPIPolicy)

Modified: releases/WebKitGTK/webkit-2.34/Source/WebCore/page/csp/ContentSecurityPolicy.h (287208 => 287209)


--- releases/WebKitGTK/webkit-2.34/Source/WebCore/page/csp/ContentSecurityPolicy.h	2021-12-17 22:41:39 UTC (rev 287208)
+++ releases/WebKitGTK/webkit-2.34/Source/WebCore/page/csp/ContentSecurityPolicy.h	2021-12-17 22:48:02 UTC (rev 287209)
@@ -84,6 +84,7 @@
     WEBCORE_EXPORT ContentSecurityPolicyResponseHeaders responseHeaders() const;
     enum ReportParsingErrors { No, Yes };
     WEBCORE_EXPORT void didReceiveHeaders(const ContentSecurityPolicyResponseHeaders&, String&& referrer, ReportParsingErrors = ReportParsingErrors::Yes);
+    void didReceiveHeaders(const ContentSecurityPolicy&, ReportParsingErrors = ReportParsingErrors::Yes);
     void didReceiveHeader(const String&, ContentSecurityPolicyHeaderType, ContentSecurityPolicy::PolicyFrom, String&& referrer, int httpStatusCode = 0);
 
     bool allowScriptWithNonce(const String& nonce, bool overrideContentSecurityPolicy = false) const;
@@ -177,6 +178,8 @@
 
     void setDocumentURL(URL& documentURL) { m_documentURL = documentURL; }
 
+    SandboxFlags sandboxFlags() const { return m_sandboxFlags; }
+
 private:
     void logToConsole(const String& message, const String& contextURL = String(), const WTF::OrdinalNumber& contextLine = WTF::OrdinalNumber::beforeFirst(), const WTF::OrdinalNumber& contextColumn = WTF::OrdinalNumber::beforeFirst(), JSC::JSGlobalObject* = nullptr) const;
     void applyPolicyToScriptExecutionContext();
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to