- Revision
- 209261
- Author
- [email protected]
- Date
- 2016-12-02 13:33:51 -0800 (Fri, 02 Dec 2016)
Log Message
Require preflight for non-standard CORS-safelisted request headers Accept, Accept-Language, and Content-Language
https://bugs.webkit.org/show_bug.cgi?id=165178
<rdar://problem/18792250>
Reviewed by Youenn Fablet.
Fetch currently only restricts the header Content-Type for simple requests:
https://fetch.spec.whatwg.org/#cors-safelisted-request-header
This means simple CORS requests can send unexpected characters in Accept,
Accept-Language, and Content-Language header values.
RFC 7231 implies restrictions on these header values:
- Accept https://tools.ietf.org/html/rfc7231#section-5.3.2
- Accept-Language https://tools.ietf.org/html/rfc7231#section-5.3.5
- Content-Language https://tools.ietf.org/html/rfc7231#section-3.1.3.2
As per discussions in the W3C WebAppSec group we should try to restrict
these header values to help protect servers that do not expect simple CORS
requests.
Non-standard, safelisted header values should trigger a preflight and require
the headers to be whitelisted in the response's Access-Control-Allow-Headers.
For Fetch in no-cors mode this change means non-standard header values are not
allowed to be set.
Source/WebCore:
Test: http/tests/xmlhttprequest/cors-non-standard-safelisted-headers-should-trigger-preflight.html
* loader/CrossOriginAccessControl.cpp:
(WebCore::isSimpleCrossOriginAccessRequest):
Now calls WebCore::isCrossOriginSafeRequestHeader() instead of
WebCore::isOnAccessControlSimpleRequestHeaderWhitelist().
(WebCore::isOnAccessControlSimpleRequestHeaderWhitelist): Deleted.
It was a duplicate of WebCore::isCrossOriginSafeRequestHeader().
* loader/CrossOriginAccessControl.h:
* loader/CrossOriginPreflightResultCache.cpp:
(WebCore::CrossOriginPreflightResultCacheItem::allowsCrossOriginHeaders):
Now calls WebCore::isCrossOriginSafeRequestHeader() instead of
WebCore::isOnAccessControlSimpleRequestHeaderWhitelist().
* platform/network/HTTPParsers.cpp:
(WebCore::isValidAcceptHeaderValue):
Basic check that the characters are all ASCII alphanumeric, ' ', '*', '.',
'/', ';', or '='.
(WebCore::isValidLanguageHeaderValue):
Basic check that the characters are all ASCII alphanumeric, ' ', '*', '-',
'.', ';', or '='.
(WebCore::isSimpleHeader):
Removed duplicate code. Now calls WebCore::isCrossOriginSafeRequestHeader().
(WebCore::isCrossOriginSafeRequestHeader):
Now makes a call to WebCore::isValidAcceptHeaderValue() for Accept
headers and WebCore::isValidLanguageHeaderValue() for Accept-Language
and Content-Language headers.
* platform/network/HTTPParsers.h:
LayoutTests:
* http/tests/xmlhttprequest/cors-non-standard-safelisted-headers-should-trigger-preflight-expected.txt: Added.
* http/tests/xmlhttprequest/cors-non-standard-safelisted-headers-should-trigger-preflight.html: Added.
Tests that:
- Normal Accept, Accept-Language, and Content-Language headers don't trigger
a preflight.
- Abnormal Accept, Accept-Language, and Content-Language headers do trigger
a preflight.
- Abnormal Accept, Accept-Language, and Content-Language headers are
accepted if the server whitelists them.
* http/tests/xmlhttprequest/resources/cors-preflight-safelisted-headers-responder.php: Added.
Modified Paths
Added Paths
Diff
Modified: trunk/LayoutTests/ChangeLog (209260 => 209261)
--- trunk/LayoutTests/ChangeLog 2016-12-02 21:25:40 UTC (rev 209260)
+++ trunk/LayoutTests/ChangeLog 2016-12-02 21:33:51 UTC (rev 209261)
@@ -1,3 +1,42 @@
+2016-12-02 John Wilander <[email protected]>
+
+ Require preflight for non-standard CORS-safelisted request headers Accept, Accept-Language, and Content-Language
+ https://bugs.webkit.org/show_bug.cgi?id=165178
+ <rdar://problem/18792250>
+
+ Reviewed by Youenn Fablet.
+
+ Fetch currently only restricts the header Content-Type for simple requests:
+ https://fetch.spec.whatwg.org/#cors-safelisted-request-header
+
+ This means simple CORS requests can send unexpected characters in Accept,
+ Accept-Language, and Content-Language header values.
+
+ RFC 7231 implies restrictions on these header values:
+ - Accept https://tools.ietf.org/html/rfc7231#section-5.3.2
+ - Accept-Language https://tools.ietf.org/html/rfc7231#section-5.3.5
+ - Content-Language https://tools.ietf.org/html/rfc7231#section-3.1.3.2
+
+ As per discussions in the W3C WebAppSec group we should try to restrict
+ these header values to help protect servers that do not expect simple CORS
+ requests.
+
+ Non-standard, safelisted header values should trigger a preflight and require
+ the headers to be whitelisted in the response's Access-Control-Allow-Headers.
+ For Fetch in no-cors mode this change means non-standard header values are not
+ allowed to be set.
+
+ * http/tests/xmlhttprequest/cors-non-standard-safelisted-headers-should-trigger-preflight-expected.txt: Added.
+ * http/tests/xmlhttprequest/cors-non-standard-safelisted-headers-should-trigger-preflight.html: Added.
+ Tests that:
+ - Normal Accept, Accept-Language, and Content-Language headers don't trigger
+ a preflight.
+ - Abnormal Accept, Accept-Language, and Content-Language headers do trigger
+ a preflight.
+ - Abnormal Accept, Accept-Language, and Content-Language headers are
+ accepted if the server whitelists them.
+ * http/tests/xmlhttprequest/resources/cors-preflight-safelisted-headers-responder.php: Added.
+
2016-12-02 Zalan Bujtas <[email protected]>
ASSERTION FAILED: flowThread->regionInRange(region, startRegion, endRegion) in WebCore::RenderBox::borderBoxRectInRegion
Added: trunk/LayoutTests/http/tests/xmlhttprequest/cors-non-standard-safelisted-headers-should-trigger-preflight-expected.txt (0 => 209261)
--- trunk/LayoutTests/http/tests/xmlhttprequest/cors-non-standard-safelisted-headers-should-trigger-preflight-expected.txt (rev 0)
+++ trunk/LayoutTests/http/tests/xmlhttprequest/cors-non-standard-safelisted-headers-should-trigger-preflight-expected.txt 2016-12-02 21:33:51 UTC (rev 209261)
@@ -0,0 +1,21 @@
+CONSOLE MESSAGE: XMLHttpRequest cannot load http://localhost:8000/xmlhttprequest/resources/cors-preflight-safelisted-headers-responder.php. Request header field Accept is not allowed by Access-Control-Allow-Headers.
+CONSOLE MESSAGE: XMLHttpRequest cannot load http://localhost:8000/xmlhttprequest/resources/cors-preflight-safelisted-headers-responder.php. Request header field Accept-Language is not allowed by Access-Control-Allow-Headers.
+CONSOLE MESSAGE: XMLHttpRequest cannot load http://localhost:8000/xmlhttprequest/resources/cors-preflight-safelisted-headers-responder.php. Request header field Content-Language is not allowed by Access-Control-Allow-Headers.
+CONSOLE MESSAGE: XMLHttpRequest cannot load http://localhost:8000/xmlhttprequest/resources/cors-preflight-safelisted-headers-responder.php. Request header field Content-Language is not allowed by Access-Control-Allow-Headers.
+CONSOLE MESSAGE: XMLHttpRequest cannot load http://localhost:8000/xmlhttprequest/resources/cors-preflight-safelisted-headers-responder.php. Request header field Accept is not allowed by Access-Control-Allow-Headers.
+PASS Accept header with normal value SHOULD NOT cause a preflight
+PASS Accept header value with all allowed non-alphanumeric characters SHOULD NOT cause a preflight
+PASS Accept-Language header with normal value SHOULD NOT cause a preflight
+PASS Accept-Language header value with all allowed non-alphanumeric characters SHOULD NOT cause a preflight
+PASS Content-Language header with normal value SHOULD NOT cause a preflight
+PASS Content-Language header value with all allowed non-alphanumeric characters SHOULD NOT cause a preflight
+PASS Accept header with abnormal value SHOULD cause a preflight
+PASS Accept-Language header with abnormal value SHOULD cause a preflight
+PASS Content-Language header with abnormal value SHOULD cause a preflight
+PASS Accept header with normal value, Accept-Language header with normal value, and Content-Language header with abnormal value SHOULD cause a preflight
+PASS Accept header with normal value and then another Accept header with abnormal value SHOULD cause a preflight
+PASS Accept header with abnormal value and explicitly allowed headers SHOULD be allowed
+PASS Content-Language header with abnormal value and explicitly allowed headers SHOULD be allowed
+PASS Accept header with normal value, Accept-Language header with normal value, Content-Language header with abnormal value, and explicitly allowed headers SHOULD be allowed
+PASS Accept header with normal value, then another Accept header with abnormal value, and explicitly allowed headers SHOULD be allowed
+
Added: trunk/LayoutTests/http/tests/xmlhttprequest/cors-non-standard-safelisted-headers-should-trigger-preflight.html (0 => 209261)
--- trunk/LayoutTests/http/tests/xmlhttprequest/cors-non-standard-safelisted-headers-should-trigger-preflight.html (rev 0)
+++ trunk/LayoutTests/http/tests/xmlhttprequest/cors-non-standard-safelisted-headers-should-trigger-preflight.html 2016-12-02 21:33:51 UTC (rev 209261)
@@ -0,0 +1,160 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="UTF-8">
+ <title>Non-Standard Safelisted Headers SHOULD Trigger a Preflight</title>
+ <script src=""
+</head>
+<body>
+<!-- https://fetch.spec.whatwg.org/#cors-safelisted-request-header -->
+<script>
+ if (window.testRunner) {
+ testRunner.dumpAsText();
+ testRunner.waitUntilDone();
+ }
+
+ var xhr;
+ var url = '';
+
+ function createReadyStateHandler (description, testNumber) {
+ return function handler (e) {
+ if (xhr.readyState === XMLHttpRequest.DONE) {
+ testPassed(description);
+ nextStep(testNumber);
+ }
+ }
+ }
+
+ function createOnErrorHandler (description, testNumber) {
+ return function handler (e) {
+ e.preventDefault();
+ testPassed(description);
+ nextStep(testNumber);
+ }
+ }
+
+ var abnormalSimpleCorsHeaderValue = "() { :;};"
+ var allAllowedNonAlphanumericCharactersForAcceptHeader = " *./;="
+ var allAllowedNonAlphanumericCharactersForAcceptAndContentLanguageHeader = " *-.;="
+ var testCases = [
+ // Positive test cases with normal headers
+ {
+ headersToAdd: [{ name : "Accept", value: "text/*" }],
+ explicitlyAllowHeaders: false,
+ shouldCausePreflight: false,
+ description: "Accept header with normal value SHOULD NOT cause a preflight"
+ }
+ ,{
+ headersToAdd: [{ name : "Accept", value: allAllowedNonAlphanumericCharactersForAcceptHeader }],
+ explicitlyAllowHeaders: false,
+ shouldCausePreflight: false,
+ description: "Accept header value with all allowed non-alphanumeric characters SHOULD NOT cause a preflight"
+ }
+ ,{
+ headersToAdd: [{ name : "Accept-Language", value: "en" }],
+ explicitlyAllowHeaders: false,
+ shouldCausePreflight: false,
+ description: "Accept-Language header with normal value SHOULD NOT cause a preflight"
+ }
+ ,{
+ headersToAdd: [{ name : "Accept-Language", value: allAllowedNonAlphanumericCharactersForAcceptAndContentLanguageHeader }],
+ explicitlyAllowHeaders: false,
+ shouldCausePreflight: false,
+ description: "Accept-Language header value with all allowed non-alphanumeric characters SHOULD NOT cause a preflight"
+ }
+ ,{
+ headersToAdd: [{ name : "Content-Language", value: "en" }],
+ explicitlyAllowHeaders: false,
+ shouldCausePreflight: false,
+ description: "Content-Language header with normal value SHOULD NOT cause a preflight"
+ }
+ ,{
+ headersToAdd: [{ name : "Content-Language", value: allAllowedNonAlphanumericCharactersForAcceptAndContentLanguageHeader }],
+ explicitlyAllowHeaders: false,
+ shouldCausePreflight: false,
+ description: "Content-Language header value with all allowed non-alphanumeric characters SHOULD NOT cause a preflight"
+ }
+ // Negative test cases with abnormal headers
+ ,{
+ headersToAdd: [{ name : "Accept", value: abnormalSimpleCorsHeaderValue }],
+ explicitlyAllowHeaders: false,
+ shouldCausePreflight: true,
+ description: "Accept header with abnormal value SHOULD cause a preflight"
+ }
+ ,{
+ headersToAdd: [{ name : "Accept-Language", value: abnormalSimpleCorsHeaderValue }],
+ explicitlyAllowHeaders: false,
+ shouldCausePreflight: true,
+ description: "Accept-Language header with abnormal value SHOULD cause a preflight"
+ }
+ ,{
+ headersToAdd: [{ name : "Content-Language", value: abnormalSimpleCorsHeaderValue }],
+ explicitlyAllowHeaders: false,
+ shouldCausePreflight: true,
+ description: "Content-Language header with abnormal value SHOULD cause a preflight"
+ }
+ ,{
+ headersToAdd: [{ name : "Accept", value: "text/*" }, { name : "Accept-Language", value: "en" }, { name : "Content-Language", value: abnormalSimpleCorsHeaderValue }],
+ explicitlyAllowHeaders: false,
+ shouldCausePreflight: true,
+ description: "Accept header with normal value, Accept-Language header with normal value, and Content-Language header with abnormal value SHOULD cause a preflight"
+ }
+ ,{
+ headersToAdd: [{ name : "Accept", value: "text/*" }, { name : "Accept", value: abnormalSimpleCorsHeaderValue }],
+ explicitlyAllowHeaders: false,
+ shouldCausePreflight: true,
+ description: "Accept header with normal value and then another Accept header with abnormal value SHOULD cause a preflight"
+ }
+ // Positive test cases with abnormal headers
+ ,{
+ headersToAdd: [{ name : "Accept", value: abnormalSimpleCorsHeaderValue }],
+ explicitlyAllowHeaders: true,
+ shouldCausePreflight: true,
+ description: "Accept header with abnormal value and explicitly allowed headers SHOULD be allowed"
+ }
+ ,{
+ headersToAdd: [{ name : "Content-Language", value: abnormalSimpleCorsHeaderValue }],
+ explicitlyAllowHeaders: true,
+ shouldCausePreflight: true,
+ description: "Content-Language header with abnormal value and explicitly allowed headers SHOULD be allowed"
+ }
+ ,{
+ headersToAdd: [{ name : "Accept", value: "text/*" }, { name : "Accept-Language", value: "en" }, { name : "Content-Language", value: abnormalSimpleCorsHeaderValue }],
+ explicitlyAllowHeaders: true,
+ shouldCausePreflight: true,
+ description: "Accept header with normal value, Accept-Language header with normal value, Content-Language header with abnormal value, and explicitly allowed headers SHOULD be allowed"
+ }
+ ,{
+ headersToAdd: [{ name : "Accept", value: "text/*" }, { name : "Accept", value: abnormalSimpleCorsHeaderValue }],
+ explicitlyAllowHeaders: true,
+ shouldCausePreflight: true,
+ description: "Accept header with normal value, then another Accept header with abnormal value, and explicitly allowed headers SHOULD be allowed"
+ }
+ ];
+
+ function runTestCase(testNumber) {
+ var testCase = testCases[testNumber];
+ xhr = new XMLHttpRequest();
+ xhr.open('GET', url + (testCase.explicitlyAllowHeaders ? "/?explicitlyAllowHeaders=true" : ""), true);
+ for (var i = 0; i < testCase.headersToAdd.length; i++) {
+ xhr.setRequestHeader(testCase.headersToAdd[i].name, testCase.headersToAdd[i].value);
+ }
+ if (testCase.shouldCausePreflight && !testCase.explicitlyAllowHeaders)
+ xhr._onerror_ = createOnErrorHandler(testCase.description, testNumber);
+ else
+ xhr._onreadystatechange_ = createReadyStateHandler(testCase.description, testNumber);
+ xhr.send();
+ }
+
+ function nextStep (testNumber) {
+ if (testNumber === (testCases.length - 1)) {
+ if (window.testRunner)
+ testRunner.notifyDone();
+ } else
+ runTestCase(testNumber + 1);
+ }
+
+ runTestCase(0);
+</script>
+</body>
+</html>
\ No newline at end of file
Added: trunk/LayoutTests/http/tests/xmlhttprequest/resources/cors-preflight-safelisted-headers-responder.php (0 => 209261)
--- trunk/LayoutTests/http/tests/xmlhttprequest/resources/cors-preflight-safelisted-headers-responder.php (rev 0)
+++ trunk/LayoutTests/http/tests/xmlhttprequest/resources/cors-preflight-safelisted-headers-responder.php 2016-12-02 21:33:51 UTC (rev 209261)
@@ -0,0 +1,8 @@
+<?php
+header('Access-Control-Allow-Origin: http://127.0.0.1:8000');
+
+if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS' && isset($_GET['explicitlyAllowHeaders'])) {
+ header('Access-Control-Allow-Methods: GET, OPTIONS');
+ header('Access-Control-Allow-Headers: Accept, Accept-Language, Content-Language');
+}
+?>
\ No newline at end of file
Modified: trunk/Source/WebCore/ChangeLog (209260 => 209261)
--- trunk/Source/WebCore/ChangeLog 2016-12-02 21:25:40 UTC (rev 209260)
+++ trunk/Source/WebCore/ChangeLog 2016-12-02 21:33:51 UTC (rev 209261)
@@ -1,3 +1,59 @@
+2016-12-02 John Wilander <[email protected]>
+
+ Require preflight for non-standard CORS-safelisted request headers Accept, Accept-Language, and Content-Language
+ https://bugs.webkit.org/show_bug.cgi?id=165178
+ <rdar://problem/18792250>
+
+ Reviewed by Youenn Fablet.
+
+ Fetch currently only restricts the header Content-Type for simple requests:
+ https://fetch.spec.whatwg.org/#cors-safelisted-request-header
+
+ This means simple CORS requests can send unexpected characters in Accept,
+ Accept-Language, and Content-Language header values.
+
+ RFC 7231 implies restrictions on these header values:
+ - Accept https://tools.ietf.org/html/rfc7231#section-5.3.2
+ - Accept-Language https://tools.ietf.org/html/rfc7231#section-5.3.5
+ - Content-Language https://tools.ietf.org/html/rfc7231#section-3.1.3.2
+
+ As per discussions in the W3C WebAppSec group we should try to restrict
+ these header values to help protect servers that do not expect simple CORS
+ requests.
+
+ Non-standard, safelisted header values should trigger a preflight and require
+ the headers to be whitelisted in the response's Access-Control-Allow-Headers.
+ For Fetch in no-cors mode this change means non-standard header values are not
+ allowed to be set.
+
+ Test: http/tests/xmlhttprequest/cors-non-standard-safelisted-headers-should-trigger-preflight.html
+
+ * loader/CrossOriginAccessControl.cpp:
+ (WebCore::isSimpleCrossOriginAccessRequest):
+ Now calls WebCore::isCrossOriginSafeRequestHeader() instead of
+ WebCore::isOnAccessControlSimpleRequestHeaderWhitelist().
+ (WebCore::isOnAccessControlSimpleRequestHeaderWhitelist): Deleted.
+ It was a duplicate of WebCore::isCrossOriginSafeRequestHeader().
+ * loader/CrossOriginAccessControl.h:
+ * loader/CrossOriginPreflightResultCache.cpp:
+ (WebCore::CrossOriginPreflightResultCacheItem::allowsCrossOriginHeaders):
+ Now calls WebCore::isCrossOriginSafeRequestHeader() instead of
+ WebCore::isOnAccessControlSimpleRequestHeaderWhitelist().
+ * platform/network/HTTPParsers.cpp:
+ (WebCore::isValidAcceptHeaderValue):
+ Basic check that the characters are all ASCII alphanumeric, ' ', '*', '.',
+ '/', ';', or '='.
+ (WebCore::isValidLanguageHeaderValue):
+ Basic check that the characters are all ASCII alphanumeric, ' ', '*', '-',
+ '.', ';', or '='.
+ (WebCore::isSimpleHeader):
+ Removed duplicate code. Now calls WebCore::isCrossOriginSafeRequestHeader().
+ (WebCore::isCrossOriginSafeRequestHeader):
+ Now makes a call to WebCore::isValidAcceptHeaderValue() for Accept
+ headers and WebCore::isValidLanguageHeaderValue() for Accept-Language
+ and Content-Language headers.
+ * platform/network/HTTPParsers.h:
+
2016-12-02 Zalan Bujtas <[email protected]>
ASSERTION FAILED: flowThread->regionInRange(region, startRegion, endRegion) in WebCore::RenderBox::borderBoxRectInRegion
Modified: trunk/Source/WebCore/loader/CrossOriginAccessControl.cpp (209260 => 209261)
--- trunk/Source/WebCore/loader/CrossOriginAccessControl.cpp 2016-12-02 21:25:40 UTC (rev 209260)
+++ trunk/Source/WebCore/loader/CrossOriginAccessControl.cpp 2016-12-02 21:33:51 UTC (rev 209261)
@@ -45,25 +45,6 @@
return method == "GET" || method == "HEAD" || method == "POST";
}
-bool isOnAccessControlSimpleRequestHeaderWhitelist(HTTPHeaderName name, const String& value)
-{
- switch (name) {
- case HTTPHeaderName::Accept:
- case HTTPHeaderName::AcceptLanguage:
- case HTTPHeaderName::ContentLanguage:
- return true;
- case HTTPHeaderName::ContentType: {
- // Preflight is required for MIME types that can not be sent via form submission.
- String mimeType = extractMIMETypeFromMediaType(value);
- return equalIgnoringASCIICase(mimeType, "application/x-www-form-urlencoded")
- || equalIgnoringASCIICase(mimeType, "multipart/form-data")
- || equalIgnoringASCIICase(mimeType, "text/plain");
- }
- default:
- return false;
- }
-}
-
bool isSimpleCrossOriginAccessRequest(const String& method, const HTTPHeaderMap& headerMap)
{
if (!isOnAccessControlSimpleRequestMethodWhitelist(method))
@@ -70,7 +51,7 @@
return false;
for (const auto& header : headerMap) {
- if (!header.keyAsHTTPHeaderName || !isOnAccessControlSimpleRequestHeaderWhitelist(header.keyAsHTTPHeaderName.value(), header.value))
+ if (!header.keyAsHTTPHeaderName || !isCrossOriginSafeRequestHeader(header.keyAsHTTPHeaderName.value(), header.value))
return false;
}
Modified: trunk/Source/WebCore/loader/CrossOriginAccessControl.h (209260 => 209261)
--- trunk/Source/WebCore/loader/CrossOriginAccessControl.h 2016-12-02 21:25:40 UTC (rev 209260)
+++ trunk/Source/WebCore/loader/CrossOriginAccessControl.h 2016-12-02 21:33:51 UTC (rev 209261)
@@ -40,7 +40,6 @@
bool isSimpleCrossOriginAccessRequest(const String& method, const HTTPHeaderMap&);
bool isOnAccessControlSimpleRequestMethodWhitelist(const String&);
-bool isOnAccessControlSimpleRequestHeaderWhitelist(HTTPHeaderName, const String& value);
bool isOnAccessControlResponseHeaderWhitelist(const String&);
void updateRequestForAccessControl(ResourceRequest&, SecurityOrigin&, StoredCredentials);
Modified: trunk/Source/WebCore/loader/CrossOriginPreflightResultCache.cpp (209260 => 209261)
--- trunk/Source/WebCore/loader/CrossOriginPreflightResultCache.cpp 2016-12-02 21:25:40 UTC (rev 209260)
+++ trunk/Source/WebCore/loader/CrossOriginPreflightResultCache.cpp 2016-12-02 21:33:51 UTC (rev 209261)
@@ -29,6 +29,7 @@
#include "CrossOriginAccessControl.h"
#include "HTTPHeaderNames.h"
+#include "HTTPParsers.h"
#include "ResourceResponse.h"
#include <wtf/MainThread.h>
#include <wtf/NeverDestroyed.h>
@@ -127,7 +128,7 @@
bool CrossOriginPreflightResultCacheItem::allowsCrossOriginHeaders(const HTTPHeaderMap& requestHeaders, String& errorDescription) const
{
for (const auto& header : requestHeaders) {
- if (header.keyAsHTTPHeaderName && isOnAccessControlSimpleRequestHeaderWhitelist(header.keyAsHTTPHeaderName.value(), header.value))
+ if (header.keyAsHTTPHeaderName && isCrossOriginSafeRequestHeader(header.keyAsHTTPHeaderName.value(), header.value))
continue;
if (!m_headers.contains(header.key)) {
errorDescription = "Request header field " + header.key + " is not allowed by Access-Control-Allow-Headers.";
Modified: trunk/Source/WebCore/platform/network/HTTPParsers.cpp (209260 => 209261)
--- trunk/Source/WebCore/platform/network/HTTPParsers.cpp 2016-12-02 21:25:40 UTC (rev 209260)
+++ trunk/Source/WebCore/platform/network/HTTPParsers.cpp 2016-12-02 21:33:51 UTC (rev 209261)
@@ -34,6 +34,7 @@
#include "HTTPParsers.h"
#include "HTTPHeaderNames.h"
+#include "Language.h"
#include <wtf/DateMath.h>
#include <wtf/NeverDestroyed.h>
#include <wtf/text/CString.h>
@@ -126,6 +127,36 @@
return true;
}
+// See RFC 7231, Section 5.3.2
+bool isValidAcceptHeaderValue(const String& value)
+{
+ for (unsigned i = 0; i < value.length(); ++i) {
+ UChar c = value[i];
+ if (isASCIIAlphanumeric(c) || c == ' ' || c == '*' || c == '.' || c == '/' || c == ';' || c == '=')
+ continue;
+ return false;
+ }
+
+ return true;
+}
+
+// See RFC 7231, Section 5.3.5 and 3.1.3.2
+bool isValidLanguageHeaderValue(const String& value)
+{
+ for (unsigned i = 0; i < value.length(); ++i) {
+ UChar c = value[i];
+ if (isASCIIAlphanumeric(c) || c == ' ' || c == '*' || c == '-' || c == '.' || c == ';' || c == '=')
+ continue;
+ return false;
+ }
+
+ // FIXME: Validate further by splitting into language tags and optional quality
+ // values (q=) and then check each language tag.
+ // Language tags https://tools.ietf.org/html/rfc7231#section-3.1.3.1
+ // Language tag syntax https://tools.ietf.org/html/bcp47#section-2.1
+ return true;
+}
+
// See RFC 7230, Section 3.2.6.
bool isValidHTTPToken(const String& value)
{
@@ -732,7 +763,7 @@
}
}
-// Implememtnation of https://fetch.spec.whatwg.org/#cors-safelisted-response-header-name
+// Implementation of https://fetch.spec.whatwg.org/#cors-safelisted-response-header-name
bool isForbiddenHeaderName(const String& name)
{
HTTPHeaderName headerName;
@@ -776,18 +807,7 @@
HTTPHeaderName headerName;
if (!findHTTPHeaderName(name, headerName))
return false;
- switch (headerName) {
- case HTTPHeaderName::Accept:
- case HTTPHeaderName::AcceptLanguage:
- case HTTPHeaderName::ContentLanguage:
- return true;
- case HTTPHeaderName::ContentType: {
- String mimeType = extractMIMETypeFromMediaType(value);
- return equalLettersIgnoringASCIICase(mimeType, "application/x-www-form-urlencoded") || equalLettersIgnoringASCIICase(mimeType, "multipart/form-data") || equalLettersIgnoringASCIICase(mimeType, "text/plain");
- }
- default:
- return false;
- }
+ return isCrossOriginSafeRequestHeader(headerName, value);
}
bool isCrossOriginSafeHeader(HTTPHeaderName name, const HTTPHeaderSet& accessControlExposeHeaderSet)
@@ -824,10 +844,12 @@
{
switch (name) {
case HTTPHeaderName::Accept:
+ return isValidAcceptHeaderValue(value);
case HTTPHeaderName::AcceptLanguage:
case HTTPHeaderName::ContentLanguage:
- return true;
+ return isValidLanguageHeaderValue(value);
case HTTPHeaderName::ContentType: {
+ // Preflight is required for MIME types that can not be sent via form submission.
String mimeType = extractMIMETypeFromMediaType(value);
return equalLettersIgnoringASCIICase(mimeType, "application/x-www-form-urlencoded") || equalLettersIgnoringASCIICase(mimeType, "multipart/form-data") || equalLettersIgnoringASCIICase(mimeType, "text/plain");
}
Modified: trunk/Source/WebCore/platform/network/HTTPParsers.h (209260 => 209261)
--- trunk/Source/WebCore/platform/network/HTTPParsers.h 2016-12-02 21:25:40 UTC (rev 209260)
+++ trunk/Source/WebCore/platform/network/HTTPParsers.h 2016-12-02 21:33:51 UTC (rev 209261)
@@ -69,6 +69,8 @@
bool isValidReasonPhrase(const String&);
bool isValidHTTPHeaderValue(const String&);
+bool isValidAcceptHeaderValue(const String&);
+bool isValidLanguageHeaderValue(const String&);
bool isValidHTTPToken(const String&);
bool parseHTTPRefresh(const String& refresh, double& delay, String& url);
std::optional<std::chrono::system_clock::time_point> parseHTTPDate(const String&);