Chrome · BackgroundFetch
CVE-2026-87453
Logic Error in BackgroundFetch
Overview
Medium
Severity
—
CVSS
No
Exploited ITW
Fixed
Fix Status
Changed Functions
| Function | Change | Notes |
|---|---|---|
forcontent/browser/background_fetch/background_fetch_service_impl.cc |
modified | |
ifcontent/browser/background_fetch/background_fetch_service_impl.cc |
modified | |
TEST_Fcontent/browser/background_fetch/background_fetch_service_unittest.cc |
modified |
Files Changed
content/browser/background_fetch/background_fetch_service_impl.cccontent/browser/background_fetch/background_fetch_service_unittest.cc
Patch
From 8046f4cc56ed8aebe6c9aa4838f5ae6b1ba07764 Mon Sep 17 00:00:00 2001 From: Nidhi Jaju <[email protected]> Date: Fri, 07 Aug 2026 04:08:03 -0700 Subject: [PATCH] [BackgroundFetch] Validate request URL scheme in the browser BackgroundFetchManager in the renderer rejects request URLs that do not use a HTTP(S) scheme. Mirror that check in BackgroundFetchServiceImpl::ValidateRequests() so the browser process does not forward such requests to the download subsystem, which would otherwise treat them as trusted browser requests. Bug: 495444970 Change-Id: If25e925d5d7e19a9d53453971933dc0d10d9a4a1 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/8200209 Commit-Queue: Peter Beverloo <[email protected]> Auto-Submit: Nidhi Jaju <[email protected]> Reviewed-by: Peter Beverloo <[email protected]> Cr-Commit-Position: refs/heads/main@{#1675631} --- diff --git a/content/browser/background_fetch/background_fetch_service_impl.cc b/content/browser/background_fetch/background_fetch_service_impl.cc index f2e3d9f..97f0ba9 100644 --- a/content/browser/background_fetch/background_fetch_service_impl.cc +++ b/content/browser/background_fetch/background_fetch_service_impl.cc @@ -222,6 +222,24 @@ return false; } + // Ensure all requests are valid and use the HTTP or HTTPS scheme. + for (const auto& request : requests) { + if (!request) { + mojo::ReportBadMessage("Null request"); + return false; + } + + if (!request->url.is_valid()) { + mojo::ReportBadMessage("Invalid request URL"); + return false; + } + + if (!request->url.SchemeIsHTTPOrHTTPS()) { + mojo::ReportBadMessage("Invalid request URL scheme"); + return false; + } + } + return true; } diff --git a/content/browser/background_fetch/background_fetch_service_unittest.cc b/content/browser/background_fetch/background_fetch_service_unittest.cc index 287e7ec5..9fb5ec3a 100644 --- a/content/browser/background_fetch/background_fetch_service_unittest.cc +++ b/content/browser/background_fetch/background_fetch_service_unittest.cc @@ -493,11 +493,69 @@ blink::mojom::BackgroundFetchRegistrationPtr registration; Fetch(/* service_worker_registration_id= */ 42, kExampleDeveloperId, - std::move(requests), std::move(options), SkBitmap(), &error, + std::move(requests), options.Clone(), SkBitmap(), &error, ®istration); ASSERT_EQ(error, blink::mojom::BackgroundFetchError::INVALID_ARGUMENT); EXPECT_EQ("Invalid requests", bad_message_observer.WaitForBadMessage()); } + + // Request URLs must use the HTTP or HTTPS scheme. + { + mojo::FakeMessageDispatchContext fake_dispatch_context; + mojo::test::BadMessageObserver bad_message_observer; + std::vector<blink::mojom::FetchAPIRequestPtr> requests; + auto request = CreateRequestWithProvidedResponse( + "GET", GURL("file:///test.txt"), + TestResponseBuilder(200).MakeIndefinitelyPending().Build()); + requests.push_back(std::move(request)); + + blink::mojom::BackgroundFetchError error; + blink::mojom::BackgroundFetchRegistrationPtr registration; + + Fetch(/* service_worker_registration_id= */ 42, kExampleDeveloperId, + std::move(requests), options.Clone(), SkBitmap(), &error, + ®istration); + EXPECT_EQ(error, blink::mojom::BackgroundFetchError::INVALID_ARGUMENT); + EXPECT_EQ("Invalid request URL scheme", + bad_message_observer.WaitForBadMessage()); + } + + // Request URLs must be valid URLs. + { + mojo::FakeMessageDispatchContext fake_dispatch_context; + mojo::test::BadMessageObserver bad_message_observer; + std::vector<blink::mojom::FetchAPIRequestPtr> requests; + auto request = CreateRequestWithProvidedResponse( + "GET", GURL("invalid-url"), + TestResponseBuilder(200).MakeIndefinitelyPending().Build()); + requests.push_back(std::move(request)); + + blink::mojom::BackgroundFetchError error; + blink::mojom::BackgroundFetchRegistrationPtr registration; + + Fetch(/* service_worker_registration_id= */ 42, kExampleDeveloperId, + std::move(requests), options.Clone(), SkBitmap(), &error, + ®istration); + EXPECT_EQ(error, blink::mojom::BackgroundFetchError::INVALID_ARGUMENT); + EXPECT_EQ("Invalid request URL", bad_message_observer.WaitForBadMessage()); + } + + // Request objects in the vector must be non-null. + { + mojo::FakeMessageDispatchContext fake_dispatch_context; + mojo::test::BadMessageObserver bad_message_observer; + std::vector<blink::mojom::FetchAPIRequestPtr> requests; + requests.push_back(nullptr); + + blink::mojom::BackgroundFetchError error; + blink::mojom::BackgroundFetchRegistrationPtr registration; + + Fetch(/* service_worker_registration_id= */ 42, kExampleDeveloperId, + std::move(requests), std::move(options), SkBitmap(), &error, + ®istration); + EXPECT_EQ(error, blink::mojom::BackgroundFetchError::INVALID_ARGUMENT); + EXPECT_EQ("Null request", bad_message_observer.WaitForBadMessage()); + } } TEST_F(BackgroundFetchServiceTest, FetchRegistrationProperties) {
Loading diff…
Regression Test / PoC
shipped with the fix
diff --git a/content/browser/background_fetch/background_fetch_service_unittest.cc b/content/browser/background_fetch/background_fetch_service_unittest.cc
index 287e7ec5..9fb5ec3a 100644
--- a/content/browser/background_fetch/background_fetch_service_unittest.cc
+++ b/content/browser/background_fetch/background_fetch_service_unittest.cc
@@ -493,11 +493,69 @@
blink::mojom::BackgroundFetchRegistrationPtr registration;
Fetch(/* service_worker_registration_id= */ 42, kExampleDeveloperId,
- std::move(requests), std::move(options), SkBitmap(), &error,
+ std::move(requests), options.Clone(), SkBitmap(), &error,
®istration);
ASSERT_EQ(error, blink::mojom::BackgroundFetchError::INVALID_ARGUMENT);
EXPECT_EQ("Invalid requests", bad_message_observer.WaitForBadMessage());
}
+
+ // Request URLs must use the HTTP or HTTPS scheme.
+ {
+ mojo::FakeMessageDispatchContext fake_dispatch_context;
+ mojo::test::BadMessageObserver bad_message_observer;
+ std::vector<blink::mojom::FetchAPIRequestPtr> requests;
+ auto request = CreateRequestWithProvidedResponse(
+ "GET", GURL("file:///test.txt"),
+ TestResponseBuilder(200).MakeIndefinitelyPending().Build());
+ requests.push_back(std::move(request));
+
+ blink::mojom::BackgroundFetchError error;
+ blink::mojom::BackgroundFetchRegistrationPtr registration;
+
+ Fetch(/* service_worker_registration_id= */ 42, kExampleDeveloperId,
+ std::move(requests), options.Clone(), SkBitmap(), &error,
+ ®istration);
+ EXPECT_EQ(error, blink::mojom::BackgroundFetchError::INVALID_ARGUMENT);
+ EXPECT_EQ("Invalid request URL scheme",
+ bad_message_observer.WaitForBadMessage());
+ }
+
+ // Request URLs must be valid URLs.
+ {
+ mojo::FakeMessageDispatchContext fake_dispatch_context;
+ mojo::test::BadMessageObserver bad_message_observer;
+ std::vector<blink::mojom::FetchAPIRequestPtr> requests;
+ auto request = CreateRequestWithProvidedResponse(
+ "GET", GURL("invalid-url"),
+ TestResponseBuilder(200).MakeIndefinitelyPending().Build());
+ requests.push_back(std::move(request));
+
+ blink::mojom::BackgroundFetchError error;
+ blink::mojom::BackgroundFetchRegistrationPtr registration;
+
+ Fetch(/* service_worker_registration_id= */ 42, kExampleDeveloperId,
+ std::move(requests), options.Clone(), SkBitmap(), &error,
+ ®istration);
+ EXPECT_EQ(error, blink::mojom::BackgroundFetchError::INVALID_ARGUMENT);
+ EXPECT_EQ("Invalid request URL", bad_message_observer.WaitForBadMessage());
+ }
+
+ // Request objects in the vector must be non-null.
+ {
+ mojo::FakeMessageDispatchContext fake_dispatch_context;
+ mojo::test::BadMessageObserver bad_message_observer;
+ std::vector<blink::mojom::FetchAPIRequestPtr> requests;
+ requests.push_back(nullptr);
+
+ blink::mojom::BackgroundFetchError error;
+ blink::mojom::BackgroundFetchRegistrationPtr registration;
+
+ Fetch(/* service_worker_registration_id= */ 42, kExampleDeveloperId,
+ std::move(requests), std::move(options), SkBitmap(), &error,
+ ®istration);
+ EXPECT_EQ(error, blink::mojom::BackgroundFetchError::INVALID_ARGUMENT);
+ EXPECT_EQ("Null request", bad_message_observer.WaitForBadMessage());
+ }
}
TEST_F(BackgroundFetchServiceTest, FetchRegistrationProperties) {
Loading diff…
Original Bug Report
The reporter's bug is still restricted on the tracker. Chrome de-restricts security bugs ~30–90 days after the fix ships; a later run will backfill it here.
References
On This Page