Title: [231464] trunk
Revision
231464
Author
[email protected]
Date
2018-05-07 16:37:46 -0700 (Mon, 07 May 2018)

Log Message

CSP status-code incorrect for document blocked due to violation of its frame-ancestors directive
https://bugs.webkit.org/show_bug.cgi?id=185366
<rdar://problem/40035116>

Reviewed by Brent Fulgham.

Source/WebCore:

Fixes an issue where the status-code in the sent CSP report for an HTTP document blocked because
its frame-ancestors directive was violated would be the status code of the previously loaded
document in the frame. If the previously loaded document was about:blank then this would be 0.

Currently whenever we send a CSP report we ask the document's loader (Document::loader()) for the
HTTP status code for the last response. Document::loader() returns the loader for the last committed
document its frame. For a frame-ancestors violation, a CSP report is sent before the document
that had the frame-ancestors directive has been committed and after it has been associate with a frame.
As a result we are in are in a transient transition state for the frame and hence the last response
for new document's loader (Document::loader()) is actually the last response of the previously loaded
document in the frame. Instead we need to take care to tell CSP about the HTTP status code for the
response associated with the document the CSP came from.

* dom/Document.cpp:
(WebCore::Document::processHttpEquiv):
(WebCore::Document::initSecurityContext):
Pass the HTTP status code to CSP.

* page/csp/ContentSecurityPolicy.cpp:
(WebCore::ContentSecurityPolicy::copyStateFrom):
(WebCore::ContentSecurityPolicy::responseHeaders const):
(WebCore::ContentSecurityPolicy::didReceiveHeaders):
(WebCore::ContentSecurityPolicy::didReceiveHeader):
(WebCore::ContentSecurityPolicy::reportViolation const):
* page/csp/ContentSecurityPolicy.h:
Modify existing functions to take the HTTP status code, store it in a instance variable,
and reference this variable when reporting a violation.

* page/csp/ContentSecurityPolicyResponseHeaders.cpp:
(WebCore::ContentSecurityPolicyResponseHeaders::ContentSecurityPolicyResponseHeaders):
(WebCore::ContentSecurityPolicyResponseHeaders::isolatedCopy const):
* page/csp/ContentSecurityPolicyResponseHeaders.h:
(WebCore::ContentSecurityPolicyResponseHeaders::encode const):
(WebCore::ContentSecurityPolicyResponseHeaders::decode):
Store the HTTP status code along with the response headers.

LayoutTests:

Update existing test results now that we send the HTTP status code for the correct document.

* http/tests/security/contentSecurityPolicy/1.1/frame-ancestors/report-frame-ancestors-cross-origin-expected.txt:
* http/tests/security/contentSecurityPolicy/1.1/frame-ancestors/report-frame-ancestors-same-origin-expected.txt:

Modified Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (231463 => 231464)


--- trunk/LayoutTests/ChangeLog	2018-05-07 23:32:28 UTC (rev 231463)
+++ trunk/LayoutTests/ChangeLog	2018-05-07 23:37:46 UTC (rev 231464)
@@ -1,3 +1,16 @@
+2018-05-07  Daniel Bates  <[email protected]>
+
+        CSP status-code incorrect for document blocked due to violation of its frame-ancestors directive
+        https://bugs.webkit.org/show_bug.cgi?id=185366
+        <rdar://problem/40035116>
+
+        Reviewed by Brent Fulgham.
+
+        Update existing test results now that we send the HTTP status code for the correct document.
+
+        * http/tests/security/contentSecurityPolicy/1.1/frame-ancestors/report-frame-ancestors-cross-origin-expected.txt:
+        * http/tests/security/contentSecurityPolicy/1.1/frame-ancestors/report-frame-ancestors-same-origin-expected.txt:
+
 2018-05-07  Ryan Haddad  <[email protected]>
 
         Update TestExpectations for inspector/sampling-profiler/named-function-_expression_.html.

Modified: trunk/LayoutTests/http/tests/security/contentSecurityPolicy/1.1/frame-ancestors/report-frame-ancestors-cross-origin-expected.txt (231463 => 231464)


--- trunk/LayoutTests/http/tests/security/contentSecurityPolicy/1.1/frame-ancestors/report-frame-ancestors-cross-origin-expected.txt	2018-05-07 23:32:28 UTC (rev 231463)
+++ trunk/LayoutTests/http/tests/security/contentSecurityPolicy/1.1/frame-ancestors/report-frame-ancestors-cross-origin-expected.txt	2018-05-07 23:37:46 UTC (rev 231464)
@@ -5,4 +5,4 @@
 REQUEST_METHOD: POST
 REQUEST_URI: /security/contentSecurityPolicy/resources/save-report.php?test=/security/contentSecurityPolicy/1.1/report-frame-ancestors-cross-origin.html
 === POST DATA =""
-{"csp-report":{"document-uri":"http://localhost:8000/security/contentSecurityPolicy/resources/echo-intertag.pl?header=Content-Security-Policy%3A+frame-ancestors+%27none%27%3B+report-uri+save-report.php%3Ftest%3D/security/contentSecurityPolicy/1.1/report-frame-ancestors-cross-origin.html&q=FAIL","referrer":"http://127.0.0.1:8000/security/contentSecurityPolicy/1.1/frame-ancestors/report-frame-ancestors-cross-origin.html","violated-directive":"frame-ancestors 'none'","effective-directive":"frame-ancestors","original-policy":"frame-ancestors 'none'; report-uri save-report.php?test=/security/contentSecurityPolicy/1.1/report-frame-ancestors-cross-origin.html","blocked-uri":"http://localhost:8000/security/contentSecurityPolicy/resources/echo-intertag.pl?header=Content-Security-Policy%3A+frame-ancestors+%27none%27%3B+report-uri+save-report.php%3Ftest%3
 D/security/contentSecurityPolicy/1.1/report-frame-ancestors-cross-origin.html&q=FAIL","status-code":0}}
+{"csp-report":{"document-uri":"http://localhost:8000/security/contentSecurityPolicy/resources/echo-intertag.pl?header=Content-Security-Policy%3A+frame-ancestors+%27none%27%3B+report-uri+save-report.php%3Ftest%3D/security/contentSecurityPolicy/1.1/report-frame-ancestors-cross-origin.html&q=FAIL","referrer":"http://127.0.0.1:8000/security/contentSecurityPolicy/1.1/frame-ancestors/report-frame-ancestors-cross-origin.html","violated-directive":"frame-ancestors 'none'","effective-directive":"frame-ancestors","original-policy":"frame-ancestors 'none'; report-uri save-report.php?test=/security/contentSecurityPolicy/1.1/report-frame-ancestors-cross-origin.html","blocked-uri":"http://localhost:8000/security/contentSecurityPolicy/resources/echo-intertag.pl?header=Content-Security-Policy%3A+frame-ancestors+%27none%27%3B+report-uri+save-report.php%3Ftest%3D
 /security/contentSecurityPolicy/1.1/report-frame-ancestors-cross-origin.html&q=FAIL","status-code":200}}

Modified: trunk/LayoutTests/http/tests/security/contentSecurityPolicy/1.1/frame-ancestors/report-frame-ancestors-same-origin-expected.txt (231463 => 231464)


--- trunk/LayoutTests/http/tests/security/contentSecurityPolicy/1.1/frame-ancestors/report-frame-ancestors-same-origin-expected.txt	2018-05-07 23:32:28 UTC (rev 231463)
+++ trunk/LayoutTests/http/tests/security/contentSecurityPolicy/1.1/frame-ancestors/report-frame-ancestors-same-origin-expected.txt	2018-05-07 23:37:46 UTC (rev 231464)
@@ -5,4 +5,4 @@
 REQUEST_METHOD: POST
 REQUEST_URI: /security/contentSecurityPolicy/resources/save-report.php?test=/security/contentSecurityPolicy/1.1/report-frame-ancestors-same-origin.html
 === POST DATA =""
-{"csp-report":{"document-uri":"http://127.0.0.1:8000/security/contentSecurityPolicy/resources/echo-intertag.pl?header=Content-Security-Policy%3A+frame-ancestors+%27none%27%3B+report-uri+save-report.php%3Ftest%3D/security/contentSecurityPolicy/1.1/report-frame-ancestors-same-origin.html&q=FAIL","referrer":"http://127.0.0.1:8000/security/contentSecurityPolicy/1.1/frame-ancestors/report-frame-ancestors-same-origin.html","violated-directive":"frame-ancestors 'none'","effective-directive":"frame-ancestors","original-policy":"frame-ancestors 'none'; report-uri save-report.php?test=/security/contentSecurityPolicy/1.1/report-frame-ancestors-same-origin.html","blocked-uri":"http://127.0.0.1:8000/security/contentSecurityPolicy/resources/echo-intertag.pl?header=Content-Security-Policy%3A+frame-ancestors+%27none%27%3B+report-uri+save-report.php%3Ftest%3D/s
 ecurity/contentSecurityPolicy/1.1/report-frame-ancestors-same-origin.html&q=FAIL","status-code":0}}
+{"csp-report":{"document-uri":"http://127.0.0.1:8000/security/contentSecurityPolicy/resources/echo-intertag.pl?header=Content-Security-Policy%3A+frame-ancestors+%27none%27%3B+report-uri+save-report.php%3Ftest%3D/security/contentSecurityPolicy/1.1/report-frame-ancestors-same-origin.html&q=FAIL","referrer":"http://127.0.0.1:8000/security/contentSecurityPolicy/1.1/frame-ancestors/report-frame-ancestors-same-origin.html","violated-directive":"frame-ancestors 'none'","effective-directive":"frame-ancestors","original-policy":"frame-ancestors 'none'; report-uri save-report.php?test=/security/contentSecurityPolicy/1.1/report-frame-ancestors-same-origin.html","blocked-uri":"http://127.0.0.1:8000/security/contentSecurityPolicy/resources/echo-intertag.pl?header=Content-Security-Policy%3A+frame-ancestors+%27none%27%3B+report-uri+save-report.php%3Ftest%3D/se
 curity/contentSecurityPolicy/1.1/report-frame-ancestors-same-origin.html&q=FAIL","status-code":200}}

Modified: trunk/Source/WebCore/ChangeLog (231463 => 231464)


--- trunk/Source/WebCore/ChangeLog	2018-05-07 23:32:28 UTC (rev 231463)
+++ trunk/Source/WebCore/ChangeLog	2018-05-07 23:37:46 UTC (rev 231464)
@@ -1,5 +1,49 @@
 2018-05-07  Daniel Bates  <[email protected]>
 
+        CSP status-code incorrect for document blocked due to violation of its frame-ancestors directive
+        https://bugs.webkit.org/show_bug.cgi?id=185366
+        <rdar://problem/40035116>
+
+        Reviewed by Brent Fulgham.
+
+        Fixes an issue where the status-code in the sent CSP report for an HTTP document blocked because
+        its frame-ancestors directive was violated would be the status code of the previously loaded
+        document in the frame. If the previously loaded document was about:blank then this would be 0.
+
+        Currently whenever we send a CSP report we ask the document's loader (Document::loader()) for the
+        HTTP status code for the last response. Document::loader() returns the loader for the last committed
+        document its frame. For a frame-ancestors violation, a CSP report is sent before the document
+        that had the frame-ancestors directive has been committed and after it has been associate with a frame.
+        As a result we are in are in a transient transition state for the frame and hence the last response
+        for new document's loader (Document::loader()) is actually the last response of the previously loaded
+        document in the frame. Instead we need to take care to tell CSP about the HTTP status code for the
+        response associated with the document the CSP came from.
+
+        * dom/Document.cpp:
+        (WebCore::Document::processHttpEquiv):
+        (WebCore::Document::initSecurityContext):
+        Pass the HTTP status code to CSP.
+
+        * page/csp/ContentSecurityPolicy.cpp:
+        (WebCore::ContentSecurityPolicy::copyStateFrom):
+        (WebCore::ContentSecurityPolicy::responseHeaders const):
+        (WebCore::ContentSecurityPolicy::didReceiveHeaders):
+        (WebCore::ContentSecurityPolicy::didReceiveHeader):
+        (WebCore::ContentSecurityPolicy::reportViolation const):
+        * page/csp/ContentSecurityPolicy.h:
+        Modify existing functions to take the HTTP status code, store it in a instance variable,
+        and reference this variable when reporting a violation.
+
+        * page/csp/ContentSecurityPolicyResponseHeaders.cpp:
+        (WebCore::ContentSecurityPolicyResponseHeaders::ContentSecurityPolicyResponseHeaders):
+        (WebCore::ContentSecurityPolicyResponseHeaders::isolatedCopy const):
+        * page/csp/ContentSecurityPolicyResponseHeaders.h:
+        (WebCore::ContentSecurityPolicyResponseHeaders::encode const):
+        (WebCore::ContentSecurityPolicyResponseHeaders::decode):
+        Store the HTTP status code along with the response headers.
+
+2018-05-07  Daniel Bates  <[email protected]>
+
         CSP referrer incorrect for document blocked due to violation of its frame-ancestors directive
         https://bugs.webkit.org/show_bug.cgi?id=185380
 

Modified: trunk/Source/WebCore/dom/Document.cpp (231463 => 231464)


--- trunk/Source/WebCore/dom/Document.cpp	2018-05-07 23:32:28 UTC (rev 231463)
+++ trunk/Source/WebCore/dom/Document.cpp	2018-05-07 23:37:46 UTC (rev 231464)
@@ -3317,6 +3317,8 @@
     }
 
     Frame* frame = this->frame();
+    auto* documentLoader = frame ? frame->loader().documentLoader() : nullptr;
+    auto httpStatusCode = documentLoader ? documentLoader->response().httpStatusCode() : 0;
 
     HTTPHeaderName headerName;
     if (!findHTTPHeaderName(equiv, headerName))
@@ -3384,12 +3386,12 @@
 
     case HTTPHeaderName::ContentSecurityPolicy:
         if (isInDocumentHead)
-            contentSecurityPolicy()->didReceiveHeader(content, ContentSecurityPolicyHeaderType::Enforce, ContentSecurityPolicy::PolicyFrom::HTTPEquivMeta, referrer());
+            contentSecurityPolicy()->didReceiveHeader(content, ContentSecurityPolicyHeaderType::Enforce, ContentSecurityPolicy::PolicyFrom::HTTPEquivMeta, referrer(), httpStatusCode);
         break;
 
     case HTTPHeaderName::XWebKitCSP:
         if (isInDocumentHead)
-            contentSecurityPolicy()->didReceiveHeader(content, ContentSecurityPolicyHeaderType::PrefixedEnforce, ContentSecurityPolicy::PolicyFrom::HTTPEquivMeta, referrer());
+            contentSecurityPolicy()->didReceiveHeader(content, ContentSecurityPolicyHeaderType::PrefixedEnforce, ContentSecurityPolicy::PolicyFrom::HTTPEquivMeta, referrer(), httpStatusCode);
         break;
 
     default:
@@ -5511,11 +5513,10 @@
     if (shouldEnforceContentDispositionAttachmentSandbox())
         applyContentDispositionAttachmentSandbox();
 
+    auto* documentLoader = m_frame->loader().documentLoader();
     bool isSecurityOriginUnique = isSandboxed(SandboxOrigin);
-    if (!isSecurityOriginUnique) {
-        auto* loader = m_frame->loader().documentLoader();
-        isSecurityOriginUnique = loader && loader->response().tainting() == ResourceResponse::Tainting::Opaque;
-    }
+    if (!isSecurityOriginUnique)
+        isSecurityOriginUnique = documentLoader && documentLoader->response().tainting() == ResourceResponse::Tainting::Opaque;
 
     setSecurityOriginPolicy(SecurityOriginPolicy::create(isSecurityOriginUnique ? SecurityOrigin::createUnique() : SecurityOrigin::create(m_url)));
     setContentSecurityPolicy(std::make_unique<ContentSecurityPolicy>(*this));
@@ -5522,7 +5523,7 @@
 
     String overrideContentSecurityPolicy = m_frame->loader().client().overrideContentSecurityPolicy();
     if (!overrideContentSecurityPolicy.isNull())
-        contentSecurityPolicy()->didReceiveHeader(overrideContentSecurityPolicy, ContentSecurityPolicyHeaderType::Enforce, ContentSecurityPolicy::PolicyFrom::API, referrer());
+        contentSecurityPolicy()->didReceiveHeader(overrideContentSecurityPolicy, ContentSecurityPolicyHeaderType::Enforce, ContentSecurityPolicy::PolicyFrom::API, referrer(), documentLoader ? documentLoader->response().httpStatusCode() : 0);
 
 #if USE(QUICK_LOOK)
     if (shouldEnforceQuickLookSandbox())

Modified: trunk/Source/WebCore/page/csp/ContentSecurityPolicy.cpp (231463 => 231464)


--- trunk/Source/WebCore/page/csp/ContentSecurityPolicy.cpp	2018-05-07 23:32:28 UTC (rev 231463)
+++ trunk/Source/WebCore/page/csp/ContentSecurityPolicy.cpp	2018-05-07 23:37:46 UTC (rev 231464)
@@ -113,6 +113,7 @@
     for (auto& policy : other->m_policies)
         didReceiveHeader(policy->header(), policy->headerType(), ContentSecurityPolicy::PolicyFrom::Inherited, String { });
     m_referrer = other->m_referrer;
+    m_httpStatusCode = other->m_httpStatusCode;
 }
 
 void ContentSecurityPolicy::copyUpgradeInsecureRequestStateFrom(const ContentSecurityPolicy& other)
@@ -167,6 +168,7 @@
         result.m_headers.reserveInitialCapacity(m_policies.size());
         for (auto& policy : m_policies)
             result.m_headers.uncheckedAppend({ policy->header(), policy->headerType() });
+        result.m_httpStatusCode = m_httpStatusCode;
         m_cachedResponseHeaders = WTFMove(result);
     }
     return *m_cachedResponseHeaders;
@@ -178,14 +180,16 @@
     for (auto& header : headers.m_headers)
         didReceiveHeader(header.first, header.second, ContentSecurityPolicy::PolicyFrom::HTTPHeader, String { });
     m_referrer = WTFMove(referrer);
+    m_httpStatusCode = headers.m_httpStatusCode;
 }
 
-void ContentSecurityPolicy::didReceiveHeader(const String& header, ContentSecurityPolicyHeaderType type, ContentSecurityPolicy::PolicyFrom policyFrom, String&& referrer)
+void ContentSecurityPolicy::didReceiveHeader(const String& header, ContentSecurityPolicyHeaderType type, ContentSecurityPolicy::PolicyFrom policyFrom, String&& referrer, int httpStatusCode)
 {
     if (m_hasAPIPolicy)
         return;
 
     m_referrer = WTFMove(referrer);
+    m_httpStatusCode = httpStatusCode;
 
     if (policyFrom == PolicyFrom::API) {
         ASSERT(m_policies.isEmpty());
@@ -668,9 +672,8 @@
     }
     String violatedDirectiveText = violatedDirective;
     String originalPolicy = violatedDirectiveList.header();
-    ASSERT(document.loader());
     // FIXME: Is it policy to not use the status code for HTTPS, or is that a bug?
-    unsigned short statusCode = document.url().protocolIs("http") && document.loader() ? document.loader()->response().httpStatusCode() : 0;
+    unsigned short statusCode = m_selfSourceProtocol == "http" ? m_httpStatusCode : 0;
 
     String sourceFile;
     int lineNumber = 0;

Modified: trunk/Source/WebCore/page/csp/ContentSecurityPolicy.h (231463 => 231464)


--- trunk/Source/WebCore/page/csp/ContentSecurityPolicy.h	2018-05-07 23:32:28 UTC (rev 231463)
+++ trunk/Source/WebCore/page/csp/ContentSecurityPolicy.h	2018-05-07 23:37:46 UTC (rev 231464)
@@ -82,7 +82,7 @@
     WEBCORE_EXPORT ContentSecurityPolicyResponseHeaders responseHeaders() const;
     enum ReportParsingErrors { No, Yes };
     WEBCORE_EXPORT void didReceiveHeaders(const ContentSecurityPolicyResponseHeaders&, String&& referrer, ReportParsingErrors = ReportParsingErrors::Yes);
-    void didReceiveHeader(const String&, ContentSecurityPolicyHeaderType, ContentSecurityPolicy::PolicyFrom, String&& referrer);
+    void didReceiveHeader(const String&, ContentSecurityPolicyHeaderType, ContentSecurityPolicy::PolicyFrom, String&& referrer, int httpStatusCode = 0);
 
     bool allowScriptWithNonce(const String& nonce, bool overrideContentSecurityPolicy = false) const;
     bool allowStyleWithNonce(const String& nonce, bool overrideContentSecurityPolicy = false) const;
@@ -217,6 +217,7 @@
     bool m_isReportingEnabled { true };
     bool m_upgradeInsecureRequests { false };
     bool m_hasAPIPolicy { false };
+    int m_httpStatusCode { 0 };
     OptionSet<ContentSecurityPolicyHashAlgorithm> m_hashAlgorithmsForInlineScripts;
     OptionSet<ContentSecurityPolicyHashAlgorithm> m_hashAlgorithmsForInlineStylesheets;
     HashSet<SecurityOriginData> m_insecureNavigationRequestsToUpgrade;

Modified: trunk/Source/WebCore/page/csp/ContentSecurityPolicyResponseHeaders.cpp (231463 => 231464)


--- trunk/Source/WebCore/page/csp/ContentSecurityPolicyResponseHeaders.cpp	2018-05-07 23:32:28 UTC (rev 231463)
+++ trunk/Source/WebCore/page/csp/ContentSecurityPolicyResponseHeaders.cpp	2018-05-07 23:37:46 UTC (rev 231464)
@@ -48,6 +48,8 @@
     policyValue = response.httpHeaderField(HTTPHeaderName::XWebKitCSPReportOnly);
     if (!policyValue.isEmpty())
         m_headers.append({ policyValue, ContentSecurityPolicyHeaderType::PrefixedReport });
+
+    m_httpStatusCode = response.httpStatusCode();
 }
 
 ContentSecurityPolicyResponseHeaders ContentSecurityPolicyResponseHeaders::isolatedCopy() const
@@ -56,6 +58,7 @@
     isolatedCopy.m_headers.reserveInitialCapacity(m_headers.size());
     for (auto& header : m_headers)
         isolatedCopy.m_headers.uncheckedAppend({ header.first.isolatedCopy(), header.second });
+    isolatedCopy.m_httpStatusCode = m_httpStatusCode;
     return isolatedCopy;
 }
 

Modified: trunk/Source/WebCore/page/csp/ContentSecurityPolicyResponseHeaders.h (231463 => 231464)


--- trunk/Source/WebCore/page/csp/ContentSecurityPolicyResponseHeaders.h	2018-05-07 23:32:28 UTC (rev 231463)
+++ trunk/Source/WebCore/page/csp/ContentSecurityPolicyResponseHeaders.h	2018-05-07 23:37:46 UTC (rev 231464)
@@ -54,6 +54,7 @@
     friend class ContentSecurityPolicy;
 
     Vector<std::pair<String, ContentSecurityPolicyHeaderType>> m_headers;
+    int m_httpStatusCode { 0 };
 };
 
 template <class Encoder>
@@ -64,6 +65,7 @@
         encoder << pair.first;
         encoder.encodeEnum(pair.second);
     }
+    encoder << m_httpStatusCode;
 }
 
 template <class Decoder>
@@ -83,6 +85,9 @@
         headers.m_headers.append(std::make_pair(header, headerType));
     }
 
+    if (!decoder.decode(headers.m_httpStatusCode))
+        return false;
+
     return true;
 }
 
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to