[XHR] Only exempt Dashboard widgets from XHR header restrictions
authordbates@webkit.org <dbates@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 3 Oct 2017 18:54:30 +0000 (18:54 +0000)
committerdbates@webkit.org <dbates@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 3 Oct 2017 18:54:30 +0000 (18:54 +0000)
https://bugs.webkit.org/show_bug.cgi?id=177824
<rdar://problem/34384301>

Reviewed by Alexey Proskuryakov.

Source/WebCore:

Currently we allow file URLs to set arbitrary XHR headers. In contrast, non-file URLs are
restricted from setting some XHR headers (e.g. COOKIE). Historically the relaxation for file
URL was for backwards compatibility to allow Dashboard widgets to work. Instead we should
apply the non-file URL policy to all URLs and only relax the policy for Dashboard widgets.

Tests: fast/xmlhttprequest/set-dangerous-headers-in-dashboard.html
       fast/xmlhttprequest/set-dangerous-headers.html

* xml/XMLHttpRequest.cpp:
(WebCore::XMLHttpRequest::setRequestHeader):

LayoutTests:

Add tests to ensure that file URLs are forbidden from setting the same set of blacklisted
headers as non-file URLs except when running in Dashboard compatibility mode.

* TestExpectations: Mark test fast/xmlhttprequest/set-dangerous-headers-in-dashboard.html
as WontFix on all platforms. We will selectively enable this test on Mac because it is the
only platform that supports Dashboard widgets.
* fast/xmlhttprequest/set-dangerous-headers-expected.txt: Added.
* fast/xmlhttprequest/set-dangerous-headers-in-dashboard-expected.txt: Added.
* fast/xmlhttprequest/set-dangerous-headers-in-dashboard.html: Added.
* fast/xmlhttprequest/set-dangerous-headers.html: Added. Derived from LayoutTests/http/tests/xmlhttprequest/set-dangerous-headers.html.
* platform/mac/TestExpectations: Enable test fast/xmlhttprequest/set-dangerous-headers-in-dashboard.html
on Mac.

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@222795 268f45cc-cd09-0410-ab3c-d52691b4dbfc

LayoutTests/ChangeLog
LayoutTests/TestExpectations
LayoutTests/fast/xmlhttprequest/set-dangerous-headers-expected.txt [new file with mode: 0644]
LayoutTests/fast/xmlhttprequest/set-dangerous-headers-in-dashboard-expected.txt [new file with mode: 0644]
LayoutTests/fast/xmlhttprequest/set-dangerous-headers-in-dashboard.html [new file with mode: 0644]
LayoutTests/fast/xmlhttprequest/set-dangerous-headers.html [new file with mode: 0644]
LayoutTests/platform/mac/TestExpectations
Source/WebCore/ChangeLog
Source/WebCore/xml/XMLHttpRequest.cpp

index 0773aab..43cbae5 100644 (file)
@@ -1,3 +1,24 @@
+2017-10-03  Daniel Bates  <dabates@apple.com>
+
+        [XHR] Only exempt Dashboard widgets from XHR header restrictions
+        https://bugs.webkit.org/show_bug.cgi?id=177824
+        <rdar://problem/34384301>
+
+        Reviewed by Alexey Proskuryakov.
+
+        Add tests to ensure that file URLs are forbidden from setting the same set of blacklisted
+        headers as non-file URLs except when running in Dashboard compatibility mode.
+
+        * TestExpectations: Mark test fast/xmlhttprequest/set-dangerous-headers-in-dashboard.html
+        as WontFix on all platforms. We will selectively enable this test on Mac because it is the
+        only platform that supports Dashboard widgets.
+        * fast/xmlhttprequest/set-dangerous-headers-expected.txt: Added.
+        * fast/xmlhttprequest/set-dangerous-headers-in-dashboard-expected.txt: Added.
+        * fast/xmlhttprequest/set-dangerous-headers-in-dashboard.html: Added.
+        * fast/xmlhttprequest/set-dangerous-headers.html: Added. Derived from LayoutTests/http/tests/xmlhttprequest/set-dangerous-headers.html.
+        * platform/mac/TestExpectations: Enable test fast/xmlhttprequest/set-dangerous-headers-in-dashboard.html
+        on Mac.
+
 2017-10-03  Fujii Hironori  <Hironori.Fujii@sony.com>
 
         REGRESSION(r221909): Failing fast/text/international/iso-8859-8.html
index d148428..755a0b9 100644 (file)
@@ -51,6 +51,9 @@ fast/forms/search/search-results-hidden-crash.html [ Skip ]
 # This doesn't have to be platform-specific, but it's only implemented on Mac now.
 fast/url/user-visible [ Skip ]
 
+# Only Mac supports Dashboard widgets.
+fast/xmlhttprequest/set-dangerous-headers-in-dashboard.html [ WontFix ]
+
 # Only Mac supports force tests.
 fast/events/cancelled-force-click-link-navigation.html [ Skip ]
 fast/events/force-click-link-selection-behavior.html [ Skip ]
diff --git a/LayoutTests/fast/xmlhttprequest/set-dangerous-headers-expected.txt b/LayoutTests/fast/xmlhttprequest/set-dangerous-headers-expected.txt
new file mode 100644 (file)
index 0000000..7ae3f42
--- /dev/null
@@ -0,0 +1,29 @@
+CONSOLE MESSAGE: line 12: Refused to set unsafe header "ACCEPT-CHARSET"
+CONSOLE MESSAGE: line 13: Refused to set unsafe header "ACCEPT-ENCODING"
+CONSOLE MESSAGE: line 14: Refused to set unsafe header "ACCESS-CONTROL-REQUEST-HEADERS"
+CONSOLE MESSAGE: line 15: Refused to set unsafe header "ACCESS-CONTROL-REQUEST-METHOD"
+CONSOLE MESSAGE: line 21: Refused to set unsafe header "CONNECTION"
+CONSOLE MESSAGE: line 22: Refused to set unsafe header "CONTENT-LENGTH"
+CONSOLE MESSAGE: line 23: Refused to set unsafe header "CONTENT-TRANSFER-ENCODING"
+CONSOLE MESSAGE: line 24: Refused to set unsafe header "COOKIE"
+CONSOLE MESSAGE: line 25: Refused to set unsafe header "COOKIE2"
+CONSOLE MESSAGE: line 26: Refused to set unsafe header "DATE"
+CONSOLE MESSAGE: line 27: Refused to set unsafe header "DNT"
+CONSOLE MESSAGE: line 28: Refused to set unsafe header "EXPECT"
+CONSOLE MESSAGE: line 29: Refused to set unsafe header "HOST"
+CONSOLE MESSAGE: line 30: Refused to set unsafe header "KEEP-ALIVE"
+CONSOLE MESSAGE: line 31: Refused to set unsafe header "ORIGIN"
+CONSOLE MESSAGE: line 32: Refused to set unsafe header "REFERER"
+CONSOLE MESSAGE: line 33: Refused to set unsafe header "TE"
+CONSOLE MESSAGE: line 34: Refused to set unsafe header "TRAILER"
+CONSOLE MESSAGE: line 35: Refused to set unsafe header "TRANSFER-ENCODING"
+CONSOLE MESSAGE: line 36: Refused to set unsafe header "UPGRADE"
+CONSOLE MESSAGE: line 37: Refused to set unsafe header "USER-AGENT"
+CONSOLE MESSAGE: line 38: Refused to set unsafe header "VIA"
+CONSOLE MESSAGE: line 40: Refused to set unsafe header "Proxy-"
+CONSOLE MESSAGE: line 41: Refused to set unsafe header "Proxy-test"
+CONSOLE MESSAGE: line 42: Refused to set unsafe header "PROXY-FOO"
+CONSOLE MESSAGE: line 44: Refused to set unsafe header "Sec-"
+CONSOLE MESSAGE: line 45: Refused to set unsafe header "Sec-test"
+CONSOLE MESSAGE: line 46: Refused to set unsafe header "SEC-FOO"
+Test that setRequestHeader() cannot be used to alter security-sensitive headers. This test PASSED if you see console warnings.
diff --git a/LayoutTests/fast/xmlhttprequest/set-dangerous-headers-in-dashboard-expected.txt b/LayoutTests/fast/xmlhttprequest/set-dangerous-headers-in-dashboard-expected.txt
new file mode 100644 (file)
index 0000000..bb842fc
--- /dev/null
@@ -0,0 +1 @@
+Test that setRequestHeader() can be used to alter security-sensitive headers in Dashboard compatibility mode. This test PASSED if you do not see any console warnings.
diff --git a/LayoutTests/fast/xmlhttprequest/set-dangerous-headers-in-dashboard.html b/LayoutTests/fast/xmlhttprequest/set-dangerous-headers-in-dashboard.html
new file mode 100644 (file)
index 0000000..996645f
--- /dev/null
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<html>
+<body>
+<p>Test that setRequestHeader() can be used to alter security-sensitive headers in Dashboard compatibility mode. This test PASSED if you do not see any console warnings.</p>
+<script>
+    if (window.testRunner)
+        testRunner.dumpAsText();
+    if (window.internals.settings)
+        internals.settings.setUsesDashboardBackwardCompatibilityMode(true);
+
+    req = new XMLHttpRequest;
+    req.open("GET", "resources/non-existent-file.txt", false);
+
+    req.setRequestHeader("ACCEPT-CHARSET", "foobar");
+    req.setRequestHeader("ACCEPT-ENCODING", "foobar");
+    req.setRequestHeader("ACCESS-CONTROL-REQUEST-HEADERS", "foobar");
+    req.setRequestHeader("ACCESS-CONTROL-REQUEST-METHOD", "foobar");
+    // AUTHORIZATION is no longer forbidden. See
+    // https://bugs.webkit.org/show_bug.cgi?id=24957 for more details. Set to
+    // a value other than the foobar since some http servers (lighttp) do not
+    // strip this out (Apache does).
+    req.setRequestHeader("AUTHORIZATION", "baz");
+    req.setRequestHeader("CONNECTION", "foobar");
+    req.setRequestHeader("CONTENT-LENGTH", "123456");
+    req.setRequestHeader("CONTENT-TRANSFER-ENCODING", "foobar");
+    req.setRequestHeader("COOKIE", "foobar");
+    req.setRequestHeader("COOKIE2", "foobar");
+    req.setRequestHeader("DATE", "foobar");
+    req.setRequestHeader("DNT", "foobar");
+    req.setRequestHeader("EXPECT", "100-continue");
+    req.setRequestHeader("HOST", "foobar");
+    req.setRequestHeader("KEEP-ALIVE", "foobar");
+    req.setRequestHeader("ORIGIN", "foobar");
+    req.setRequestHeader("REFERER", "foobar");
+    req.setRequestHeader("TE", "foobar");
+    req.setRequestHeader("TRAILER", "foobar");
+    req.setRequestHeader("TRANSFER-ENCODING", "foobar");
+    req.setRequestHeader("UPGRADE", "foobar");
+    req.setRequestHeader("USER-AGENT", "foobar");
+    req.setRequestHeader("VIA", "foobar");
+
+    req.setRequestHeader("Proxy-", "foobar");
+    req.setRequestHeader("Proxy-test", "foobar");
+    req.setRequestHeader("PROXY-FOO", "foobar");
+
+    req.setRequestHeader("Sec-", "foobar");
+    req.setRequestHeader("Sec-test", "foobar");
+    req.setRequestHeader("SEC-FOO", "foobar");
+</script>
+</body>
+</html>
diff --git a/LayoutTests/fast/xmlhttprequest/set-dangerous-headers.html b/LayoutTests/fast/xmlhttprequest/set-dangerous-headers.html
new file mode 100644 (file)
index 0000000..02ea7d9
--- /dev/null
@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<html>
+<body>
+<p>Test that setRequestHeader() cannot be used to alter security-sensitive headers. This test PASSED if you see console warnings.</p>
+<script>
+    if (window.testRunner)
+        testRunner.dumpAsText();
+
+    req = new XMLHttpRequest;
+    req.open("GET", "resources/non-existent-file.txt", false);
+
+    req.setRequestHeader("ACCEPT-CHARSET", "foobar");
+    req.setRequestHeader("ACCEPT-ENCODING", "foobar");
+    req.setRequestHeader("ACCESS-CONTROL-REQUEST-HEADERS", "foobar");
+    req.setRequestHeader("ACCESS-CONTROL-REQUEST-METHOD", "foobar");
+    // AUTHORIZATION is no longer forbidden. See
+    // https://bugs.webkit.org/show_bug.cgi?id=24957 for more details. Set to
+    // a value other than the foobar since some http servers (lighttp) do not
+    // strip this out (Apache does).
+    req.setRequestHeader("AUTHORIZATION", "baz");
+    req.setRequestHeader("CONNECTION", "foobar");
+    req.setRequestHeader("CONTENT-LENGTH", "123456");
+    req.setRequestHeader("CONTENT-TRANSFER-ENCODING", "foobar");
+    req.setRequestHeader("COOKIE", "foobar");
+    req.setRequestHeader("COOKIE2", "foobar");
+    req.setRequestHeader("DATE", "foobar");
+    req.setRequestHeader("DNT", "foobar");
+    req.setRequestHeader("EXPECT", "100-continue");
+    req.setRequestHeader("HOST", "foobar");
+    req.setRequestHeader("KEEP-ALIVE", "foobar");
+    req.setRequestHeader("ORIGIN", "foobar");
+    req.setRequestHeader("REFERER", "foobar");
+    req.setRequestHeader("TE", "foobar");
+    req.setRequestHeader("TRAILER", "foobar");
+    req.setRequestHeader("TRANSFER-ENCODING", "foobar");
+    req.setRequestHeader("UPGRADE", "foobar");
+    req.setRequestHeader("USER-AGENT", "foobar");
+    req.setRequestHeader("VIA", "foobar");
+
+    req.setRequestHeader("Proxy-", "foobar");
+    req.setRequestHeader("Proxy-test", "foobar");
+    req.setRequestHeader("PROXY-FOO", "foobar");
+
+    req.setRequestHeader("Sec-", "foobar");
+    req.setRequestHeader("Sec-test", "foobar");
+    req.setRequestHeader("SEC-FOO", "foobar");
+</script>
+</body>
+</html>
index 0ba6ca1..6201f97 100644 (file)
@@ -29,6 +29,8 @@ fast/harness/uiscriptcontroller [ Pass ]
 
 fast/events/do-not-drag-and-drop-data-detectors-link.html [ Pass ]
 
+fast/xmlhttprequest/set-dangerous-headers-in-dashboard.html [ Pass ]
+
 #//////////////////////////////////////////////////////////////////////////////////////////
 # End platform-specific directories.
 #//////////////////////////////////////////////////////////////////////////////////////////
index 5cbfbdd..f1c7995 100644 (file)
@@ -1,3 +1,22 @@
+2017-10-03  Daniel Bates  <dabates@apple.com>
+
+        [XHR] Only exempt Dashboard widgets from XHR header restrictions
+        https://bugs.webkit.org/show_bug.cgi?id=177824
+        <rdar://problem/34384301>
+
+        Reviewed by Alexey Proskuryakov.
+
+        Currently we allow file URLs to set arbitrary XHR headers. In contrast, non-file URLs are
+        restricted from setting some XHR headers (e.g. COOKIE). Historically the relaxation for file
+        URL was for backwards compatibility to allow Dashboard widgets to work. Instead we should
+        apply the non-file URL policy to all URLs and only relax the policy for Dashboard widgets.
+
+        Tests: fast/xmlhttprequest/set-dangerous-headers-in-dashboard.html
+               fast/xmlhttprequest/set-dangerous-headers.html
+
+        * xml/XMLHttpRequest.cpp:
+        (WebCore::XMLHttpRequest::setRequestHeader):
+
 2017-10-03  Fujii Hironori  <Hironori.Fujii@sony.com>
 
         REGRESSION(r221909): Failing fast/text/international/iso-8859-8.html
index 16fbcf2..2594469 100644 (file)
@@ -923,8 +923,11 @@ ExceptionOr<void> XMLHttpRequest::setRequestHeader(const String& name, const Str
     if (!isValidHTTPToken(name) || !isValidHTTPHeaderValue(normalizedValue))
         return Exception { SyntaxError };
 
-    // A privileged script (e.g. a Dashboard widget) can set any headers.
-    if (!securityOrigin()->canLoadLocalResources() && !isAllowedHTTPHeader(name)) {
+    bool allowUnsafeHeaderField = false;
+#if ENABLE(DASHBOARD_SUPPORT)
+    allowUnsafeHeaderField = usesDashboardBackwardCompatibilityMode();
+#endif
+    if (!allowUnsafeHeaderField && !isAllowedHTTPHeader(name)) {
         logConsoleError(scriptExecutionContext(), "Refused to set unsafe header \"" + name + "\"");
         return { };
     }