Chrome · Receiver
CVE-2026-17776
Logic Error in Receiver
Overview
Medium
Severity
—
CVSS
No
Exploited ITW
Fixed
Fix Status
Changed Functions
| Function | Change | Notes |
|---|---|---|
forcomponents/url_rewrite/common/url_loader_throttle.cc |
modified | |
ifcomponents/url_rewrite/common/url_loader_throttle.cc |
modified | |
TEST_Fcomponents/url_rewrite/common/url_loader_throttle_unittest.cc |
modified |
Files Changed
components/url_rewrite/common/url_loader_throttle.cccomponents/url_rewrite/common/url_loader_throttle_unittest.cc
Patch
From 3bf03fd44bc60a251de356c5010e2172d7d84923 Mon Sep 17 00:00:00 2001 From: Muyao Xu <[email protected]> Date: Wed, 24 Jun 2026 12:04:10 -0700 Subject: [PATCH] Always Reevaluate access policies if a rule changes the URL URLLoaderThrottle was evaluating embedder-defined access policies (kAllow/kDeny) only once on the initial request URL. If rewrite rules were applied sequentially, a rule could mutate the URL to a denied host without triggering a policy re-check. This CL updates WillStartRequest to re-evaluate the access policy on the mutated request URL if a rule changes the URL. Bug: 513404032 Change-Id: Ie251b72920383cc0e94334e17a2bc19af93f40e3 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7923228 Reviewed-by: David Song <[email protected]> Commit-Queue: Muyao Xu <[email protected]> Cr-Commit-Position: refs/heads/main@{#1651875} --- diff --git a/components/url_rewrite/common/url_loader_throttle.cc b/components/url_rewrite/common/url_loader_throttle.cc index 8579d1b..5eca3303 100644 --- a/components/url_rewrite/common/url_loader_throttle.cc +++ b/components/url_rewrite/common/url_loader_throttle.cc @@ -193,8 +193,18 @@ return; } - for (const auto& rule : rules_->data->rules) + GURL current_url = request->url; + for (const auto& rule : rules_->data->rules) { ApplyRule(request, rule); + if (request->url != current_url) { + if (!IsRequestAllowed(request, rules_->data)) { + delegate_->CancelWithError(net::ERR_ABORTED, + "Resource load blocked by embedder policy."); + return; + } + current_url = request->url; + } + } if (!added_headers_.empty()) { original_origin_ = url::Origin::Create(request->url); diff --git a/components/url_rewrite/common/url_loader_throttle_unittest.cc b/components/url_rewrite/common/url_loader_throttle_unittest.cc index f4f062b..4646160e 100644 --- a/components/url_rewrite/common/url_loader_throttle_unittest.cc +++ b/components/url_rewrite/common/url_loader_throttle_unittest.cc @@ -408,4 +408,49 @@ } } +TEST_F(URLLoaderThrottleTest, ReplaceUrlReevaluatesPolicy) { + mojom::UrlRequestRewriteRulesPtr rules = mojom::UrlRequestRewriteRules::New(); + + { + mojom::UrlRequestRewriteReplaceUrlPtr replace_url = + mojom::UrlRequestRewriteReplaceUrl::New(); + replace_url->url_ends_with = "/partner-endpoint"; + replace_url->new_url = GURL("http://internal.host/api"); + + mojom::UrlRequestRulePtr rule = mojom::UrlRequestRule::New(); + rule->hosts_filter = + std::optional<std::vector<std::string>>({"allowed.com"}); + rule->actions.push_back( + mojom::UrlRequestAction::NewReplaceUrl(std::move(replace_url))); + rules->rules.push_back(std::move(rule)); + } + + { + mojom::UrlRequestRulePtr rule = mojom::UrlRequestRule::New(); + rule->hosts_filter = + std::optional<std::vector<std::string>>({"internal.host"}); + rule->actions.push_back(mojom::UrlRequestAction::NewPolicy( + mojom::UrlRequestAccessPolicy::kDeny)); + rules->rules.push_back(std::move(rule)); + } + + TestThrottleDelegate delegate; + URLLoaderThrottle throttle( + base::MakeRefCounted<UrlRequestRewriteRules>(std::move(rules)), + CreateCorsExemptHeadersCallback({})); + throttle.set_delegate(&delegate); + + bool unused_defer = false; + + // Request to allowed.com/partner-endpoint should be rewritten to + // internal.host, which is denied, thus the request should be canceled. + network::ResourceRequest request; + request.url = GURL("http://allowed.com/partner-endpoint?q=ATTACKER"); + throttle.WillStartRequest(&request, &unused_defer); + + EXPECT_TRUE(delegate.canceled()); + EXPECT_EQ(delegate.cancel_reason(), + "Resource load blocked by embedder policy."); +} + } // namespace url_rewrite
Loading diff…
Regression Test / PoC
shipped with the fix
diff --git a/components/url_rewrite/common/url_loader_throttle_unittest.cc b/components/url_rewrite/common/url_loader_throttle_unittest.cc
index f4f062b..4646160e 100644
--- a/components/url_rewrite/common/url_loader_throttle_unittest.cc
+++ b/components/url_rewrite/common/url_loader_throttle_unittest.cc
@@ -408,4 +408,49 @@
}
}
+TEST_F(URLLoaderThrottleTest, ReplaceUrlReevaluatesPolicy) {
+ mojom::UrlRequestRewriteRulesPtr rules = mojom::UrlRequestRewriteRules::New();
+
+ {
+ mojom::UrlRequestRewriteReplaceUrlPtr replace_url =
+ mojom::UrlRequestRewriteReplaceUrl::New();
+ replace_url->url_ends_with = "/partner-endpoint";
+ replace_url->new_url = GURL("http://internal.host/api");
+
+ mojom::UrlRequestRulePtr rule = mojom::UrlRequestRule::New();
+ rule->hosts_filter =
+ std::optional<std::vector<std::string>>({"allowed.com"});
+ rule->actions.push_back(
+ mojom::UrlRequestAction::NewReplaceUrl(std::move(replace_url)));
+ rules->rules.push_back(std::move(rule));
+ }
+
+ {
+ mojom::UrlRequestRulePtr rule = mojom::UrlRequestRule::New();
+ rule->hosts_filter =
+ std::optional<std::vector<std::string>>({"internal.host"});
+ rule->actions.push_back(mojom::UrlRequestAction::NewPolicy(
+ mojom::UrlRequestAccessPolicy::kDeny));
+ rules->rules.push_back(std::move(rule));
+ }
+
+ TestThrottleDelegate delegate;
+ URLLoaderThrottle throttle(
+ base::MakeRefCounted<UrlRequestRewriteRules>(std::move(rules)),
+ CreateCorsExemptHeadersCallback({}));
+ throttle.set_delegate(&delegate);
+
+ bool unused_defer = false;
+
+ // Request to allowed.com/partner-endpoint should be rewritten to
+ // internal.host, which is denied, thus the request should be canceled.
+ network::ResourceRequest request;
+ request.url = GURL("http://allowed.com/partner-endpoint?q=ATTACKER");
+ throttle.WillStartRequest(&request, &unused_defer);
+
+ EXPECT_TRUE(delegate.canceled());
+ EXPECT_EQ(delegate.cancel_reason(),
+ "Resource load blocked by embedder policy.");
+}
+
} // namespace url_rewrite
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