Medium watch CVSS 5.4 chrome Logic Error 📄 Reporter bug report 🔧 Commit mapped

Overview

Medium
Severity
5.4
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactInappropriate implementation in Background Fetch API
DescriptionInappropriate implementation in Background Fetch API
ComponentBackground Fetch API
Sub-componentBackground fetch
Bug ClassLogic Error
Action tierwatch — logic/policy bug — security-relevant, no memory-unsafety
Computed by PatchGap's deterministic exploitability ruler from the fixing commit. patch-now = RCE-class & attacker-reachable in a default config, or exploited in the wild; watch = real security signal below that bar; noise = no security relevance.
Tracker40058068
Fix commit43cac9d50998 (chromium/src) +13/-0
CWECWE-200 (Information exposure)
CVSS vectorCVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:L/I:L/A:N
CISA KEVNot listed
CreditedMaurice Dauer
Reported2021-11-29 · bounty $4000 (per vendor advisory)
Fix landed2025-04-22 (public git)
Disclosed2025-05-27
Patch gap35 days — fix public in source before the advisory

Background

Background Fetch API
a web API that lets a page/service worker schedule resource fetches that continue in the background via the browser’s download service rather than as normal page-driven network requests.
`request_initiator`
the origin that initiated a network request, documented in url_request.mojom, which the network stack relies on to perform security checks (e.g. same-origin, site-isolation, and CORS-related decisions).
`DownloadParams` / `download_url_params`
the parameter structs threaded from the background-fetch delegate through the download service (components/download/...) to build the actual network download request.
`isolation_info`
the network isolation key information already passed through this path; the patch adds the initiator origin alongside it.

Root Cause Analysis

Background Fetch scheduled its requests through the download service, but the download path never populated a request initiator, so the resulting network requests lacked the request_initiator that url_request.mojom says is required for certain security checks. In components/download/public/background_service/download_params.h there was no field to carry the origin, so components/background_fetch/background_fetch_delegate_base.cc could not forward it and components/download/content/internal/download_driver_impl.cc never set it on download_url_params. Because these background-fetch requests behaved like ordinary downloads (which normally do not need an initiator), the origin-dependent checks could be skipped or misapplied — the “inappropriate implementation in Background Fetch API” the advisory describes.

The fix adds a std::optional<url::Origin> initiator field to DownloadParams, sets params.request_params.initiator = job_details->fetch_description->origin in the background-fetch delegate, and, in the download driver, calls download_url_params->set_initiator(request_params.initiator.value()) when the initiator is present, so the initiating origin flows to the network request and the required security checks run with correct context.

Key insight
The single core mistake was omitting the initiating origin from background-fetch download requests so request_initiator-based security checks lacked their input; the fix threads fetch_description->origin into DownloadParams::initiator and sets it as the request initiator before the download is issued.

Attack Path

  1. Issue a background fetch A page or service worker uses the Background Fetch API to schedule a request that is routed to the download service.
  2. Request built without initiator Pre-patch, download_driver_impl.cc constructed download_url_params without setting an initiator because DownloadParams had no initiator field to carry the origin.
  3. Security checks lack context The network request proceeds without a request_initiator, so origin-dependent checks that url_request.mojom requires are not applied as they would be for a page-initiated fetch.
  4. Policy bypass The attacker’s background fetch reaches resources or is treated in ways that the initiating origin’s security checks should have constrained. (inferred specific cross-origin access primitive)

Impact Assessment

A web origin using Background Fetch could cause network requests to be made without the initiating origin attached, bypassing or misapplying the security checks that depend on request_initiator, consistent with the advisory’s “Inappropriate implementation in Background Fetch API.” The precondition is the ability to use the Background Fetch API from a page/service worker. The vendor advisory rates this medium severity and does not report in-the-wild exploitation; NVD scores it CVSS 5.4. Any concrete escalation such as cross-origin data access beyond the missing-initiator condition is (inferred).

Changed Functions

FunctionChangeNotes
if
components/download/content/internal/download_driver_impl.cc
modified

Files Changed

  • AUTHORS
  • components/background_fetch/background_fetch_delegate_base.cc
  • components/download/content/internal/download_driver_impl.cc
  • components/download/public/background_service/download_params.h

Audit Directions

  • Requests routed around the normal network path
    Audit APIs (background fetch, downloads, prefetch, service-worker-scheduled fetches) that build network requests through non-standard paths and verify request_initiator and isolation info are set as they are for page-driven requests.
  • Optional security fields left unset
    Look for std::optional security-relevant fields (initiator, isolation info, trusted params) that are only conditionally set, and confirm callers on privileged paths always populate them.
  • `url_request.mojom` invariants
    Cross-check consumers of url_request.mojom request parameters against its documented requirements to find code that satisfies functional needs but omits the fields the security checks depend on.
From 43cac9d509983c7f68a5ffa119cc7509bde375ea Mon Sep 17 00:00:00 2001
From: Maurice Dauer <layton.cscg@gmail.com>
Date: Tue, 22 Apr 2025 02:49:18 -0700
Subject: [PATCH] [Background fetch] Pass request initiator to download service

The request initiator is required to perform certain security checks,
see |request_initiator| in url_request.mojom for details. Since
background fetch doesn't work like a normal download, we need to pass it
to the download service.

R=peter@chromium.org

Bug: 40058068
Change-Id: I680e759afda3c582d38c05fb98e322065c43f124
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6464959
Reviewed-by: Min Qin <qinmin@chromium.org>
Commit-Queue: Peter Beverloo <peter@chromium.org>
Reviewed-by: Peter Beverloo <peter@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1449821}
---

diff --git a/AUTHORS b/AUTHORS
index cb106a2..3dc5d32b 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -975,6 +975,7 @@
 Matthieu Rigolot <matthieu.rigolot@gmail.com>
 Matthieu Vlad Hauglustaine <matt.hauglustaine@gmail.com>
 Mattias Buelens <mattias.buelens@gmail.com>
+Maurice Dauer <layton.cscg@gmail.com>
 Max Coplan <mchcopl@gmail.com>
 Max Perepelitsyn <pph34r@gmail.com>
 Max Schmitt <max@schmitt.mx>
diff --git a/components/background_fetch/background_fetch_delegate_base.cc b/components/background_fetch/background_fetch_delegate_base.cc
index 2cd4b82..d4ecd4e5 100644
--- a/components/background_fetch/background_fetch_delegate_base.cc
+++ b/components/background_fetch/background_fetch_delegate_base.cc
@@ -114,6 +114,7 @@
     job_details->MarkJobAsStarted();
   }
 
+  params.request_params.initiator = job_details->fetch_description->origin;
   params.request_params.isolation_info =
       job_details->fetch_description->isolation_info;
 
diff --git a/components/download/content/internal/download_driver_impl.cc b/components/download/content/internal/download_driver_impl.cc
index 0428af02..5e0f726 100644
--- a/components/download/content/internal/download_driver_impl.cc
+++ b/components/download/content/internal/download_driver_impl.cc
@@ -229,6 +229,9 @@
   }
   download_url_params->set_update_first_party_url_on_redirect(
       request_params.update_first_party_url_on_redirect);
+  if (request_params.initiator) {
+    download_url_params->set_initiator(request_params.initiator.value());
+  }
 
   download_manager_coordinator_->DownloadUrl(std::move(download_url_params));
 }
diff --git a/components/download/public/background_service/download_params.h b/components/download/public/background_service/download_params.h
index 8d539cb..5277fcc 100644
--- a/components/download/public/background_service/download_params.h
+++ b/components/download/public/background_service/download_params.h
@@ -18,6 +18,7 @@
 #include "net/traffic_annotation/network_traffic_annotation.h"
 #include "services/network/public/mojom/fetch_api.mojom-shared.h"
 #include "url/gurl.h"
+#include "url/origin.h"
 
 namespace download {
 
@@ -135,6 +136,13 @@
   // considered a main frame navigation. However, this is not true for
   // background fetch.
   bool update_first_party_url_on_redirect = true;
+
+  // The origin that initiated the request. This is used to perform
+  // security checks. Normally, these checks aren't required for downloads,
+  // but necessary for background fetch.
+  // See |request_initiator| in url_request.mojom for a more detailed
+  // explanation.
+  std::optional<url::Origin> initiator;
 };
 
 // The parameters that describe a download request made to the DownloadService.
Loading diff…

Original Bug Report

reported by la...@gmail.com

Security: Bypass of Issue 1239709: Cross-Origin Response Leak If wildcard ACAO is sent

VULNERABILITY DETAILS
BackgroundFetch sends cookies even if the credentials mode is “omit” or “same-origin” and thus bypassing the fix for https://crbug.com/chromium/1239709.

VERSION
Version 96.0.4664.45 (Official Build) Arch Linux (64-bit)

REPRODUCTION CASE
Using the glitch.me site from https://crbug.com/chromium/1239709:

<script>  
  const url = "https://echo-cookie-test.glitch.me/echo-cookie"; // some site with a wildcard ACAO header  
  
  navigator.serviceWorker.ready.then(async (swReg) => {  
    // { credentials: "same-origin" || "omit" } still sends cookies, but isn't blocked  
    const bgFetch = await swReg.backgroundFetch.fetch("test", [new Request(url, { credentials: "omit" })]);  
  
    const targetPage = await bgFetch.match(url);  
    const response = await targetPage.responseReady;  
  
    console.log(await response.text()); // response contains cookie  
  });  
  
  navigator.serviceWorker.register("sw.js");  
</script>  
// can be empty  

I’m not entirely sure, but AFAIU setting the request->request_initiator1, that is explained here2, in the DownloadParams struct, that is declared here3, should fix this.
Also not sure how that relates to https://crbug.com/chromium/1268580 and if that fixes it too.

CREDIT INFORMATION
Reporter credit: Maurice Dauer

View on issue tracker