Chrome · Extensions
CVE-2026-79017
Race in Extensions
Overview
Low
Severity
—
CVSS
No
Exploited ITW
Fixed
Fix Status
Changed Functions
| Function | Change | Notes |
|---|---|---|
ExtensionApiPdfTestchrome/browser/extensions/api/tabs/tabs_test.cc |
modified |
Files Changed
chrome/browser/extensions/api/tabs/tabs_api.ccchrome/browser/extensions/api/tabs/tabs_test.cc
Patch
From b500751eac4a405ec8c988c29db0c2c7edd714a7 Mon Sep 17 00:00:00 2001
From: Devlin Cronin <rdevlin.cronin@chromium.org>
Date: Wed, 15 Jul 2026 11:43:37 -0700
Subject: [PATCH] [Extensions] Use GetLastCommittedURL() in tabs zoom functions
Changing the zoom settings for a tab affects the zoom settings for the
frame's origin, which uses the committed origin. However, the check
compared visible URL to see if it was a restricted URL. This would
allow an extension to zoom a tab on a restricted URL if the visible
URL differed (such as if a user navigation was under way).
Fix this so that the tabs zoom checks use the last committed URL, and
add a regression test.
Fixed: 533021205
Change-Id: I0dfbf22eec7ae1e08c0619f00c8dac9862bf3f92
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/8087626
Commit-Queue: Devlin Cronin <rdevlin.cronin@chromium.org>
Reviewed-by: Andrea Orru <andreaorru@chromium.org>
Auto-Submit: Devlin Cronin <rdevlin.cronin@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1662763}
---
diff --git a/chrome/browser/extensions/api/tabs/tabs_api.cc b/chrome/browser/extensions/api/tabs/tabs_api.cc
index 3e365131..efc8a9e 100644
--- a/chrome/browser/extensions/api/tabs/tabs_api.cc
+++ b/chrome/browser/extensions/api/tabs/tabs_api.cc
@@ -3938,7 +3938,7 @@
return RespondNow(Error(std::move(error)));
}
- GURL url(web_contents->GetVisibleURL());
+ const GURL& url = web_contents->GetLastCommittedURL();
if (extension()->permissions_data()->IsRestrictedUrl(url, &error)) {
return RespondNow(Error(std::move(error)));
}
@@ -4000,7 +4000,7 @@
return RespondNow(Error(std::move(error)));
}
- GURL url(web_contents->GetVisibleURL());
+ const GURL& url = web_contents->GetLastCommittedURL();
if (extension()->permissions_data()->IsRestrictedUrl(url, &error)) {
return RespondNow(Error(std::move(error)));
}
diff --git a/chrome/browser/extensions/api/tabs/tabs_test.cc b/chrome/browser/extensions/api/tabs/tabs_test.cc
index d3bc73d..991a9617 100644
--- a/chrome/browser/extensions/api/tabs/tabs_test.cc
+++ b/chrome/browser/extensions/api/tabs/tabs_test.cc
@@ -3178,9 +3178,8 @@
error = RunSetZoomSettingsExpectError(bogus_id, "manual", "per-tab");
EXPECT_TRUE(base::MatchPattern(error, ExtensionTabUtil::kTabNotFoundError));
- const char kNewTestTabArgs[] = "chrome://version";
- params = GetOpenParams(kNewTestTabArgs);
- web_contents = browser()->OpenURL(params, /*navigation_handle_callback=*/{});
+ const char kNewTestTabArgs[] = "chrome://version/";
+ web_contents = OpenUrlAndWaitForLoad(GURL(kNewTestTabArgs));
tab_id = ExtensionTabUtil::GetTabId(web_contents);
// Test chrome.tabs.setZoom().
@@ -3194,6 +3193,44 @@
base::MatchPattern(error, manifest_errors::kCannotAccessChromeUrl));
}
+// Tests that tabs.zoom properly looks at the committed (not visible) URLs.
+// Regression test for crbug.com/533021205.
+IN_PROC_BROWSER_TEST_F(ExtensionTabsZoomTest,
+ ZoomingRestrictedURLsChecksCommittedURL) {
+ ASSERT_TRUE(embedded_test_server()->Start());
+
+ // Open a restricted URL and wait for it to load.
+ const char kRestrictedUrl[] = "chrome://version/";
+ content::WebContents* web_contents =
+ OpenUrlAndWaitForLoad(GURL(kRestrictedUrl));
+ int tab_id = ExtensionTabUtil::GetTabId(web_contents);
+
+ ASSERT_EQ(GURL(kRestrictedUrl), web_contents->GetLastCommittedURL());
+ ASSERT_EQ(GURL(kRestrictedUrl), web_contents->GetVisibleURL());
+
+ // Start a browser-initiated navigation to an unrestricted URL, but do not
+ // wait for it to commit.
+ GURL unrestricted_url = embedded_test_server()->GetURL("/title1.html");
+ content::NavigationController::LoadURLParams load_params(unrestricted_url);
+ web_contents->GetController().LoadURLWithParams(load_params);
+
+ // The visible URL should update immediately to the pending navigation target.
+ ASSERT_EQ(unrestricted_url, web_contents->GetVisibleURL());
+ // The committed URL should still be the restricted one.
+ ASSERT_EQ(GURL(kRestrictedUrl), web_contents->GetLastCommittedURL());
+
+ // Attempt to set zoom. It should fail because the committed URL is
+ // restricted.
+ std::string error = RunSetZoomExpectError(tab_id, 3.14159);
+ EXPECT_TRUE(
+ base::MatchPattern(error, manifest_errors::kCannotAccessChromeUrl));
+
+ // Attempt to set zoom settings. It should also fail.
+ error = RunSetZoomSettingsExpectError(tab_id, "manual", "per-tab");
+ EXPECT_TRUE(
+ base::MatchPattern(error, manifest_errors::kCannotAccessChromeUrl));
+}
+
#if BUILDFLAG(ENABLE_PDF)
class ExtensionApiPdfTest : public base::test::WithFeatureOverride,
public PDFExtensionTestBase {
Loading diff…
Regression Test / PoC
shipped with the fix
diff --git a/chrome/browser/extensions/api/tabs/tabs_test.cc b/chrome/browser/extensions/api/tabs/tabs_test.cc
index d3bc73d..991a9617 100644
--- a/chrome/browser/extensions/api/tabs/tabs_test.cc
+++ b/chrome/browser/extensions/api/tabs/tabs_test.cc
@@ -3178,9 +3178,8 @@
error = RunSetZoomSettingsExpectError(bogus_id, "manual", "per-tab");
EXPECT_TRUE(base::MatchPattern(error, ExtensionTabUtil::kTabNotFoundError));
- const char kNewTestTabArgs[] = "chrome://version";
- params = GetOpenParams(kNewTestTabArgs);
- web_contents = browser()->OpenURL(params, /*navigation_handle_callback=*/{});
+ const char kNewTestTabArgs[] = "chrome://version/";
+ web_contents = OpenUrlAndWaitForLoad(GURL(kNewTestTabArgs));
tab_id = ExtensionTabUtil::GetTabId(web_contents);
// Test chrome.tabs.setZoom().
@@ -3194,6 +3193,44 @@
base::MatchPattern(error, manifest_errors::kCannotAccessChromeUrl));
}
+// Tests that tabs.zoom properly looks at the committed (not visible) URLs.
+// Regression test for crbug.com/533021205.
+IN_PROC_BROWSER_TEST_F(ExtensionTabsZoomTest,
+ ZoomingRestrictedURLsChecksCommittedURL) {
+ ASSERT_TRUE(embedded_test_server()->Start());
+
+ // Open a restricted URL and wait for it to load.
+ const char kRestrictedUrl[] = "chrome://version/";
+ content::WebContents* web_contents =
+ OpenUrlAndWaitForLoad(GURL(kRestrictedUrl));
+ int tab_id = ExtensionTabUtil::GetTabId(web_contents);
+
+ ASSERT_EQ(GURL(kRestrictedUrl), web_contents->GetLastCommittedURL());
+ ASSERT_EQ(GURL(kRestrictedUrl), web_contents->GetVisibleURL());
+
+ // Start a browser-initiated navigation to an unrestricted URL, but do not
+ // wait for it to commit.
+ GURL unrestricted_url = embedded_test_server()->GetURL("/title1.html");
+ content::NavigationController::LoadURLParams load_params(unrestricted_url);
+ web_contents->GetController().LoadURLWithParams(load_params);
+
+ // The visible URL should update immediately to the pending navigation target.
+ ASSERT_EQ(unrestricted_url, web_contents->GetVisibleURL());
+ // The committed URL should still be the restricted one.
+ ASSERT_EQ(GURL(kRestrictedUrl), web_contents->GetLastCommittedURL());
+
+ // Attempt to set zoom. It should fail because the committed URL is
+ // restricted.
+ std::string error = RunSetZoomExpectError(tab_id, 3.14159);
+ EXPECT_TRUE(
+ base::MatchPattern(error, manifest_errors::kCannotAccessChromeUrl));
+
+ // Attempt to set zoom settings. It should also fail.
+ error = RunSetZoomSettingsExpectError(tab_id, "manual", "per-tab");
+ EXPECT_TRUE(
+ base::MatchPattern(error, manifest_errors::kCannotAccessChromeUrl));
+}
+
#if BUILDFLAG(ENABLE_PDF)
class ExtensionApiPdfTest : public base::test::WithFeatureOverride,
public PDFExtensionTestBase {
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