Reject invalid requests with "same-origin" credentials mode
Reject invalid use found in
https://crrev.com/c/chromium/src/+/1695341/.
Bug: 862184
Change-Id: I174d90bec44b8f077168a446b671a76ad38f0317
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1699587
Commit-Queue: Yutaka Hirano <yhirano@chromium.org>
Reviewed-by: David Benjamin <davidben@chromium.org>
Reviewed-by: Tom Sepez <tsepez@chromium.org>
Reviewed-by: Takashi Toyoshima <toyoshim@chromium.org>
Cr-Commit-Position: refs/heads/master@{#682188}
diff --git a/services/network/cors/cors_url_loader_factory.cc b/services/network/cors/cors_url_loader_factory.cc
index 74fb33be..ebda635 100644
--- a/services/network/cors/cors_url_loader_factory.cc
+++ b/services/network/cors/cors_url_loader_factory.cc
@@ -207,6 +207,26 @@
LogConcerningRequestHeaders(request.headers,
false /* added_during_redirect */);
+ // Specifying CredentialsMode::kSameOrigin without an initiator origin doesn't
+ // make sense.
+ if (request.credentials_mode == mojom::CredentialsMode::kSameOrigin &&
+ !request.request_initiator) {
+ LOG(WARNING) << "same-origin credentials mode without initiator";
+ mojo::ReportBadMessage(
+ "CorsURLLoaderFactory: same-origin credentials mode without initiator");
+ return false;
+ }
+
+ // We only support |kInclude| credentials mode with navigations. See also:
+ // a note at https://fetch.spec.whatwg.org/#concept-request-credentials-mode.
+ if (request.credentials_mode != mojom::CredentialsMode::kInclude &&
+ request.mode == mojom::RequestMode::kNavigate) {
+ LOG(WARNING) << "unsupported credentials mode on a navigation request";
+ mojo::ReportBadMessage(
+ "CorsURLLoaderFactory: unsupported credentials mode on navigation");
+ return false;
+ }
+
// TODO(yhirano): If the request mode is "no-cors", the redirect mode should
// be "follow".
return true;
diff --git a/services/network/cors/cors_url_loader_unittest.cc b/services/network/cors/cors_url_loader_unittest.cc
index 1b05d77..95962de2 100644
--- a/services/network/cors/cors_url_loader_unittest.cc
+++ b/services/network/cors/cors_url_loader_unittest.cc
@@ -1705,6 +1705,75 @@
EXPECT_EQ(net::ERR_INVALID_ARGUMENT, client().completion_status().error_code);
}
+TEST_F(CorsURLLoaderTest, SameOriginCredentialsModeWithoutInitiator) {
+ ResourceRequest request;
+ request.mode = mojom::RequestMode::kNoCors;
+ request.credentials_mode = mojom::CredentialsMode::kSameOrigin;
+ request.url = GURL("http://example.com/");
+ request.request_initiator = base::nullopt;
+
+ BadMessageTestHelper bad_message_helper;
+ CreateLoaderAndStart(request);
+ RunUntilComplete();
+
+ EXPECT_FALSE(IsNetworkLoaderStarted());
+ EXPECT_FALSE(client().has_received_redirect());
+ EXPECT_FALSE(client().has_received_response());
+ EXPECT_TRUE(client().has_received_completion());
+ EXPECT_EQ(net::ERR_INVALID_ARGUMENT, client().completion_status().error_code);
+ EXPECT_THAT(bad_message_helper.bad_message_reports(),
+ ::testing::ElementsAre("CorsURLLoaderFactory: same-origin "
+ "credentials mode without initiator"));
+}
+
+TEST_F(CorsURLLoaderTest, SameOriginCredentialsModeOnNavigation) {
+ ResetFactory(base::nullopt /* initiator */, mojom::kBrowserProcessId);
+
+ ResourceRequest request;
+ request.mode = mojom::RequestMode::kNavigate;
+ request.credentials_mode = mojom::CredentialsMode::kSameOrigin;
+ request.url = GURL("http://example.com/");
+ request.request_initiator = url::Origin::Create(request.url);
+
+ BadMessageTestHelper bad_message_helper;
+ CreateLoaderAndStart(request);
+ RunUntilComplete();
+
+ EXPECT_FALSE(IsNetworkLoaderStarted());
+ EXPECT_FALSE(client().has_received_redirect());
+ EXPECT_FALSE(client().has_received_response());
+ EXPECT_TRUE(client().has_received_completion());
+ EXPECT_EQ(net::ERR_INVALID_ARGUMENT, client().completion_status().error_code);
+ EXPECT_THAT(
+ bad_message_helper.bad_message_reports(),
+ ::testing::ElementsAre(
+ "CorsURLLoaderFactory: unsupported credentials mode on navigation"));
+}
+
+TEST_F(CorsURLLoaderTest, OmitCredentialsModeOnNavigation) {
+ ResetFactory(base::nullopt /* initiator */, mojom::kBrowserProcessId);
+
+ ResourceRequest request;
+ request.mode = mojom::RequestMode::kNavigate;
+ request.credentials_mode = mojom::CredentialsMode::kOmit;
+ request.url = GURL("http://example.com/");
+ request.request_initiator = url::Origin::Create(request.url);
+
+ BadMessageTestHelper bad_message_helper;
+ CreateLoaderAndStart(request);
+ RunUntilComplete();
+
+ EXPECT_FALSE(IsNetworkLoaderStarted());
+ EXPECT_FALSE(client().has_received_redirect());
+ EXPECT_FALSE(client().has_received_response());
+ EXPECT_TRUE(client().has_received_completion());
+ EXPECT_EQ(net::ERR_INVALID_ARGUMENT, client().completion_status().error_code);
+ EXPECT_THAT(
+ bad_message_helper.bad_message_reports(),
+ ::testing::ElementsAre(
+ "CorsURLLoaderFactory: unsupported credentials mode on navigation"));
+}
+
} // namespace
} // namespace cors
diff --git a/services/network/public/mojom/url_loader.mojom b/services/network/public/mojom/url_loader.mojom
index ec053d34..03e054e 100644
--- a/services/network/public/mojom/url_loader.mojom
+++ b/services/network/public/mojom/url_loader.mojom
@@ -238,8 +238,8 @@
// https://fetch.spec.whatwg.org/#concept-request-credentials-mode
// Controls whether credentials are attached to this request.
- // Currently kSameOrigin does not work with |mode: kNavigate|.
- // TODO(yhirano): Fix this.
+ // |kSameOrigin| credentials mode requires a non-null |request_initiator|.
+ // When |mode| is |kNavigate|, this needs to be |kInclude|.
CredentialsMode credentials_mode;
// https://fetch.spec.whatwg.org/#concept-request-redirect-mode