Changeset 142683 in webkit


Ignore:
Timestamp:
Feb 12, 2013 3:44:51 PM (11 years ago)
Author:
mkwst@chromium.org
Message:

Implement script MIME restrictions for X-Content-Type-Options: nosniff
https://bugs.webkit.org/show_bug.cgi?id=71851

Reviewed by Adam Barth.

Source/WebCore:

This patch adds support for 'X-Content-Type-Options: nosniff' when
deciding whether or not to execute a given chunk of JavaScript. If the
header is present, script will only execute if it matches a predefined
set of MIME types[1] that are deemed "executable". Scripts served with
types that don't match the list will not execute.

IE introduced this feature, and Gecko is working on an implementation[2]
now. There's been some discussion on the WHATWG list about formalizing
the specification for this feature[3], but nothing significant has been
decided.

This implementation's list of acceptible MIME types differs from IE's:
it matches the list of supported JavaScript MIME types defined in
MIMETypeRegistry::initializeSupportedJavaScriptMIMETypes()[4]. In
particular, the VBScript types are not accepted, and
'text/javascript1.{1,2,3}' are accepted, along with 'text/livescript'.

This feature is locked tightly behind the ENABLE_NOSNIFF flag, which is
currently only enabled on the Chromium port.

[1]: http://msdn.microsoft.com/en-us/library/gg622941(v=vs.85).aspx
[2]: https://bugzilla.mozilla.org/show_bug.cgi?id=471020
[3]: http://lists.whatwg.org/htdig.cgi/whatwg-whatwg.org/2012-November/037974.html
[4]: http://trac.webkit.org/browser/trunk/Source/WebCore/platform/MIMETypeRegistry.cpp?rev=142086#L307

Tests: http/tests/security/contentTypeOptions/invalid-content-type-options-allowed.html

http/tests/security/contentTypeOptions/nosniff-script-allowed.html
http/tests/security/contentTypeOptions/nosniff-script-blocked.html
http/tests/security/contentTypeOptions/nosniff-script-without-content-type-allowed.html

  • dom/ScriptElement.cpp:

(WebCore::ScriptElement::executeScript):

Before executing script, ensure that it shouldn't be blocked due to
its MIME type. If it is blocked, write an error message to the
console.

  • loader/cache/CachedScript.cpp:

(WebCore::CachedScript::mimeType):

Make scripts' MIME type available outside the context of
CachedScript in order to correctly populate error messages we write
to the console in ScriptElement::executeScript

(WebCore):
(WebCore::CachedScript::mimeTypeAllowedByNosniff):

  • loader/cache/CachedScript.h:

(CachedScript):

A new method which checks the resource's HTTP headers to set the
'nosniff' disposition, and compares the resource's MIME type against
the list of allowed executable types. Returns true iff the script
is allowed.

  • platform/network/HTTPParsers.cpp:

(WebCore):
(WebCore::parseContentTypeOptionsHeader):

  • platform/network/HTTPParsers.h:

Adds a new enum which relates the sniffable status of the resource,
and a method to parse the HTTP header.

LayoutTests:

  • http/tests/security/contentTypeOptions/invalid-content-type-options-allowed-expected.txt: Added.
  • http/tests/security/contentTypeOptions/invalid-content-type-options-allowed.html: Added.
  • http/tests/security/contentTypeOptions/nosniff-script-allowed-expected.txt: Added.
  • http/tests/security/contentTypeOptions/nosniff-script-allowed.html: Added.
  • http/tests/security/contentTypeOptions/nosniff-script-blocked-expected.txt: Added.
  • http/tests/security/contentTypeOptions/nosniff-script-blocked.html: Added.
  • http/tests/security/contentTypeOptions/nosniff-script-without-content-type-blocked-expected.txt: Added.
  • http/tests/security/contentTypeOptions/nosniff-script-without-content-type-blocked.html: Added.
  • http/tests/security/contentTypeOptions/resources/script-with-header.pl: Added.

New tests!

  • platform/efl/TestExpectations:
  • platform/gtk/TestExpectations:
  • platform/mac/TestExpectations:
  • platform/qt/TestExpectations:
  • platform/win/TestExpectations:
  • platform/wincairo/TestExpectations:
  • platform/wk2/TestExpectations:

Skip the new tests on platforms where ENABLE_NOSNIFF isn't yet
enabled (everything other than Chromium).

Location:
trunk
Files:
11 added
14 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r142674 r142683  
     12013-02-12  Mike West  <mkwst@chromium.org>
     2
     3        Implement script MIME restrictions for X-Content-Type-Options: nosniff
     4        https://bugs.webkit.org/show_bug.cgi?id=71851
     5
     6        Reviewed by Adam Barth.
     7
     8        * http/tests/security/contentTypeOptions/invalid-content-type-options-allowed-expected.txt: Added.
     9        * http/tests/security/contentTypeOptions/invalid-content-type-options-allowed.html: Added.
     10        * http/tests/security/contentTypeOptions/nosniff-script-allowed-expected.txt: Added.
     11        * http/tests/security/contentTypeOptions/nosniff-script-allowed.html: Added.
     12        * http/tests/security/contentTypeOptions/nosniff-script-blocked-expected.txt: Added.
     13        * http/tests/security/contentTypeOptions/nosniff-script-blocked.html: Added.
     14        * http/tests/security/contentTypeOptions/nosniff-script-without-content-type-blocked-expected.txt: Added.
     15        * http/tests/security/contentTypeOptions/nosniff-script-without-content-type-blocked.html: Added.
     16        * http/tests/security/contentTypeOptions/resources/script-with-header.pl: Added.
     17            New tests!
     18        * platform/efl/TestExpectations:
     19        * platform/gtk/TestExpectations:
     20        * platform/mac/TestExpectations:
     21        * platform/qt/TestExpectations:
     22        * platform/win/TestExpectations:
     23        * platform/wincairo/TestExpectations:
     24        * platform/wk2/TestExpectations:
     25            Skip the new tests on platforms where ENABLE_NOSNIFF isn't yet
     26            enabled (everything other than Chromium).
     27
    1282013-02-12  Emil A Eklund  <eae@chromium.org>
    229
  • trunk/LayoutTests/platform/efl/TestExpectations

    r142599 r142683  
    307307fast/forms/file/input-file-entries.html
    308308http/tests/security/contentSecurityPolicy/filesystem-urls-match-self.html
     309
     310# X-Content-Type-Options (ENABLE_NOSNIFF) is not enabled.
     311http/tests/security/contentTypeOptions
    309312
    310313# Transparent image being produced
  • trunk/LayoutTests/platform/gtk/TestExpectations

    r142609 r142683  
    118118webkit.org/b/103547 fast/xpath/xpath-template-element.html [ Skip ]
    119119webkit.org/b/103547 fast/xsl/xslt-processor-template.html [ Skip ]
     120
     121# X-Content-Type-Options (ENABLE_NOSNIFF) is not enabled.
     122webkit.org/b/71851 http/tests/security/contentTypeOptions [ Skip ]
    120123
    121124# These test -apple- and -khtml- prefixed CSS properties, which we don't support.
  • trunk/LayoutTests/platform/mac/TestExpectations

    r142654 r142683  
    198198# ENABLE_GAMEPAD not enabled.
    199199gamepad/
     200
     201# X-Content-Type-Options (ENABLE_NOSNIFF) is not enabled.
     202http/tests/security/contentTypeOptions
    200203
    201204# Speech input is not yet enabled.
  • trunk/LayoutTests/platform/qt/TestExpectations

    r142580 r142683  
    482482# Missing eventSender.scheduleAsynchronousKeyDown() implementation
    483483fast/dom/MutationObserver/inline-event-listener.html
     484
     485# X-Content-Type-Options (ENABLE_NOSNIFF) is not enabled.
     486http/tests/security/contentTypeOptions
    484487
    485488# =========================================================================== #
  • trunk/LayoutTests/platform/win/TestExpectations

    r142580 r142683  
    5858fast/css/cursor-parsing-image-set.html
    5959fast/events/mouse-cursor-image-set.html
     60
     61# X-Content-Type-Options (ENABLE_NOSNIFF) is not enabled.
     62http/tests/security/contentTypeOptions
    6063
    6164# https://bugs.webkit.org/show_bug.cgi?id=77645
  • trunk/LayoutTests/platform/wincairo/TestExpectations

    r142599 r142683  
    25232523http/tests/security/contentSecurityPolicy/1.1
    25242524
     2525# X-Content-Type-Options (ENABLE_NOSNIFF) is not enabled.
     2526http/tests/security/contentTypeOptions
     2527
    25252528# Skip tests in fast/text/shaping
    25262529fast/text/shaping
  • trunk/LayoutTests/platform/wk2/TestExpectations

    r142599 r142683  
    564564# https://bugs.webkit.org/show_bug.cgi?id=85558
    565565http/tests/security/contentSecurityPolicy/1.1
     566
     567# X-Content-Type-Options (ENABLE_NOSNIFF) is not enabled.
     568http/tests/security/contentTypeOptions
    566569
    567570# Unexpected redirection happens.
  • trunk/Source/WebCore/ChangeLog

    r142673 r142683  
     12013-02-12  Mike West  <mkwst@chromium.org>
     2
     3        Implement script MIME restrictions for X-Content-Type-Options: nosniff
     4        https://bugs.webkit.org/show_bug.cgi?id=71851
     5
     6        Reviewed by Adam Barth.
     7
     8        This patch adds support for 'X-Content-Type-Options: nosniff' when
     9        deciding whether or not to execute a given chunk of JavaScript. If the
     10        header is present, script will only execute if it matches a predefined
     11        set of MIME types[1] that are deemed "executable". Scripts served with
     12        types that don't match the list will not execute.
     13
     14        IE introduced this feature, and Gecko is working on an implementation[2]
     15        now. There's been some discussion on the WHATWG list about formalizing
     16        the specification for this feature[3], but nothing significant has been
     17        decided.
     18
     19        This implementation's list of acceptible MIME types differs from IE's:
     20        it matches the list of supported JavaScript MIME types defined in
     21        MIMETypeRegistry::initializeSupportedJavaScriptMIMETypes()[4]. In
     22        particular, the VBScript types are not accepted, and
     23        'text/javascript1.{1,2,3}' are accepted, along with 'text/livescript'.
     24
     25        This feature is locked tightly behind the ENABLE_NOSNIFF flag, which is
     26        currently only enabled on the Chromium port.
     27
     28        [1]: http://msdn.microsoft.com/en-us/library/gg622941(v=vs.85).aspx
     29        [2]: https://bugzilla.mozilla.org/show_bug.cgi?id=471020
     30        [3]: http://lists.whatwg.org/htdig.cgi/whatwg-whatwg.org/2012-November/037974.html
     31        [4]: http://trac.webkit.org/browser/trunk/Source/WebCore/platform/MIMETypeRegistry.cpp?rev=142086#L307
     32
     33        Tests: http/tests/security/contentTypeOptions/invalid-content-type-options-allowed.html
     34               http/tests/security/contentTypeOptions/nosniff-script-allowed.html
     35               http/tests/security/contentTypeOptions/nosniff-script-blocked.html
     36               http/tests/security/contentTypeOptions/nosniff-script-without-content-type-allowed.html
     37
     38        * dom/ScriptElement.cpp:
     39        (WebCore::ScriptElement::executeScript):
     40            Before executing script, ensure that it shouldn't be blocked due to
     41            its MIME type. If it is blocked, write an error message to the
     42            console.
     43        * loader/cache/CachedScript.cpp:
     44        (WebCore::CachedScript::mimeType):
     45            Make scripts' MIME type available outside the context of
     46            CachedScript in order to correctly populate error messages we write
     47            to the console in ScriptElement::executeScript
     48        (WebCore):
     49        (WebCore::CachedScript::mimeTypeAllowedByNosniff):
     50        * loader/cache/CachedScript.h:
     51        (CachedScript):
     52            A new method which checks the resource's HTTP headers to set the
     53            'nosniff' disposition, and compares the resource's MIME type against
     54            the list of allowed executable types. Returns true iff the script
     55            is allowed.
     56        * platform/network/HTTPParsers.cpp:
     57        (WebCore):
     58        (WebCore::parseContentTypeOptionsHeader):
     59        * platform/network/HTTPParsers.h:
     60            Adds a new enum which relates the sniffable status of the resource,
     61            and a method to parse the HTTP header.
     62
    1632013-02-12  Adam Barth  <abarth@webkit.org>
    264
  • trunk/Source/WebCore/dom/ScriptElement.cpp

    r139942 r142683  
    294294        return;
    295295
     296#if ENABLE(NOSNIFF)
     297    if (m_isExternalScript && m_cachedScript && !m_cachedScript->mimeTypeAllowedByNosniff()) {
     298        m_element->document()->addConsoleMessage(JSMessageSource, ErrorMessageLevel, "Refused to execute script from '" + m_cachedScript->url().string() + "' because its MIME type ('" + m_cachedScript->mimeType() + "') is not executable, and strict MIME type checking is enabled.");
     299        return;
     300    }
     301#endif
     302
    296303    RefPtr<Document> document = m_element->document();
    297304    ASSERT(document);
  • trunk/Source/WebCore/loader/cache/CachedScript.cpp

    r141570 r142683  
    2828#include "CachedScript.h"
    2929
    30 #include "MemoryCache.h"
    3130#include "CachedResourceClient.h"
    3231#include "CachedResourceClientWalker.h"
     32#include "HTTPParsers.h"
     33#include "MIMETypeRegistry.h"
     34#include "MemoryCache.h"
    3335#include "ResourceBuffer.h"
    3436#include "TextResourceDecoder.h"
     
    6466{
    6567    return m_decoder->encoding().name();
     68}
     69
     70String CachedScript::mimeType() const
     71{
     72    return extractMIMETypeFromMediaType(m_response.httpHeaderField("Content-Type")).lower();
    6673}
    6774
     
    120127#endif
    121128
     129#if ENABLE(NOSNIFF)
     130bool CachedScript::mimeTypeAllowedByNosniff() const
     131{
     132    return !parseContentTypeOptionsHeader(m_response.httpHeaderField("X-Content-Type-Options")) == ContentTypeOptionsNosniff || MIMETypeRegistry::isSupportedJavaScriptMIMEType(mimeType());
     133}
     134#endif
     135
    122136void CachedScript::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
    123137{
  • trunk/Source/WebCore/loader/cache/CachedScript.h

    r130983 r142683  
    5050        virtual String encoding() const;
    5151        virtual void data(PassRefPtr<ResourceBuffer> data, bool allDataReceived);
     52        String mimeType() const;
    5253
    5354        virtual void destroyDecodedData();
     
    5657        JSC::SourceProviderCache* sourceProviderCache() const;
    5758        void sourceProviderCacheSizeChanged(int delta);
     59#endif
     60#if ENABLE(NOSNIFF)
     61        bool mimeTypeAllowedByNosniff() const;
    5862#endif
    5963
  • trunk/Source/WebCore/platform/network/HTTPParsers.cpp

    r133323 r142683  
    430430}
    431431
     432#if ENABLE(NOSNIFF)
     433ContentTypeOptionsDisposition parseContentTypeOptionsHeader(const String& header)
     434{
     435    if (header.stripWhiteSpace().lower() == "nosniff")
     436        return ContentTypeOptionsNosniff;
     437    return ContentTypeOptionsNone;
     438}
     439#endif
     440
    432441String extractReasonPhraseFromHTTPStatusLine(const String& statusLine)
    433442{
  • trunk/Source/WebCore/platform/network/HTTPParsers.h

    r133323 r142683  
    5454} ContentDispositionType;
    5555
     56#if ENABLE(NOSNIFF)
     57enum ContentTypeOptionsDisposition {
     58    ContentTypeOptionsNone,
     59    ContentTypeOptionsNosniff
     60};
     61#endif
     62
    5663ContentDispositionType contentDispositionType(const String&);
    5764bool isRFC2616Token(const String&);
     
    6875bool parseRange(const String&, long long& rangeOffset, long long& rangeEnd, long long& rangeSuffixLength);
    6976
     77#if ENABLE(NOSNIFF)
     78ContentTypeOptionsDisposition parseContentTypeOptionsHeader(const String& header);
     79#endif
     80
    7081// Parsing Complete HTTP Messages.
    7182enum HTTPVersion { Unknown, HTTP_1_0, HTTP_1_1 };
Note: See TracChangeset for help on using the changeset viewer.