Diff
Modified: trunk/LayoutTests/ChangeLog (258798 => 258799)
--- trunk/LayoutTests/ChangeLog 2020-03-20 23:24:33 UTC (rev 258798)
+++ trunk/LayoutTests/ChangeLog 2020-03-20 23:52:09 UTC (rev 258799)
@@ -1,3 +1,14 @@
+2020-03-20 David Kilzer <[email protected]>
+
+ Content-Type & Nosniff Ignored on XML External Entity Resources
+ <https://webkit.org/b/191171>
+ <rdar://problem/45763222>
+
+ Reviewed by Darin Adler.
+
+ * http/tests/security/contentTypeOptions/nosniff-xml-external-entity-expected.txt: Add.
+ * http/tests/security/contentTypeOptions/nosniff-xml-external-entity.xhtml: Add.
+
2020-03-20 Sihui Liu <[email protected]>
REGRESSION (r258707): storage/indexeddb/cursor-leak.html is flaky timing out
Added: trunk/LayoutTests/http/tests/security/contentTypeOptions/nosniff-xml-external-entity-expected.txt (0 => 258799)
--- trunk/LayoutTests/http/tests/security/contentTypeOptions/nosniff-xml-external-entity-expected.txt (rev 0)
+++ trunk/LayoutTests/http/tests/security/contentTypeOptions/nosniff-xml-external-entity-expected.txt 2020-03-20 23:52:09 UTC (rev 258799)
@@ -0,0 +1,17 @@
+CONSOLE MESSAGE: Did not parse external entity resource at 'http://127.0.0.1:8000/security/contentTypeOptions/resources/script-with-header.pl?mime=application/pdf' because non XML External Entity MIME types are not allowed when 'X-Content-Type-Options: nosniff' is given.
+CONSOLE MESSAGE: Did not parse external entity resource at 'http://127.0.0.1:8000/security/contentTypeOptions/resources/script-with-header.pl?mime=text/html' because non XML External Entity MIME types are not allowed when 'X-Content-Type-Options: nosniff' is given.
+CONSOLE MESSAGE: Did not parse external entity resource at 'http://127.0.0.1:8000/security/contentTypeOptions/resources/script-with-header.pl?mime=text/_javascript_' because non XML External Entity MIME types are not allowed when 'X-Content-Type-Options: nosniff' is given.
+CONSOLE MESSAGE: line 42: Executed script with MIME type: 'application/xml'.
+CONSOLE MESSAGE: line 42: Executed script with MIME type: 'text/xml'.
+CONSOLE MESSAGE: line 42: Executed script with MIME type: 'application/xml-external-parsed-entity'.
+CONSOLE MESSAGE: line 42: Executed script with MIME type: 'text/xml-external-parsed-entity'.
+Check that xml external entity resources loaded with an 'X-Content-Type-Options: nosniff' header are correctly accepted or blocked based on the MIME type.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS window.scriptsSuccessfullyLoaded is 4
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Added: trunk/LayoutTests/http/tests/security/contentTypeOptions/nosniff-xml-external-entity.xhtml (0 => 258799)
--- trunk/LayoutTests/http/tests/security/contentTypeOptions/nosniff-xml-external-entity.xhtml (rev 0)
+++ trunk/LayoutTests/http/tests/security/contentTypeOptions/nosniff-xml-external-entity.xhtml 2020-03-20 23:52:09 UTC (rev 258799)
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"
+[
+<!ENTITY entA SYSTEM "http://127.0.0.1:8000/security/contentTypeOptions/resources/script-with-header.pl?mime=application/xml">
+<!ENTITY entB SYSTEM "http://127.0.0.1:8000/security/contentTypeOptions/resources/script-with-header.pl?mime=text/xml">
+<!ENTITY entC SYSTEM "http://127.0.0.1:8000/security/contentTypeOptions/resources/script-with-header.pl?mime=application/xml-external-parsed-entity">
+<!ENTITY entD SYSTEM "http://127.0.0.1:8000/security/contentTypeOptions/resources/script-with-header.pl?mime=text/xml-external-parsed-entity">
+<!ENTITY entE SYSTEM "http://127.0.0.1:8000/security/contentTypeOptions/resources/script-with-header.pl?mime=application/pdf">
+<!ENTITY entF SYSTEM "http://127.0.0.1:8000/security/contentTypeOptions/resources/script-with-header.pl?mime=text/html">
+<!ENTITY entG SYSTEM "http://127.0.0.1:8000/security/contentTypeOptions/resources/script-with-header.pl?mime=text/_javascript_">
+]>
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+ <title>'X-Content-Type-Options: nosniff' blocks xml external entity resources with improper MIME type</title>
+ <script src=""
+ <script type="text/_javascript_">
+ window.jsTestIsAsync = true;
+ window.scriptsSuccessfullyLoaded = 0;
+
+ window._onload_ = function () {
+ shouldBe('window.scriptsSuccessfullyLoaded', '4');
+ finishJSTest();
+ };
+ </script>
+ <script type="text/_javascript_">&entA;</script>
+ <script type="text/_javascript_">&entB;</script>
+ <script type="text/_javascript_">&entC;</script>
+ <script type="text/_javascript_">&entD;</script>
+ <script type="text/_javascript_">&entE;</script>
+ <script type="text/_javascript_">&entF;</script>
+ <script type="text/_javascript_">&entG;</script>
+</head>
+<body>
+ <script type="text/_javascript_">
+ description('Check that xml external entity resources loaded with an \'X-Content-Type-Options: nosniff\' header are correctly accepted or blocked based on the MIME type.');
+ </script>
+ <script src=""
+</body>
+</html>
Modified: trunk/Source/WebCore/ChangeLog (258798 => 258799)
--- trunk/Source/WebCore/ChangeLog 2020-03-20 23:24:33 UTC (rev 258798)
+++ trunk/Source/WebCore/ChangeLog 2020-03-20 23:52:09 UTC (rev 258799)
@@ -1,3 +1,29 @@
+2020-03-20 David Kilzer <[email protected]>
+
+ Content-Type & Nosniff Ignored on XML External Entity Resources
+ <https://webkit.org/b/191171>
+ <rdar://problem/45763222>
+
+ Reviewed by Darin Adler.
+
+ Test: http/tests/security/contentTypeOptions/nosniff-xml-external-entity.xhtml
+
+ * platform/MIMETypeRegistry.cpp:
+ (WebCore::MIMETypeRegistry::isXMLEntityMIMEType): Add.
+ * platform/MIMETypeRegistry.h:
+ (WebCore::MIMETypeRegistry::isXMLEntityMIMEType): Add.
+ - Checks for XML external entity MIME types.
+
+ * xml/parser/XMLDocumentParserLibxml2.cpp:
+ (WebCore::externalEntityMimeTypeAllowedByNosniff): Add.
+ - Checks whether the MIME type is valid based on the presence of
+ the "X-Content-Type-Options: nosniff" header.
+ (WebCore::openFunc):
+ - Drop the contents of the resource that was returned and print
+ an error message to the Web Inspector console if
+ externalEntityMimeTypeAllowedByNosniff() says the MIME type is
+ not allowed.
+
2020-03-20 Alex Christensen <[email protected]>
CORS-disabling SPI introduced in r253978 should make responses non-opaque
Modified: trunk/Source/WebCore/platform/MIMETypeRegistry.cpp (258798 => 258799)
--- trunk/Source/WebCore/platform/MIMETypeRegistry.cpp 2020-03-20 23:24:33 UTC (rev 258798)
+++ trunk/Source/WebCore/platform/MIMETypeRegistry.cpp 2020-03-20 23:52:09 UTC (rev 258799)
@@ -637,6 +637,12 @@
return true;
}
+bool MIMETypeRegistry::isXMLEntityMIMEType(StringView mimeType)
+{
+ return equalLettersIgnoringASCIICase(mimeType, "text/xml-external-parsed-entity")
+ || equalLettersIgnoringASCIICase(mimeType, "application/xml-external-parsed-entity");
+}
+
bool MIMETypeRegistry::isJavaAppletMIMEType(const String& mimeType)
{
// Since this set is very limited and is likely to remain so we won't bother with the overhead
Modified: trunk/Source/WebCore/platform/MIMETypeRegistry.h (258798 => 258799)
--- trunk/Source/WebCore/platform/MIMETypeRegistry.h 2020-03-20 23:24:33 UTC (rev 258798)
+++ trunk/Source/WebCore/platform/MIMETypeRegistry.h 2020-03-20 23:52:09 UTC (rev 258799)
@@ -126,6 +126,9 @@
// rather than an HTML document.
WEBCORE_EXPORT static bool isXMLMIMEType(const String& mimeType);
+ // Check to see if a MIME type is for an XML external entity resource.
+ WEBCORE_EXPORT static bool isXMLEntityMIMEType(StringView mimeType);
+
// Used in page load algorithm to decide whether to display as a text
// document in a frame. Not a good idea to use elsewhere, because that code
// makes this test is after many other tests are done on the MIME type.
Modified: trunk/Source/WebCore/xml/parser/XMLDocumentParserLibxml2.cpp (258798 => 258799)
--- trunk/Source/WebCore/xml/parser/XMLDocumentParserLibxml2.cpp 2020-03-20 23:24:33 UTC (rev 258798)
+++ trunk/Source/WebCore/xml/parser/XMLDocumentParserLibxml2.cpp 2020-03-20 23:52:09 UTC (rev 258799)
@@ -39,7 +39,9 @@
#include "HTMLEntityParser.h"
#include "HTMLHtmlElement.h"
#include "HTMLTemplateElement.h"
+#include "HTTPParsers.h"
#include "InlineClassicScript.h"
+#include "MIMETypeRegistry.h"
#include "PendingScript.h"
#include "ProcessingInstruction.h"
#include "ResourceError.h"
@@ -375,6 +377,19 @@
unsigned m_currentOffset;
};
+static bool externalEntityMimeTypeAllowedByNosniff(const ResourceResponse& response)
+{
+ ContentTypeOptionsDisposition contentTypeOption = parseContentTypeOptionsHeader(response.httpHeaderField(HTTPHeaderName::XContentTypeOptions));
+ if (contentTypeOption != ContentTypeOptionsNosniff) {
+ // Allow any MIME type without 'X-Content-Type-Options: nosniff' HTTP header.
+ return true;
+ }
+ String mimeType = extractMIMETypeFromMediaType(response.httpHeaderField(HTTPHeaderName::ContentType));
+ if (MIMETypeRegistry::isXMLMIMEType(mimeType) || MIMETypeRegistry::isXMLEntityMIMEType(mimeType))
+ return true;
+ return false;
+}
+
static inline void setAttributes(Element* element, Vector<Attribute>& attributeVector, ParserContentPolicy parserContentPolicy)
{
if (!scriptingContentIsAllowed(parserContentPolicy))
@@ -455,6 +470,11 @@
options.mode = FetchOptions::Mode::SameOrigin;
options.credentials = FetchOptions::Credentials::Include;
cachedResourceLoader->frame()->loader().loadResourceSynchronously(url, ClientCredentialPolicy::MayAskClientForCredentials, options, { }, error, response, data);
+ if (!externalEntityMimeTypeAllowedByNosniff(response)) {
+ data = ""
+ if (Page* page = cachedResourceLoader->document()->page())
+ page->console().addMessage(MessageSource::Security, MessageLevel::Error, makeString("Did not parse external entity resource at '", url.stringCenterEllipsizedToLength(), "' because non XML External Entity MIME types are not allowed when 'X-Content-Type-Options: nosniff' is given."));
+ }
}
}