⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 196874 in webkit


Ignore:
Timestamp:
Feb 21, 2016, 10:52:51 AM (11 years ago)
Author:
dbates@webkit.org
Message:

CSP: sandbox directive should be ignored when contained in a policy defined via a meta element
​https://bugs.webkit.org/show_bug.cgi?id=154299
<rdar://problem/24680433>

Reviewed by Brent Fulgham.

Source/WebCore:

The Content Security Policy sandbox directive should only be honored when enforcing a policy
defined via an HTTP header as per section sandbox of the Content Security Policy 2.0 spec.,
<​https://www.w3.org/TR/2015/CR-CSP2-20150721/>.

Currently we honor the sandbox directive when enforcing a policy defined either via an HTML
meta element or an HTTP header. Instead we should only honor this directive when defined
via an HTTP header and log a message to the Web Inspector console to explain that the directive
was ignored as suggested in <​https://www.w3.org/TR/2015/CR-CSP2-20150721/#delivery-html-meta-element>.

Tests: http/tests/security/contentSecurityPolicy/sandbox-allow-scripts-in-http-header2.php

http/tests/security/contentSecurityPolicy/sandbox-empty-in-http-header-inherited-by-subframe.php
http/tests/security/contentSecurityPolicy/sandbox-empty-in-http-header.php
http/tests/security/contentSecurityPolicy/sandbox-in-meta-tag-ignored.html

  • dom/Document.cpp:

(WebCore::Document::processHttpEquiv): Substitute ContentSecurityPolicy::processHTTPEquiv() for
ContentSecurityPolicy::didReceiveHeader() as the latter was made private.

  • page/csp/ContentSecurityPolicy.cpp:

(WebCore::ContentSecurityPolicy::copyStateFrom): Updated as needed based on ContentSecurityPolicy::didReceiveHeader() change below.
(WebCore::ContentSecurityPolicy::didReceiveHeaders): Ditto.
(WebCore::ContentSecurityPolicy::didReceiveHeader): Modified to take argument of type ContentSecurityPolicy::PolicyFrom
and pass it through to ContentSecurityPolicyDirectiveList::create().
(WebCore::ContentSecurityPolicy::reportInvalidDirectiveInHTTPEquivMeta): Logs a message to the Web Inspector console
that the specified directive was ignored because it was delivered via an HTML meta element.

  • page/csp/ContentSecurityPolicy.h: Made member function ContentSecurityPolicy::didReceiveHeader() private. Defined

enum class PolicyFrom to represent the source of the Content Security Policy: HTTP equiv meta element, HTTP header, or
inherited from another ContentSecurityPolicy object (this value is only used by ContentSecurityPolicy::copyStateFrom()).
(WebCore::ContentSecurityPolicy::processHTTPEquiv): Added; turns around and calls ContentSecurityPolicy::didReceiveHeader().
The name of this function better describes its purpose - to handle the processing of a Content Security Policy
delivered via <meta http-equiv="Content-Security-Policy" content="...">.

  • page/csp/ContentSecurityPolicyDirectiveList.cpp:

(WebCore::ContentSecurityPolicyDirectiveList::create): Modified to take argument of type ContentSecurityPolicy::PolicyFrom
as pass it through to ContentSecurityPolicyDirectiveList::parse().
(WebCore::ContentSecurityPolicyDirectiveList::parse): Modified to ignore the directive sandbox when the Content Security
Policy came from an HTML meta element.

  • page/csp/ContentSecurityPolicyDirectiveList.h:

LayoutTests:

Add test http/tests/security/contentSecurityPolicy/sandbox-in-meta-tag-ignored.html to ensure that we ignore
the sandbox directive when delivered via an HTML meta element and log a message to the Web Inspector console.

Remove tests http/tests/security/contentSecurityPolicy/sandbox-{allow-scripts-subframe, empty, empty-subframe}.html
that are no longer meaningful now that we ignore the sandbox directive when delivered via an HTML meta element and
create analogous tests for when the sandbox directive is delivered via an HTTP header.

  • http/tests/security/contentSecurityPolicy/sandbox-allow-scripts-in-http-header2-expected.txt: Renamed from LayoutTests/http/tests/security/contentSecurityPolicy/sandbox-allow-scripts-expected.txt.
  • http/tests/security/contentSecurityPolicy/sandbox-allow-scripts-in-http-header2.php: Renamed from LayoutTests/http/tests/security/contentSecurityPolicy/sandbox-allow-scripts.html.
  • http/tests/security/contentSecurityPolicy/sandbox-allow-scripts-subframe-expected.txt: Removed.
  • http/tests/security/contentSecurityPolicy/sandbox-allow-scripts-subframe.html: Removed.

This test is no longer meaningful now that we ignore the sandbox directive when delivered via an HTML meta element.
An analogous test for when the directive is delivered via an HTTP header is http/tests/security/contentSecurityPolicysandbox-allow-scripts-in-http-header.html.

  • http/tests/security/contentSecurityPolicy/sandbox-empty-in-http-header-inherited-by-subframe-expected.txt: Added.
  • http/tests/security/contentSecurityPolicy/sandbox-empty-in-http-header-inherited-by-subframe.php: Added. Derived from test http/tests/security/contentSecurityPolicy/sandbox-empty-subframe.html.
  • http/tests/security/contentSecurityPolicy/sandbox-empty-in-http-header-expected.txt: Added.
  • http/tests/security/contentSecurityPolicy/sandbox-empty-in-http-header.php: Added. Derived from test http/tests/security/contentSecurityPolicy/sandbox-empty.html.
  • http/tests/security/contentSecurityPolicy/sandbox-empty-subframe-expected.txt: Removed.
  • http/tests/security/contentSecurityPolicy/sandbox-empty-subframe.html: Removed.

This test is no longer meaningful now that we ignore the sandbox directive when delivered via an HTML meta element.
The analogous test for when the directive is delivered via an HTTP header is http/tests/security/contentSecurityPolicy/sandbox-empty-in-http-header-inherited-by-subframe.php.

  • http/tests/security/contentSecurityPolicy/sandbox-empty-expected.txt: Removed.
  • http/tests/security/contentSecurityPolicy/sandbox-empty.html: Removed.

This test is no longer meaningful now that we ignore the sandbox directive when delivered via an HTML meta element.
The analogous test for when the directive is delivered via an HTTP header is http/tests/security/contentSecurityPolicy/sandbox-empty-in-http-header.php.

  • http/tests/security/contentSecurityPolicy/sandbox-in-meta-tag-ignored-expected.txt: Added.
  • http/tests/security/contentSecurityPolicy/sandbox-in-meta-tag-ignored.html: Added.
Location:
trunk
Files:
6 added
6 deleted
7 edited
2 moved

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r196872 r196874  
     12016-02-21  Daniel Bates  <dabates@apple.com>
     2
     3        CSP: sandbox directive should be ignored when contained in a policy defined via a meta element
     4        https://bugs.webkit.org/show_bug.cgi?id=154299
     5        <rdar://problem/24680433>
     6
     7        Reviewed by Brent Fulgham.
     8
     9        Add test http/tests/security/contentSecurityPolicy/sandbox-in-meta-tag-ignored.html to ensure that we ignore
     10        the sandbox directive when delivered via an HTML meta element and log a message to the Web Inspector console.
     11
     12        Remove tests http/tests/security/contentSecurityPolicy/sandbox-{allow-scripts-subframe, empty, empty-subframe}.html
     13        that are no longer meaningful now that we ignore the sandbox directive when delivered via an HTML meta element and
     14        create analogous tests for when the sandbox directive is delivered via an HTTP header.
     15
     16        * http/tests/security/contentSecurityPolicy/sandbox-allow-scripts-in-http-header2-expected.txt: Renamed from LayoutTests/http/tests/security/contentSecurityPolicy/sandbox-allow-scripts-expected.txt.
     17        * http/tests/security/contentSecurityPolicy/sandbox-allow-scripts-in-http-header2.php: Renamed from LayoutTests/http/tests/security/contentSecurityPolicy/sandbox-allow-scripts.html.
     18
     19        * http/tests/security/contentSecurityPolicy/sandbox-allow-scripts-subframe-expected.txt: Removed.
     20        * http/tests/security/contentSecurityPolicy/sandbox-allow-scripts-subframe.html: Removed.
     21        This test is no longer meaningful now that we ignore the sandbox directive when delivered via an HTML meta element.
     22        An analogous test for when the directive is delivered via an HTTP header is http/tests/security/contentSecurityPolicy//sandbox-allow-scripts-in-http-header.html.
     23
     24        * http/tests/security/contentSecurityPolicy/sandbox-empty-in-http-header-inherited-by-subframe-expected.txt: Added.
     25        * http/tests/security/contentSecurityPolicy/sandbox-empty-in-http-header-inherited-by-subframe.php: Added. Derived from test http/tests/security/contentSecurityPolicy/sandbox-empty-subframe.html.
     26
     27        * http/tests/security/contentSecurityPolicy/sandbox-empty-in-http-header-expected.txt: Added.
     28        * http/tests/security/contentSecurityPolicy/sandbox-empty-in-http-header.php: Added. Derived from test http/tests/security/contentSecurityPolicy/sandbox-empty.html.
     29
     30        * http/tests/security/contentSecurityPolicy/sandbox-empty-subframe-expected.txt: Removed.
     31        * http/tests/security/contentSecurityPolicy/sandbox-empty-subframe.html: Removed.
     32        This test is no longer meaningful now that we ignore the sandbox directive when delivered via an HTML meta element.
     33        The analogous test for when the directive is delivered via an HTTP header is http/tests/security/contentSecurityPolicy/sandbox-empty-in-http-header-inherited-by-subframe.php.
     34
     35        * http/tests/security/contentSecurityPolicy/sandbox-empty-expected.txt: Removed.
     36        * http/tests/security/contentSecurityPolicy/sandbox-empty.html: Removed.
     37        This test is no longer meaningful now that we ignore the sandbox directive when delivered via an HTML meta element.
     38        The analogous test for when the directive is delivered via an HTTP header is http/tests/security/contentSecurityPolicy/sandbox-empty-in-http-header.php.
     39
     40        * http/tests/security/contentSecurityPolicy/sandbox-in-meta-tag-ignored-expected.txt: Added.
     41        * http/tests/security/contentSecurityPolicy/sandbox-in-meta-tag-ignored.html: Added.
     42
    1432016-02-21  Commit Queue  <commit-queue@webkit.org>
    244
  • trunk/LayoutTests/http/tests/security/contentSecurityPolicy/sandbox-allow-scripts-in-http-header2.php

    r196873 r196874  
     1<?php
     2    header("Content-Security-Policy: sandbox allow-scripts");
     3?>
     4<!DOCTYPE html>
     5<html>
     6<body>
    17<script>
    28if (window.testRunner)
    39    testRunner.dumpAsText();
    410</script>
    5 <meta http-equiv="Content-Security-Policy" content="sandbox allow-scripts">
    611This test passes if it does alert pass.
    712<script>
    813alert('PASS');
    914</script>
     15</body>
     16</html>
  • trunk/Source/WebCore/ChangeLog

    r196872 r196874  
     12016-02-21  Daniel Bates  <dabates@apple.com>
     2
     3        CSP: sandbox directive should be ignored when contained in a policy defined via a meta element
     4        https://bugs.webkit.org/show_bug.cgi?id=154299
     5        <rdar://problem/24680433>
     6
     7        Reviewed by Brent Fulgham.
     8
     9        The Content Security Policy sandbox directive should only be honored when enforcing a policy
     10        defined via an HTTP header as per section sandbox of the Content Security Policy 2.0 spec.,
     11        <https://www.w3.org/TR/2015/CR-CSP2-20150721/>.
     12
     13        Currently we honor the sandbox directive when enforcing a policy defined either via an HTML
     14        meta element or an HTTP header. Instead we should only honor this directive when defined
     15        via an HTTP header and log a message to the Web Inspector console to explain that the directive
     16        was ignored as suggested in <https://www.w3.org/TR/2015/CR-CSP2-20150721/#delivery-html-meta-element>.
     17
     18        Tests: http/tests/security/contentSecurityPolicy/sandbox-allow-scripts-in-http-header2.php
     19               http/tests/security/contentSecurityPolicy/sandbox-empty-in-http-header-inherited-by-subframe.php
     20               http/tests/security/contentSecurityPolicy/sandbox-empty-in-http-header.php
     21               http/tests/security/contentSecurityPolicy/sandbox-in-meta-tag-ignored.html
     22
     23        * dom/Document.cpp:
     24        (WebCore::Document::processHttpEquiv): Substitute ContentSecurityPolicy::processHTTPEquiv() for
     25        ContentSecurityPolicy::didReceiveHeader() as the latter was made private.
     26        * page/csp/ContentSecurityPolicy.cpp:
     27        (WebCore::ContentSecurityPolicy::copyStateFrom): Updated as needed based on ContentSecurityPolicy::didReceiveHeader() change below.
     28        (WebCore::ContentSecurityPolicy::didReceiveHeaders): Ditto.
     29        (WebCore::ContentSecurityPolicy::didReceiveHeader): Modified to take argument of type ContentSecurityPolicy::PolicyFrom
     30        and pass it through to ContentSecurityPolicyDirectiveList::create().
     31        (WebCore::ContentSecurityPolicy::reportInvalidDirectiveInHTTPEquivMeta): Logs a message to the Web Inspector console
     32        that the specified directive was ignored because it was delivered via an HTML meta element.
     33        * page/csp/ContentSecurityPolicy.h: Made member function ContentSecurityPolicy::didReceiveHeader() private. Defined
     34        enum class PolicyFrom to represent the source of the Content Security Policy: HTTP equiv meta element, HTTP header, or
     35        inherited from another ContentSecurityPolicy object (this value is only used by ContentSecurityPolicy::copyStateFrom()).
     36        (WebCore::ContentSecurityPolicy::processHTTPEquiv): Added; turns around and calls ContentSecurityPolicy::didReceiveHeader().
     37        The name of this function better describes its purpose - to handle the processing of a Content Security Policy
     38        delivered via <meta http-equiv="Content-Security-Policy" content="...">.
     39        * page/csp/ContentSecurityPolicyDirectiveList.cpp:
     40        (WebCore::ContentSecurityPolicyDirectiveList::create): Modified to take argument of type ContentSecurityPolicy::PolicyFrom
     41        as pass it through to ContentSecurityPolicyDirectiveList::parse().
     42        (WebCore::ContentSecurityPolicyDirectiveList::parse): Modified to ignore the directive sandbox when the Content Security
     43        Policy came from an HTML meta element.
     44        * page/csp/ContentSecurityPolicyDirectiveList.h:
     45
    1462016-02-21  Commit Queue  <commit-queue@webkit.org>
    247
  • trunk/Source/WebCore/dom/Document.cpp

    r196807 r196874  
    32723272
    32733273    case HTTPHeaderName::ContentSecurityPolicy:
    3274         contentSecurityPolicy()->didReceiveHeader(content, ContentSecurityPolicyHeaderType::Enforce);
     3274        contentSecurityPolicy()->processHTTPEquiv(content, ContentSecurityPolicyHeaderType::Enforce);
    32753275        break;
    32763276
    32773277    case HTTPHeaderName::ContentSecurityPolicyReportOnly:
    3278         contentSecurityPolicy()->didReceiveHeader(content, ContentSecurityPolicyHeaderType::Report);
     3278        contentSecurityPolicy()->processHTTPEquiv(content, ContentSecurityPolicyHeaderType::Report);
    32793279        break;
    32803280
    32813281    case HTTPHeaderName::XWebKitCSP:
    3282         contentSecurityPolicy()->didReceiveHeader(content, ContentSecurityPolicyHeaderType::PrefixedEnforce);
     3282        contentSecurityPolicy()->processHTTPEquiv(content, ContentSecurityPolicyHeaderType::PrefixedEnforce);
    32833283        break;
    32843284
    32853285    case HTTPHeaderName::XWebKitCSPReportOnly:
    3286         contentSecurityPolicy()->didReceiveHeader(content, ContentSecurityPolicyHeaderType::PrefixedReport);
     3286        contentSecurityPolicy()->processHTTPEquiv(content, ContentSecurityPolicyHeaderType::PrefixedReport);
    32873287        break;
    32883288
  • trunk/Source/WebCore/page/csp/ContentSecurityPolicy.cpp

    r196664 r196874  
    7979    ASSERT(m_policies.isEmpty());
    8080    for (auto& policy : other->m_policies)
    81         didReceiveHeader(policy->header(), policy->headerType());
     81        didReceiveHeader(policy->header(), policy->headerType(), ContentSecurityPolicy::PolicyFrom::Inherited);
    8282}
    8383
    … …  
    9494{
    9595    for (auto& header : headers.m_headers)
    96         didReceiveHeader(header.first, header.second);
    97 }
    98 
    99 void ContentSecurityPolicy::didReceiveHeader(const String& header, ContentSecurityPolicyHeaderType type)
     96        didReceiveHeader(header.first, header.second, ContentSecurityPolicy::PolicyFrom::HTTPHeader);
     97}
     98
     99void ContentSecurityPolicy::didReceiveHeader(const String& header, ContentSecurityPolicyHeaderType type, ContentSecurityPolicy::PolicyFrom policyFrom)
    100100{
    101101    // RFC2616, section 4.2 specifies that headers appearing multiple times can
    … …  
    111111        // header1,header2 OR header1
    112112        //        ^                  ^
    113         std::unique_ptr<ContentSecurityPolicyDirectiveList> policy = ContentSecurityPolicyDirectiveList::create(*this, String(begin, position - begin), type);
     113        std::unique_ptr<ContentSecurityPolicyDirectiveList> policy = ContentSecurityPolicyDirectiveList::create(*this, String(begin, position - begin), type, policyFrom);
    114114        if (!policy->allowEval(0, ContentSecurityPolicy::ReportingStatus::SuppressReport))
    115115            m_lastPolicyEvalDisabledErrorMessage = policy->evalDisabledErrorMessage();
    … …  
    458458}
    459459
     460void ContentSecurityPolicy::reportInvalidDirectiveInHTTPEquivMeta(const String& directiveName) const
     461{
     462    logToConsole("The Content Security Policy directive '" + directiveName + "' is ignored when delivered via an HTML meta element.");
     463}
     464
    460465void ContentSecurityPolicy::reportInvalidDirectiveValueCharacter(const String& directiveName, const String& value) const
    461466{
  • trunk/Source/WebCore/page/csp/ContentSecurityPolicy.h

    r196582 r196874  
    6868    ReflectedXSSDisposition reflectedXSSDisposition() const;
    6969
     70    enum class PolicyFrom {
     71        HTTPEquivMeta,
     72        HTTPHeader,
     73        Inherited,
     74    };
    7075    ContentSecurityPolicyResponseHeaders responseHeaders() const;
    7176    void didReceiveHeaders(const ContentSecurityPolicyResponseHeaders&);
    72     void didReceiveHeader(const String&, ContentSecurityPolicyHeaderType);
     77    void processHTTPEquiv(const String& content, ContentSecurityPolicyHeaderType type) { didReceiveHeader(content, type, ContentSecurityPolicy::PolicyFrom::HTTPEquivMeta); }
    7378
    7479    enum class ReportingStatus {
    … …  
    124129    void reportInvalidReflectedXSS(const String&) const;
    125130    void reportInvalidDirectiveInReportOnlyMode(const String&) const;
     131    void reportInvalidDirectiveInHTTPEquivMeta(const String&) const;
    126132    void reportMissingReportURI(const String&) const;
    127133    void reportUnsupportedDirective(const String&) const;
    … …  
    137143    void applyPolicyToScriptExecutionContext();
    138144
     145    void didReceiveHeader(const String&, ContentSecurityPolicyHeaderType, ContentSecurityPolicy::PolicyFrom);
     146
    139147    ScriptExecutionContext* m_scriptExecutionContext { nullptr };
    140148    std::unique_ptr<ContentSecurityPolicySource> m_selfSource;
  • trunk/Source/WebCore/page/csp/ContentSecurityPolicyDirectiveList.cpp

    r196582 r196874  
    116116}
    117117
    118 std::unique_ptr<ContentSecurityPolicyDirectiveList> ContentSecurityPolicyDirectiveList::create(ContentSecurityPolicy& policy, const String& header, ContentSecurityPolicyHeaderType type)
     118std::unique_ptr<ContentSecurityPolicyDirectiveList> ContentSecurityPolicyDirectiveList::create(ContentSecurityPolicy& policy, const String& header, ContentSecurityPolicyHeaderType type, ContentSecurityPolicy::PolicyFrom from)
    119119{
    120120    auto directives = std::make_unique<ContentSecurityPolicyDirectiveList>(policy, type);
    121     directives->parse(header);
     121    directives->parse(header, from);
    122122
    123123    if (!directives->checkEval(directives->operativeDirective(directives->m_scriptSrc.get()))) {
    … …  
    390390// directive-list    = [ directive *( ";" [ directive ] ) ]
    391391//
    392 void ContentSecurityPolicyDirectiveList::parse(const String& policy)
     392void ContentSecurityPolicyDirectiveList::parse(const String& policy, ContentSecurityPolicy::PolicyFrom policyFrom)
    393393{
    394394    m_header = policy;
    … …  
    407407        if (parseDirective(directiveBegin, position, name, value)) {
    408408            ASSERT(!name.isEmpty());
    409             addDirective(name, value);
     409            switch (policyFrom) {
     410            case ContentSecurityPolicy::PolicyFrom::HTTPEquivMeta:
     411                // FIXME: We also need to ignore directive report-uri (https://bugs.webkit.org/show_bug.cgi?id=154307).
     412                if (equalLettersIgnoringASCIICase(name, sandbox)) {
     413                    m_policy.reportInvalidDirectiveInHTTPEquivMeta(name);
     414                    break;
     415                }
     416                FALLTHROUGH;
     417            default:
     418                addDirective(name, value);
     419                break;
     420            }
    410421        }
    411422
  • trunk/Source/WebCore/page/csp/ContentSecurityPolicyDirectiveList.h

    r196526 r196874  
    4242    WTF_MAKE_NONCOPYABLE(ContentSecurityPolicyDirectiveList)
    4343public:
    44     static std::unique_ptr<ContentSecurityPolicyDirectiveList> create(ContentSecurityPolicy&, const String&, ContentSecurityPolicyHeaderType);
     44    static std::unique_ptr<ContentSecurityPolicyDirectiveList> create(ContentSecurityPolicy&, const String&, ContentSecurityPolicyHeaderType, ContentSecurityPolicy::PolicyFrom);
    4545    ContentSecurityPolicyDirectiveList(ContentSecurityPolicy&, ContentSecurityPolicyHeaderType);
    4646
    … …  
    7373
    7474private:
    75     void parse(const String&);
     75    void parse(const String&, ContentSecurityPolicy::PolicyFrom);
    7676
    7777    bool parseDirective(const UChar* begin, const UChar* end, String& name, String& value);
Note: See TracChangeset for help on using the changeset viewer.