Changeset 206009 in webkit


Ignore:
Timestamp:
Sep 16, 2016 12:33:44 AM (8 years ago)
Author:
commit-queue@webkit.org
Message:

[Fetch API] Referrer and Origin header should not be considered as safe request headers
https://bugs.webkit.org/show_bug.cgi?id=161902

Patch by Youenn Fablet <youenn@apple.com> on 2016-09-16
Reviewed by Sam Weinig.

LayoutTests/imported/w3c:

  • web-platform-tests/fetch/api/cors/cors-preflight-referrer-expected.txt:
  • web-platform-tests/fetch/api/cors/cors-preflight-referrer-worker-expected.txt:
  • web-platform-tests/fetch/api/cors/cors-preflight-referrer.js:

(corsPreflightReferrer): Adding check of the preflight Access-Control-Request-Headers header value.
Added new tests to check for non-default referrer values.

Source/WebCore:

Test: http/tests/fetch/fetch-cors-with-referrer.html and updated WPT tests.

Removing Origin and Referrer from safe request headers.
Making referrer header setting after preflight for fetch API code path.

Ensuring that no ThreadableLoader client sets Origin or Referrer headers of the ResourceRequest, as they should use the proper mechanisms for that.

Handling no-referrer referrer special value by setting the referrer-policy to NoReferrer in FetchLoader.

  • Modules/fetch/FetchLoader.cpp:

(WebCore::FetchLoader::start): Computing referrer value and handling special "client"and "no-referrer" cases.
Passing the value directly to ThreadableLoader.

  • Modules/fetch/FetchRequest.cpp:

(WebCore::FetchRequest::internalRequest): Removing setting of ResourceRequest referrer header.
(WebCore::FetchRequest::clone): Removing obsolete FIXME.

  • Modules/fetch/FetchRequest.h:
  • loader/CrossOriginAccessControl.cpp:

(WebCore::isOnAccessControlSimpleRequestHeaderWhitelist): Removing Origin and Referrer headers.

  • loader/DocumentThreadableLoader.cpp:

(WebCore::DocumentThreadableLoader::create): Updated to take a referrer as parameter.
(WebCore::DocumentThreadableLoader::DocumentThreadableLoader): Ditto.

  • loader/DocumentThreadableLoader.h: Ditto.
  • loader/ThreadableLoader.cpp: Ditto.

(WebCore::ThreadableLoader::create): Ditto.

  • loader/ThreadableLoader.h: Ditto.
  • loader/WorkerThreadableLoader.cpp: Ditto.

(WebCore::WorkerThreadableLoader::WorkerThreadableLoader): Ditto.
(WebCore::WorkerThreadableLoader::loadResourceSynchronously): Ditto.

  • loader/WorkerThreadableLoader.h: Ditto.

(WebCore::WorkerThreadableLoader::create): Ditto.

  • platform/network/ResourceRequestBase.cpp:

(WebCore::ResourceRequestBase::hasHTTPReferrer): Added to enable asserting that no threadable loader client sets the referrer in the request.

  • platform/network/ResourceRequestBase.h:

LayoutTests:

  • http/tests/fetch/fetch-cors-with-referrer-expected.txt: Added.
  • http/tests/fetch/fetch-cors-with-referrer.html: Added.
Location:
trunk
Files:
2 added
18 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r206001 r206009  
     12016-09-16  Youenn Fablet  <youenn@apple.com>
     2
     3        [Fetch API] Referrer and Origin header should not be considered as safe request headers
     4        https://bugs.webkit.org/show_bug.cgi?id=161902
     5
     6        Reviewed by Sam Weinig.
     7
     8        * http/tests/fetch/fetch-cors-with-referrer-expected.txt: Added.
     9        * http/tests/fetch/fetch-cors-with-referrer.html: Added.
     10
    1112016-09-13  Jer Noble  <jer.noble@apple.com>
    212
  • trunk/LayoutTests/imported/w3c/ChangeLog

    r205923 r206009  
     12016-09-16  Youenn Fablet  <youenn@apple.com>
     2
     3        [Fetch API] Referrer and Origin header should not be considered as safe request headers
     4        https://bugs.webkit.org/show_bug.cgi?id=161902
     5
     6        Reviewed by Sam Weinig.
     7
     8        * web-platform-tests/fetch/api/cors/cors-preflight-referrer-expected.txt:
     9        * web-platform-tests/fetch/api/cors/cors-preflight-referrer-worker-expected.txt:
     10        * web-platform-tests/fetch/api/cors/cors-preflight-referrer.js:
     11        (corsPreflightReferrer): Adding check of the preflight Access-Control-Request-Headers header value.
     12        Added new tests to check for non-default referrer values.
     13
    1142016-09-14  Chris Dumez  <cdumez@apple.com>
    215
  • trunk/LayoutTests/imported/w3c/web-platform-tests/fetch/api/cors/cors-preflight-referrer-expected.txt

    r204019 r206009  
    11
    2 PASS Referrer policy: no-referrer
    3 PASS Referrer policy: ""
    4 PASS Referrer policy: origin
    5 PASS Referrer policy: origin-when-cross-origin
    6 PASS Referrer policy: unsafe-url
     2PASS Referrer policy: no-referrer ('myreferrer' referrer)
     3PASS Referrer policy: no-referrer (default referrer)
     4PASS Referrer policy: "" ('myreferrer' referrer)
     5PASS Referrer policy: "" (default referrer)
     6PASS Referrer policy: origin ('myreferrer' referrer)
     7PASS Referrer policy: origin (default referrer)
     8PASS Referrer policy: origin-when-cross-origin ('myreferrer' referrer)
     9PASS Referrer policy: origin-when-cross-origin (default referrer)
     10PASS Referrer policy: unsafe-url ('myreferrer' referrer)
     11PASS Referrer policy: unsafe-url (default referrer)
    712
  • trunk/LayoutTests/imported/w3c/web-platform-tests/fetch/api/cors/cors-preflight-referrer-worker-expected.txt

    r204019 r206009  
    11
    2 PASS Referrer policy: no-referrer
    3 PASS Referrer policy: ""
    4 PASS Referrer policy: origin
    5 PASS Referrer policy: origin-when-cross-origin
    6 PASS Referrer policy: unsafe-url
     2PASS Referrer policy: no-referrer ('myreferrer' referrer)
     3PASS Referrer policy: no-referrer (default referrer)
     4PASS Referrer policy: "" ('myreferrer' referrer)
     5PASS Referrer policy: "" (default referrer)
     6PASS Referrer policy: origin ('myreferrer' referrer)
     7PASS Referrer policy: origin (default referrer)
     8PASS Referrer policy: origin-when-cross-origin ('myreferrer' referrer)
     9PASS Referrer policy: origin-when-cross-origin (default referrer)
     10PASS Referrer policy: unsafe-url ('myreferrer' referrer)
     11PASS Referrer policy: unsafe-url (default referrer)
    712
  • trunk/LayoutTests/imported/w3c/web-platform-tests/fetch/api/cors/cors-preflight-referrer.js

    r205743 r206009  
    66}
    77
    8 function corsPreflightReferrer(desc, corsUrl, referrerPolicy, expectedReferrer) {
     8function corsPreflightReferrer(desc, corsUrl, referrerPolicy, referrer, expectedReferrer) {
    99  var uuid_token = token();
    1010  var url = corsUrl;
    1111  var urlParameters = "?token=" + uuid_token + "&max_age=0";
    1212  var requestInit = {"mode": "cors", "referrerPolicy": referrerPolicy};
     13
     14  if (referrer)
     15      requestInit.referrer = referrer;
    1316
    1417  /* Force preflight */
     
    2427        assert_equals(resp.headers.get("x-preflight-referrer"), expectedReferrer, "Preflight's referrer is correct");
    2528        assert_equals(resp.headers.get("x-referrer"), expectedReferrer, "Request's referrer is correct");
     29        assert_equals(resp.headers.get("x-control-request-headers"), "", "Access-Control-Allow-Headers value");
    2630      });
    2731    });
    28   }, desc);
     32  }, desc + (referrer ? " (default referrer)" : " ('myreferrer' referrer)"));
    2933}
    30 
    3134var corsUrl = get_host_info().HTTP_REMOTE_ORIGIN  + dirname(location.pathname) + RESOURCES_DIR + "preflight.py";
    3235var origin = get_host_info().HTTP_ORIGIN + "/";
    3336
    34 corsPreflightReferrer("Referrer policy: no-referrer", corsUrl, "no-referrer", "");
    35 corsPreflightReferrer("Referrer policy: \"\"", corsUrl, "", location.toString())
     37corsPreflightReferrer("Referrer policy: no-referrer", corsUrl, "no-referrer", undefined, "");
     38corsPreflightReferrer("Referrer policy: no-referrer", corsUrl, "no-referrer", "myreferrer", "");
    3639
    37 corsPreflightReferrer("Referrer policy: origin", corsUrl, "origin", origin);
    38 corsPreflightReferrer("Referrer policy: origin-when-cross-origin", corsUrl, "origin-when-cross-origin", origin);
    39 corsPreflightReferrer("Referrer policy: unsafe-url", corsUrl, "unsafe-url", location.toString());
     40corsPreflightReferrer("Referrer policy: \"\"", corsUrl, "", undefined, location.toString())
     41corsPreflightReferrer("Referrer policy: \"\"", corsUrl, "", "myreferrer", new URL("myreferrer", location).toString());
     42
     43corsPreflightReferrer("Referrer policy: origin", corsUrl, "origin", undefined, origin);
     44corsPreflightReferrer("Referrer policy: origin", corsUrl, "origin", "myreferrer", origin);
     45
     46corsPreflightReferrer("Referrer policy: origin-when-cross-origin", corsUrl, "origin-when-cross-origin", undefined, origin);
     47corsPreflightReferrer("Referrer policy: origin-when-cross-origin", corsUrl, "origin-when-cross-origin", "myreferrer", origin);
     48
     49corsPreflightReferrer("Referrer policy: unsafe-url", corsUrl, "unsafe-url", undefined, location.toString());
     50corsPreflightReferrer("Referrer policy: unsafe-url", corsUrl, "unsafe-url", "myreferrer", new URL("myreferrer", location).toString());
    4051
    4152done();
  • trunk/Source/WebCore/ChangeLog

    r206007 r206009  
     12016-09-16  Youenn Fablet  <youenn@apple.com>
     2
     3        [Fetch API] Referrer and Origin header should not be considered as safe request headers
     4        https://bugs.webkit.org/show_bug.cgi?id=161902
     5
     6        Reviewed by Sam Weinig.
     7
     8        Test: http/tests/fetch/fetch-cors-with-referrer.html and updated WPT tests.
     9
     10        Removing Origin and Referrer from safe request headers.
     11        Making referrer header setting after preflight for fetch API code path.
     12
     13        Ensuring that no ThreadableLoader client sets Origin or Referrer headers of the ResourceRequest, as they should use the proper mechanisms for that.
     14
     15        Handling no-referrer referrer special value by setting the referrer-policy to NoReferrer in FetchLoader.
     16
     17        * Modules/fetch/FetchLoader.cpp:
     18        (WebCore::FetchLoader::start): Computing referrer value and handling special "client"and "no-referrer" cases.
     19        Passing the value directly to ThreadableLoader.
     20        * Modules/fetch/FetchRequest.cpp:
     21        (WebCore::FetchRequest::internalRequest): Removing setting of ResourceRequest referrer header.
     22        (WebCore::FetchRequest::clone): Removing obsolete FIXME.
     23        * Modules/fetch/FetchRequest.h:
     24        * loader/CrossOriginAccessControl.cpp:
     25        (WebCore::isOnAccessControlSimpleRequestHeaderWhitelist): Removing Origin and Referrer headers.
     26        * loader/DocumentThreadableLoader.cpp:
     27        (WebCore::DocumentThreadableLoader::create): Updated to take a referrer as parameter.
     28        (WebCore::DocumentThreadableLoader::DocumentThreadableLoader): Ditto.
     29        * loader/DocumentThreadableLoader.h: Ditto.
     30        * loader/ThreadableLoader.cpp: Ditto.
     31        (WebCore::ThreadableLoader::create): Ditto.
     32        * loader/ThreadableLoader.h: Ditto.
     33        * loader/WorkerThreadableLoader.cpp: Ditto.
     34        (WebCore::WorkerThreadableLoader::WorkerThreadableLoader): Ditto.
     35        (WebCore::WorkerThreadableLoader::loadResourceSynchronously): Ditto.
     36        * loader/WorkerThreadableLoader.h: Ditto.
     37        (WebCore::WorkerThreadableLoader::create): Ditto.
     38        * platform/network/ResourceRequestBase.cpp:
     39        (WebCore::ResourceRequestBase::hasHTTPReferrer): Added to enable asserting that no threadable loader client sets the referrer in the request.
     40        * platform/network/ResourceRequestBase.h:
     41
    1422016-09-15  Dave Hyatt  <hyatt@apple.com>
    243
  • trunk/Source/WebCore/Modules/fetch/FetchLoader.cpp

    r205265 r206009  
    9393    }
    9494
    95     m_loader = ThreadableLoader::create(context, *this, WTFMove(fetchRequest), options);
     95    String referrer = request.internalRequestReferrer();
     96    if (referrer == "no-referrer") {
     97        options.referrerPolicy = FetchOptions::ReferrerPolicy::NoReferrer;
     98        referrer = String();
     99    } else
     100        referrer = (referrer == "client") ? context.url().strippedForUseAsReferrer() : URL(context.url(), referrer).strippedForUseAsReferrer();
     101
     102    m_loader = ThreadableLoader::create(context, *this, WTFMove(fetchRequest), options, WTFMove(referrer));
    96103    m_isStarted = m_loader;
    97104}
  • trunk/Source/WebCore/Modules/fetch/FetchRequest.cpp

    r205253 r206009  
    305305    request.setHTTPBody(body().bodyForInternalRequest(*scriptExecutionContext()));
    306306
    307     // FIXME: Support no-referrer and client. Ensure this case-sensitive comparison is ok.
    308     if (m_internalRequest.referrer != "no-referrer" && m_internalRequest.referrer != "client")
    309         request.setHTTPReferrer(URL(URL(), m_internalRequest.referrer).strippedForUseAsReferrer());
    310 
    311307    return request;
    312308}
     
    319315    }
    320316
    321     // FIXME: Validate body teeing.
    322317    return adoptRef(*new FetchRequest(context, FetchBody(m_body), FetchHeaders::create(m_headers.get()), FetchRequest::InternalRequest(m_internalRequest)));
    323318}
  • trunk/Source/WebCore/Modules/fetch/FetchRequest.h

    r203675 r206009  
    9393    ResourceRequest internalRequest() const;
    9494
     95    const String& internalRequestReferrer() const { return m_internalRequest.referrer; }
     96
    9597private:
    9698    FetchRequest(ScriptExecutionContext&, FetchBody&&, Ref<FetchHeaders>&&, InternalRequest&&);
  • trunk/Source/WebCore/loader/CrossOriginAccessControl.cpp

    r203899 r206009  
    5252    case HTTPHeaderName::AcceptLanguage:
    5353    case HTTPHeaderName::ContentLanguage:
    54     case HTTPHeaderName::Origin:
    55     case HTTPHeaderName::Referer:
    5654        return true;
    5755    case HTTPHeaderName::ContentType: {
  • trunk/Source/WebCore/loader/DocumentThreadableLoader.cpp

    r205481 r206009  
    7777}
    7878
    79 RefPtr<DocumentThreadableLoader> DocumentThreadableLoader::create(Document& document, ThreadableLoaderClient& client, ResourceRequest&& request, const ThreadableLoaderOptions& options)
    80 {
    81     return create(document, client, WTFMove(request), options, nullptr, nullptr, String());
     79RefPtr<DocumentThreadableLoader> DocumentThreadableLoader::create(Document& document, ThreadableLoaderClient& client, ResourceRequest&& request, const ThreadableLoaderOptions& options, String&& referrer)
     80{
     81    return create(document, client, WTFMove(request), options, nullptr, nullptr, WTFMove(referrer));
    8282}
    8383
     
    9393    , m_contentSecurityPolicy(WTFMove(contentSecurityPolicy))
    9494{
    95     // Setting an outgoing referer is only supported in the async code path.
    96     ASSERT(m_async || request.httpReferrer().isEmpty());
     95    // Setting a referrer header is only supported in the async code path.
     96    ASSERT(m_async || m_referrer.isEmpty());
     97
     98    // Referrer and Origin headers should be set after the preflight if any.
     99    ASSERT(!request.hasHTTPReferrer() && !request.hasHTTPOrigin());
    97100
    98101    ASSERT_WITH_SECURITY_IMPLICATION(isAllowedByContentSecurityPolicy(request.url()));
  • trunk/Source/WebCore/loader/DocumentThreadableLoader.h

    r204693 r206009  
    5050
    5151        static RefPtr<DocumentThreadableLoader> create(Document&, ThreadableLoaderClient&, ResourceRequest&&, const ThreadableLoaderOptions&, RefPtr<SecurityOrigin>&&, std::unique_ptr<ContentSecurityPolicy>&&, String&& referrer);
    52         static RefPtr<DocumentThreadableLoader> create(Document&, ThreadableLoaderClient&, ResourceRequest&&, const ThreadableLoaderOptions&);
     52        static RefPtr<DocumentThreadableLoader> create(Document&, ThreadableLoaderClient&, ResourceRequest&&, const ThreadableLoaderOptions&, String&& referrer = String());
    5353
    5454        virtual ~DocumentThreadableLoader();
  • trunk/Source/WebCore/loader/ThreadableLoader.cpp

    r205265 r206009  
    6060}
    6161
    62 RefPtr<ThreadableLoader> ThreadableLoader::create(ScriptExecutionContext& context, ThreadableLoaderClient& client, ResourceRequest&& request, const ThreadableLoaderOptions& options)
     62RefPtr<ThreadableLoader> ThreadableLoader::create(ScriptExecutionContext& context, ThreadableLoaderClient& client, ResourceRequest&& request, const ThreadableLoaderOptions& options, String&& referrer)
    6363{
    6464    if (is<WorkerGlobalScope>(context))
    65         return WorkerThreadableLoader::create(downcast<WorkerGlobalScope>(context), client, WorkerRunLoop::defaultMode(), WTFMove(request), options);
     65        return WorkerThreadableLoader::create(downcast<WorkerGlobalScope>(context), client, WorkerRunLoop::defaultMode(), WTFMove(request), options, referrer);
    6666
    67     return DocumentThreadableLoader::create(downcast<Document>(context), client, WTFMove(request), options);
     67    return DocumentThreadableLoader::create(downcast<Document>(context), client, WTFMove(request), options, WTFMove(referrer));
    6868}
    6969
  • trunk/Source/WebCore/loader/ThreadableLoader.h

    r205265 r206009  
    8181    public:
    8282        static void loadResourceSynchronously(ScriptExecutionContext&, ResourceRequest&&, ThreadableLoaderClient&, const ThreadableLoaderOptions&);
    83         static RefPtr<ThreadableLoader> create(ScriptExecutionContext&, ThreadableLoaderClient&, ResourceRequest&&, const ThreadableLoaderOptions&);
     83        static RefPtr<ThreadableLoader> create(ScriptExecutionContext&, ThreadableLoaderClient&, ResourceRequest&&, const ThreadableLoaderOptions&, String&& referrer = String());
    8484
    8585        virtual void cancel() = 0;
  • trunk/Source/WebCore/loader/WorkerThreadableLoader.cpp

    r205265 r206009  
    5151static const char loadResourceSynchronouslyMode[] = "loadResourceSynchronouslyMode";
    5252
    53 WorkerThreadableLoader::WorkerThreadableLoader(WorkerGlobalScope& workerGlobalScope, ThreadableLoaderClient& client, const String& taskMode, ResourceRequest&& request, const ThreadableLoaderOptions& options)
     53WorkerThreadableLoader::WorkerThreadableLoader(WorkerGlobalScope& workerGlobalScope, ThreadableLoaderClient& client, const String& taskMode, ResourceRequest&& request, const ThreadableLoaderOptions& options, const String& referrer)
    5454    : m_workerGlobalScope(workerGlobalScope)
    5555    , m_workerClientWrapper(ThreadableLoaderClientWrapper::create(client))
    56     , m_bridge(*new MainThreadBridge(m_workerClientWrapper.get(), workerGlobalScope.thread().workerLoaderProxy(), taskMode, WTFMove(request), options, workerGlobalScope.url().strippedForUseAsReferrer(), workerGlobalScope.securityOrigin(), workerGlobalScope.contentSecurityPolicy()))
     56    , m_bridge(*new MainThreadBridge(m_workerClientWrapper.get(), workerGlobalScope.thread().workerLoaderProxy(), taskMode, WTFMove(request), options, referrer.isEmpty() ? workerGlobalScope.url().strippedForUseAsReferrer() : referrer, workerGlobalScope.securityOrigin(), workerGlobalScope.contentSecurityPolicy()))
    5757{
    5858}
     
    7171    mode.append(String::number(runLoop.createUniqueId()));
    7272
    73     RefPtr<WorkerThreadableLoader> loader = WorkerThreadableLoader::create(workerGlobalScope, client, mode, WTFMove(request), options);
     73    RefPtr<WorkerThreadableLoader> loader = WorkerThreadableLoader::create(workerGlobalScope, client, mode, WTFMove(request), options, String());
    7474    MessageQueueWaitResult result = MessageQueueMessageReceived;
    7575    while (!loader->done() && result != MessageQueueTerminated)
  • trunk/Source/WebCore/loader/WorkerThreadableLoader.h

    r204019 r206009  
    5151    public:
    5252        static void loadResourceSynchronously(WorkerGlobalScope&, ResourceRequest&&, ThreadableLoaderClient&, const ThreadableLoaderOptions&);
    53         static Ref<WorkerThreadableLoader> create(WorkerGlobalScope& workerGlobalScope, ThreadableLoaderClient& client, const String& taskMode, ResourceRequest&& request, const ThreadableLoaderOptions& options)
     53        static Ref<WorkerThreadableLoader> create(WorkerGlobalScope& workerGlobalScope, ThreadableLoaderClient& client, const String& taskMode, ResourceRequest&& request, const ThreadableLoaderOptions& options, const String& referrer)
    5454        {
    55             return adoptRef(*new WorkerThreadableLoader(workerGlobalScope, client, taskMode, WTFMove(request), options));
     55            return adoptRef(*new WorkerThreadableLoader(workerGlobalScope, client, taskMode, WTFMove(request), options, referrer));
    5656        }
    5757
     
    121121        };
    122122
    123         WorkerThreadableLoader(WorkerGlobalScope&, ThreadableLoaderClient&, const String& taskMode, ResourceRequest&&, const ThreadableLoaderOptions&);
     123        WorkerThreadableLoader(WorkerGlobalScope&, ThreadableLoaderClient&, const String& taskMode, ResourceRequest&&, const ThreadableLoaderOptions&, const String& referrer);
    124124
    125125        Ref<WorkerGlobalScope> m_workerGlobalScope;
  • trunk/Source/WebCore/platform/network/ResourceRequestBase.cpp

    r203815 r206009  
    289289}
    290290
     291bool ResourceRequestBase::hasHTTPReferrer() const
     292{
     293    return m_httpHeaderFields.contains(HTTPHeaderName::Referer);
     294}
     295
    291296void ResourceRequestBase::setHTTPReferrer(const String& httpReferrer)
    292297{
  • trunk/Source/WebCore/platform/network/ResourceRequestBase.h

    r205269 r206009  
    9999
    100100    WEBCORE_EXPORT String httpReferrer() const;
     101    bool hasHTTPReferrer() const;
    101102    WEBCORE_EXPORT void setHTTPReferrer(const String&);
    102103    WEBCORE_EXPORT void clearHTTPReferrer();
Note: See TracChangeset for help on using the changeset viewer.