High watch CVSS 8.1 chrome Input Validation 📄 Reporter bug report 🔧 Commit mapped

Overview

High
Severity
8.1
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactInsufficient validation of untrusted input in Workers
DescriptionInsufficient validation of untrusted input in Workers
ComponentWorkers
Bug ClassInput Validation
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.
Tracker532939327
Fix commit22500d480098 (chromium/src) +94/-0
CWECWE-20 (Improper input validation)
CVSS vectorCVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:N
CISA KEVNot listed
CreditedGoogle
Reported2026-07-09 (per vendor advisory)
Fix landed2026-07-22 (public git)
Disclosed2026-08-06
Patch gap15 days — fix public in source before the advisory

Background

`WorkerScriptLoader`
the browser-process (UI thread) URLLoader/URLLoaderClient shim in content/browser/worker_host/ that fetches the main script of dedicated and shared workers and passes results to an outer client such as WorkerScriptFetcher.
`OnReceiveRedirect`
the loader-client callback that receives a net::RedirectInfo (holding new_url) and decides whether the redirect is forwarded and followed or the load is completed with an error.
`IsSafeRedirectTarget()`
a content helper (from content/public/common/url_utils.h) that decides whether a redirect from one URL to another is allowed; per the commit message it rejects targets such as file:// or chrome://.
`blob:` URL
an in-memory object URL served by the blob system; per the patch comment, “Loading a blob URL never produces a redirect”.

Root Cause Analysis

WorkerScriptLoader::OnReceiveRedirect (named in the commit message; the hunk shows only its parameters, redirect_info and response_head) used to check only the redirect count (--redirect_limit_ == 0 → ERR_TOO_MANY_REDIRECTS) before passing a redirect to the outer client and following it. It never checked what was redirecting or where the redirect led. Two invariants were therefore not enforced for worker main-script loads, even though NavigationURLLoaderImpl already enforces them for main-frame navigations: a blob: load must never redirect, and a redirect must go to a scheme that IsSafeRedirectTarget() allows.

The patch adds two early-exit checks at the top of the function, before the redirect-limit check and before any forwarding. If resource_request_.url.SchemeIsBlob(), or if !IsSafeRedirectTarget(resource_request_.url, redirect_info.new_url), the loader sets complete_status_ to net::ERR_UNSAFE_REDIRECT, calls CommitCompleted() and returns. The new tests confirm that the outer client then sees no redirect (has_received_redirect() is false) and only a completion with ERR_UNSAFE_REDIRECT. The diff does not show which upstream loader can actually produce a redirect for a blob: worker script; the test injects one by hand.

Key insight
The worker script loader trusted any redirect it received and checked only how many there were, not whether the source scheme could legitimately redirect or whether the target scheme was safe. The fix validates both the source (blob: never redirects) and the target (IsSafeRedirectTarget()) before the redirect is forwarded or followed.

Attack Path

  1. Page starts a worker Web content creates a dedicated or shared worker, so the browser starts a WorkerScriptLoader for the main script URL (either an https: URL or a blob: URL).
  2. Loader receives a redirect The underlying load returns a redirect: either an attacker server’s HTTP redirect to a scheme such as file: or chrome: (as in RejectUnsafeRedirectTarget), or a redirect on a blob: load that should never happen (as in RedirectFromBlobUrl). How a blob: load would produce one in practice is not shown in the diff.
  3. Redirect forwarded without validation Before the patch, OnReceiveRedirect only decremented redirect_limit_ and then passed the redirect on to the outer URLLoaderClient (for example WorkerScriptFetcher) to be followed.
  4. Worker script from an unintended origin or scheme Following the redirect could let the worker’s script, and possibly the URL or origin the browser associates with it, come from a privileged or local scheme, or let a blob: worker escape blob-origin semantics (inferred; the downstream effect is not shown in the patch).

Impact Assessment

This is an input-validation gap in browser-process worker script loading. The likely security effect is a policy bypass, such as loading a worker script through a redirect to a disallowed scheme or a redirect on a blob: load, rather than memory corruption. Any resulting access to local files or privileged pages is (inferred), since IsSafeRedirectTarget() and other layers may already block some targets. Web content in a stock build can start workers and control the redirect responses of its own servers, but whether a blob: load can redirect without a compromised renderer or other special conditions is not established by the diff. The vendor advisory rates this high severity and does not report in-the-wild exploitation; NVD scores it CVSS 8.1.

Changed Functions

FunctionChangeNotes
if
content/browser/worker_host/worker_script_loader.cc
modified
TEST_F
content/browser/worker_host/worker_script_loader_factory_unittest.cc
modified

Files Changed

  • content/browser/worker_host/worker_script_loader.cc
  • content/browser/worker_host/worker_script_loader_factory_unittest.cc

Audit Directions

  • Loader shims that only count redirects
    Audit other browser-side URLLoaderClient wrappers (service worker script loading, ServiceWorkerMainResourceLoaderInterceptor paths, prefetch/prerender loaders, extension and WebUI loaders) that check redirect_limit_ but not IsSafeRedirectTarget() or the source scheme.
  • Schemes that must never redirect
    Any loader for blob:, data:, filesystem: or about: content should treat a redirect as a hard error. Look for paths where a renderer-supplied or interceptor-supplied URLLoaderFactory could produce one.
  • Parity with navigation
    Compare worker, shared-worker and service-worker script fetch policy with NavigationURLLoaderImpl for redirects, URLLoaderThrottle checks and scheme restrictions; the commit explicitly fixes such a parity gap.
From 22500d480098ce3bb02f8850a7e4f93bed85d335 Mon Sep 17 00:00:00 2001
From: Yoshisto Yanagisawa <yyanagisawa@chromium.org>
Date: Tue, 21 Jul 2026 21:58:39 -0700
Subject: [PATCH] Reject unsupported redirects during worker script loading

Loading a blob: URL is not expected to produce a redirect. To maintain
behavioral consistency with main frame navigations in
NavigationURLLoaderImpl and to follow expected resource loading
semantics, worker main script loading paths should decline unexpected or
unsupported redirect sequences.

This change updates WorkerScriptLoader::OnReceiveRedirect to immediately
complete script loads with net::ERR_UNSAFE_REDIRECT when:
- The originating request URL uses the blob: scheme.
- The destination URL scheme is not supported as a redirect target
  according to IsSafeRedirectTarget() (e.g., attempting a redirect to
  file:// or chrome://).

Handling this verification at WorkerScriptLoader guarantees that
unsupported redirects are cleanly terminated at the underlying URLLoader
boundary before ever reaching the outer URLLoaderClient (such as
WorkerScriptFetcher). This provides consistent error handling across
both renderer-initiated and browser-initiated worker loading flows.

Two unit test cases (RedirectFromBlobUrl and RejectUnsafeRedirectTarget)
are added to WorkerScriptLoaderFactoryTest to verify this error
handling.

TAG=agy
CONV=e9ed9a69-d0d2-4765-a7e4-262255687012

Bug: 532939327
Change-Id: I486a8e999b926472c7835234efb4f05d338d5ae6
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/8130577
Reviewed-by: Hiroki Nakagawa <nhiroki@chromium.org>
Auto-Submit: Yoshisato Yanagisawa <yyanagisawa@chromium.org>
Commit-Queue: Hiroki Nakagawa <nhiroki@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1666012}
---
diff --git a/content/browser/worker_host/worker_script_loader.cc b/content/browser/worker_host/worker_script_loader.cc
index 735a44a..dcccdae 100644
--- a/content/browser/worker_host/worker_script_loader.cc
+++ b/content/browser/worker_host/worker_script_loader.cc
@@ -12,7 +12,9 @@
 #include "content/browser/service_worker/service_worker_main_resource_loader_interceptor.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
+#include "content/public/common/url_utils.h"
 #include "net/base/load_timing_info.h"
+#include "net/base/net_errors.h"
 #include "net/url_request/redirect_util.h"
 #include "services/network/public/cpp/record_ontransfersizeupdate_utils.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
@@ -229,6 +231,22 @@
     const net::RedirectInfo& redirect_info,
     network::mojom::URLResponseHeadPtr response_head) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+  if (resource_request_.url.SchemeIsBlob()) {
+    // Loading a blob URL never produces a redirect.
+    complete_status_ =
+        network::URLLoaderCompletionStatus(net::ERR_UNSAFE_REDIRECT);
+    CommitCompleted();
+    return;
+  }
+
+  if (!IsSafeRedirectTarget(resource_request_.url, redirect_info.new_url)) {
+    complete_status_ =
+        network::URLLoaderCompletionStatus(net::ERR_UNSAFE_REDIRECT);
+    CommitCompleted();
+    return;
+  }
+
   if (--redirect_limit_ == 0) {
     complete_status_ =
         network::URLLoaderCompletionStatus(net::ERR_TOO_MANY_REDIRECTS);
diff --git a/content/browser/worker_host/worker_script_loader_factory_unittest.cc b/content/browser/worker_host/worker_script_loader_factory_unittest.cc
index d9d896b..4746b25f 100644
--- a/content/browser/worker_host/worker_script_loader_factory_unittest.cc
+++ b/content/browser/worker_host/worker_script_loader_factory_unittest.cc
@@ -6,6 +6,7 @@
 
 #include "base/functional/callback_helpers.h"
 #include "base/run_loop.h"
+#include "base/test/run_until.h"
 #include "content/browser/service_worker/embedded_worker_test_helper.h"
 #include "content/browser/service_worker/service_worker_client.h"
 #include "content/browser/service_worker/service_worker_context_core.h"
@@ -16,6 +17,7 @@
 #include "content/test/fake_network_url_loader_factory.h"
 #include "net/base/isolation_info.h"
 #include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
+#include "net/url_request/redirect_info.h"
 #include "services/network/public/cpp/wrapper_shared_url_loader_factory.h"
 #include "services/network/public/mojom/fetch_api.mojom.h"
 #include "services/network/test/test_url_loader_client.h"
@@ -186,6 +188,80 @@
   EXPECT_EQ(net::ERR_ABORTED, client.completion_status().error_code);
 }
 
+// Tests that a redirect received while loading a blob: URL is rejected. Loading
+// a blob URL never produces a redirect, so any redirect must be rejected before
+// it is forwarded or followed.
+TEST_F(WorkerScriptLoaderFactoryTest, RedirectFromBlobUrl) {
+  GURL url("blob:https://www.example.com/49146318-7a89-4041-9bcc-36e6b6eeef86");
+
+  // Defer the mock network load so we can inject a redirect on the in-flight
+  // load.
+  network_loader_factory_instance_->DeferHandleRequest();
+
+  // Create the factory.
+  auto factory = std::make_unique<WorkerScriptLoaderFactory>(
+      kProcessId, DedicatedOrSharedWorkerToken(),
+      net::IsolationInfo::CreateForInternalRequest(url::Origin::Create(url)),
+      service_worker_handle_.get(), browser_context_getter_,
+      network_loader_factory_);
+
+  // Start loading the script.
+  network::TestURLLoaderClient client;
+  mojo::PendingRemote<network::mojom::URLLoader> loader =
+      CreateTestLoaderAndStart(url, factory.get(), &client);
+  ASSERT_TRUE(base::test::RunUntil(
+      [&]() { return factory->GetScriptLoader() != nullptr; }));
+
+  // Simulate receiving a redirect from the blob load.
+  net::RedirectInfo redirect_info;
+  redirect_info.status_code = 302;
+  redirect_info.new_method = "GET";
+  redirect_info.new_url = GURL("https://other.example.com/worker.js");
+  factory->GetScriptLoader()->OnReceiveRedirect(
+      redirect_info, network::mojom::URLResponseHead::New());
+  client.RunUntilComplete();
+
+  // Verify that the redirect was blocked and the load was aborted with
+  // ERR_UNSAFE_REDIRECT.
+  EXPECT_FALSE(client.has_received_redirect());
+  ASSERT_TRUE(client.has_received_completion());
+  EXPECT_EQ(net::ERR_UNSAFE_REDIRECT, client.completion_status().error_code);
+}
+
+// Tests that a redirect to an unsafe target scheme is rejected.
+TEST_F(WorkerScriptLoaderFactoryTest, RejectUnsafeRedirectTarget) {
+  GURL url("https://www.example.com/worker.js");
+
+  network_loader_factory_instance_->DeferHandleRequest();
+
+  auto factory = std::make_unique<WorkerScriptLoaderFactory>(
+      kProcessId, DedicatedOrSharedWorkerToken(),
+      net::IsolationInfo::CreateForInternalRequest(url::Origin::Create(url)),
+      service_worker_handle_.get(), browser_context_getter_,
+      network_loader_factory_);
+
+  network::TestURLLoaderClient client;
+  mojo::PendingRemote<network::mojom::URLLoader> loader =
+      CreateTestLoaderAndStart(url, factory.get(), &client);
+  ASSERT_TRUE(base::test::RunUntil(
+      [&]() { return factory->GetScriptLoader() != nullptr; }));
+
+  // Simulate receiving an unsafe redirect (e.g. to a file scheme).
+  net::RedirectInfo redirect_info;
+  redirect_info.status_code = 302;
+  redirect_info.new_method = "GET";
+  redirect_info.new_url = GURL("file:///path/to/worker.js");
+  factory->GetScriptLoader()->OnReceiveRedirect(
+      redirect_info, network::mojom::URLResponseHead::New());
+  client.RunUntilComplete();
+
+  // Verify that the redirect was blocked and the load was aborted with
+  // ERR_UNSAFE_REDIRECT.
+  EXPECT_FALSE(client.has_received_redirect());
+  ASSERT_TRUE(client.has_received_completion());
+  EXPECT_EQ(net::ERR_UNSAFE_REDIRECT, client.completion_status().error_code);
+}
+
 // TODO(falken): Add a test for a shared worker that's controlled by a service
 // worker.
 
Loading diff…

Regression Test / PoC

shipped with the fix
diff --git a/content/browser/worker_host/worker_script_loader_factory_unittest.cc b/content/browser/worker_host/worker_script_loader_factory_unittest.cc
index d9d896b..4746b25f 100644
--- a/content/browser/worker_host/worker_script_loader_factory_unittest.cc
+++ b/content/browser/worker_host/worker_script_loader_factory_unittest.cc
@@ -6,6 +6,7 @@
 
 #include "base/functional/callback_helpers.h"
 #include "base/run_loop.h"
+#include "base/test/run_until.h"
 #include "content/browser/service_worker/embedded_worker_test_helper.h"
 #include "content/browser/service_worker/service_worker_client.h"
 #include "content/browser/service_worker/service_worker_context_core.h"
@@ -16,6 +17,7 @@
 #include "content/test/fake_network_url_loader_factory.h"
 #include "net/base/isolation_info.h"
 #include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
+#include "net/url_request/redirect_info.h"
 #include "services/network/public/cpp/wrapper_shared_url_loader_factory.h"
 #include "services/network/public/mojom/fetch_api.mojom.h"
 #include "services/network/test/test_url_loader_client.h"
@@ -186,6 +188,80 @@
   EXPECT_EQ(net::ERR_ABORTED, client.completion_status().error_code);
 }
 
+// Tests that a redirect received while loading a blob: URL is rejected. Loading
+// a blob URL never produces a redirect, so any redirect must be rejected before
+// it is forwarded or followed.
+TEST_F(WorkerScriptLoaderFactoryTest, RedirectFromBlobUrl) {
+  GURL url("blob:https://www.example.com/49146318-7a89-4041-9bcc-36e6b6eeef86");
+
+  // Defer the mock network load so we can inject a redirect on the in-flight
+  // load.
+  network_loader_factory_instance_->DeferHandleRequest();
+
+  // Create the factory.
+  auto factory = std::make_unique<WorkerScriptLoaderFactory>(
+      kProcessId, DedicatedOrSharedWorkerToken(),
+      net::IsolationInfo::CreateForInternalRequest(url::Origin::Create(url)),
+      service_worker_handle_.get(), browser_context_getter_,
+      network_loader_factory_);
+
+  // Start loading the script.
+  network::TestURLLoaderClient client;
+  mojo::PendingRemote<network::mojom::URLLoader> loader =
+      CreateTestLoaderAndStart(url, factory.get(), &client);
+  ASSERT_TRUE(base::test::RunUntil(
+      [&]() { return factory->GetScriptLoader() != nullptr; }));
+
+  // Simulate receiving a redirect from the blob load.
+  net::RedirectInfo redirect_info;
+  redirect_info.status_code = 302;
+  redirect_info.new_method = "GET";
+  redirect_info.new_url = GURL("https://other.example.com/worker.js");
+  factory->GetScriptLoader()->OnReceiveRedirect(
+      redirect_info, network::mojom::URLResponseHead::New());
+  client.RunUntilComplete();
+
+  // Verify that the redirect was blocked and the load was aborted with
+  // ERR_UNSAFE_REDIRECT.
+  EXPECT_FALSE(client.has_received_redirect());
+  ASSERT_TRUE(client.has_received_completion());
+  EXPECT_EQ(net::ERR_UNSAFE_REDIRECT, client.completion_status().error_code);
+}
+
+// Tests that a redirect to an unsafe target scheme is rejected.
+TEST_F(WorkerScriptLoaderFactoryTest, RejectUnsafeRedirectTarget) {
+  GURL url("https://www.example.com/worker.js");
+
+  network_loader_factory_instance_->DeferHandleRequest();
+
+  auto factory = std::make_unique<WorkerScriptLoaderFactory>(
+      kProcessId, DedicatedOrSharedWorkerToken(),
+      net::IsolationInfo::CreateForInternalRequest(url::Origin::Create(url)),
+      service_worker_handle_.get(), browser_context_getter_,
+      network_loader_factory_);
+
+  network::TestURLLoaderClient client;
+  mojo::PendingRemote<network::mojom::URLLoader> loader =
+      CreateTestLoaderAndStart(url, factory.get(), &client);
+  ASSERT_TRUE(base::test::RunUntil(
+      [&]() { return factory->GetScriptLoader() != nullptr; }));
+
+  // Simulate receiving an unsafe redirect (e.g. to a file scheme).
+  net::RedirectInfo redirect_info;
+  redirect_info.status_code = 302;
+  redirect_info.new_method = "GET";
+  redirect_info.new_url = GURL("file:///path/to/worker.js");
+  factory->GetScriptLoader()->OnReceiveRedirect(
+      redirect_info, network::mojom::URLResponseHead::New());
+  client.RunUntilComplete();
+
+  // Verify that the redirect was blocked and the load was aborted with
+  // ERR_UNSAFE_REDIRECT.
+  EXPECT_FALSE(client.has_received_redirect());
+  ASSERT_TRUE(client.has_received_completion());
+  EXPECT_EQ(net::ERR_UNSAFE_REDIRECT, client.completion_status().error_code);
+}
+
 // TODO(falken): Add a test for a shared worker that's controlled by a service
 // worker.
Loading diff…

Original Bug Report

reported by vm...@google.com

Site Isolation Bypass via Missing Blob Redirect Validation in WorkerScriptLoader

Project Fortify, an experimental security project, has identified the following potential security issue. If you’re a feature owner CC-ed on this bug, please do your best to review these reports. Please see https://chromium.googlesource.com/chromium/src/+/main/docs/security/ai-generated-security-bugs-faq.md for more information.

Overview: A missing URL scheme check in WorkerScriptLoader’s redirect handler potentially allows a compromised renderer to forge a cross-origin redirect from a custom blob: URL. By driving the browser-side service worker interceptor with the redirected victim URL, the renderer can potentially obtain cross-origin Service Worker response data. This leads to a potential Site Isolation bypass and cross-origin information leak.

Affected files:

  • content/browser/worker_host/worker_script_loader.cc
  • content/browser/worker_host/worker_script_fetcher.cc

Estimated timestamp from git blame: 2018-04-06

Root Cause

In Chromium, loading a blob: URL should never produce a redirect. For standard frame navigations, this security property is enforced in NavigationURLLoaderImpl::OnReceiveRedirect (content/browser/loader/navigation_url_loader_impl.cc:1595-1597):

if (url_.SchemeIsBlob()) {
  // Loading a blob URL never produces a redirect.
  error = net::ERR_UNSAFE_REDIRECT;
}

However, this mitigation was not applied to the worker main-script loading path. Specifically, WorkerScriptLoader::OnReceiveRedirect (content/browser/worker_host/worker_script_loader.cc:228-241) accepts redirects unconditionally:

void WorkerScriptLoader::OnReceiveRedirect(
    const net::RedirectInfo& redirect_info,
    network::mojom::URLResponseHeadPtr response_head) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  if (--redirect_limit_ == 0) { ...; return; }

  redirect_info_ = redirect_info;
  client_->OnReceiveRedirect(redirect_info, std::move(response_head));
}

When a worker script loader accepts a redirect, WorkerScriptFetcher::OnReceiveRedirect immediately auto-follows the redirect via url_loader_->FollowRedirect() (content/browser/worker_host/worker_script_fetcher.cc:784-791). This results in WorkerScriptLoader::FollowRedirect rewriting resource_request_.url with the new, attacker-supplied redirect URL and calling Start() again to re-enter the Service Worker interceptor layer with the new URL.

Because the request has not yet committed, the associated ServiceWorkerClient’s state can be mutated to the new cross-origin URL. The security helper CheckOnUpdateUrls (content/browser/service_worker/service_worker_security_utils.cc:54-77) that asserts origin boundaries is compiled out in production builds because it is wrapped entirely within #if DCHECK_IS_ON().

Consequently, the browser can be coerced into dispatching a FetchEvent to a cross-origin Service Worker (under the victim’s partitioned storage key) and routing the returned response data pipe back to the attacker’s renderer process via WorkerMainScriptLoadParams during client_->OnScriptLoadStarted in DedicatedWorkerHost::DidStartScriptLoad.


Potential Trigger Steps

Note: These are suggested and potential steps; our tooling does not have the ability to run functional exploit code to verify this sequence.

  1. A compromised renderer process under https://evil.com binds a local implementation of blink::mojom::Blob and registers a custom blob URL (e.g., blob:https://evil.com/attacker-uuid) via BlobURLStoreImpl::Register.
  2. The renderer requests worker script loading for this blob URL via DedicatedWorkerHostFactory::CreateWorkerHostAndStartScriptLoad, passing the corresponding BlobURLToken.
  3. The browser establishes the connection and initiates the loader. Since the target is a blob URL, it queries the renderer’s blob implementation via BlobURLLoaderFactory::CreateLoaderAndStart. This delivers a browser-process Mojo URLLoaderClient remote directly to the attacker’s renderer.
  4. The compromised renderer invokes client->OnReceiveRedirect on the acquired Mojo remote, supplying a forged net::RedirectInfo targeting https://victim.com/secret.
  5. WorkerScriptLoader stores the redirect without validating that the original scheme was blob:. WorkerScriptFetcher auto-follows, and WorkerScriptLoader::FollowRedirect updates the request URL to https://victim.com/secret and restarts.
  6. The browser-side ServiceWorkerMainResourceLoaderInterceptor runs InitializeForRequest on the redirected URL. Since no response has committed yet, is_response_committed() is false, allowing the browser to update the worker’s ServiceWorkerClient URL and key to the victim’s origin (partitioned under https://evil.com).
  7. The interceptor lookup succeeds for a partitioned Service Worker matching the victim’s origin, dispatches a FetchEvent to the victim’s Service Worker for https://victim.com/secret, and returns the cross-origin response data pipe directly back to the attacker’s renderer via client_->OnScriptLoadStarted.

Impact

A compromised renderer can potentially bypass Site Isolation and leak cross-origin data by forcing the browser to execute a cross-origin fetch through a victim’s partitioned Service Worker and retrieve its response body.


Suggested Fix

Enforce scheme validation inside WorkerScriptLoader::OnReceiveRedirect similar to the navigation loader. Reject any redirect attempt if the original request URL scheme is a blob URL:

void WorkerScriptLoader::OnReceiveRedirect(
    const net::RedirectInfo& redirect_info,
    network::mojom::URLResponseHeadPtr response_head) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  
  if (resource_request_.url.SchemeIsBlob()) {
    complete_status_ = network::URLLoaderCompletionStatus(net::ERR_UNSAFE_REDIRECT);
    CommitCompleted();
    return;
  }
  
  if (--redirect_limit_ == 0) {
    complete_status_ = network::URLLoaderCompletionStatus(net::ERR_TOO_MANY_REDIRECTS);
    CommitCompleted();
    return;
  }

  redirect_info_ = redirect_info;
  client_->OnReceiveRedirect(redirect_info, std::move(response_head));
}

Evaluated with Chrome root at commit: 84065d9121f6e48f67755f0ae963cc09617e5c85


Results so far have been promising, but there can be wrong deductions. Feel free to adjust as follows:

  • If you are familiar with the severity guidelines, you may adjust the severity.
  • If this is a false positive, and there’s no work to be done, please close as WAI.
  • If there is work to do here but not a vulnerability, please change the issue type to Task/Bug/FR.

Data from false positives will be used to improve accuracy over time. And please feel free to reach out to me directly if you have concerns or feedback on the project.

View on issue tracker