CVE-2026-11254
Overview
Changed Functions
| Function | Change | Notes |
|---|---|---|
TEST_Fchrome/browser/content_settings/one_time_permission_provider_unittest.cc |
modified |
Files Changed
chrome/browser/content_settings/one_time_permission_provider.ccchrome/browser/content_settings/one_time_permission_provider_unittest.cc
Patch
From 399c4bfed9ec95a89c228aea2a51fe0fda282323 Mon Sep 17 00:00:00 2001 From: Antonio Sartori <[email protected]> Date: Tue, 07 Apr 2026 07:01:03 -0700 Subject: [PATCH] [permissions] Fix OnTimePermissionProvider::ClearAllContentSettingsRules This CL fixes a guard in OnTimePermissionProvider which made ClearAllContentSettingsRules do nothing. Bug: 498405554 Change-Id: I4e3c3ffc3e7c0aa4756527d84e6b1e600269858e Fixed: 498405554 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7735621 Reviewed-by: Christian Dullweber <[email protected]> Commit-Queue: Antonio Sartori <[email protected]> Cr-Commit-Position: refs/heads/main@{#1610719} --- diff --git a/chrome/browser/content_settings/one_time_permission_provider.cc b/chrome/browser/content_settings/one_time_permission_provider.cc index fd319eb..2b19ecc5 100644 --- a/chrome/browser/content_settings/one_time_permission_provider.cc +++ b/chrome/browser/content_settings/one_time_permission_provider.cc @@ -199,7 +199,7 @@ void OneTimePermissionProvider::ClearAllContentSettingsRules( ContentSettingsType content_type) { - if (permissions::PermissionUtil::DoesStoreTemporaryGrantsInHcsm( + if (!permissions::PermissionUtil::DoesStoreTemporaryGrantsInHcsm( content_type)) { return; } diff --git a/chrome/browser/content_settings/one_time_permission_provider_unittest.cc b/chrome/browser/content_settings/one_time_permission_provider_unittest.cc index 3c46ff6..efa839b 100644 --- a/chrome/browser/content_settings/one_time_permission_provider_unittest.cc +++ b/chrome/browser/content_settings/one_time_permission_provider_unittest.cc @@ -148,6 +148,31 @@ ContentSettingsType::GEOLOCATION, false)); } +TEST_F(OneTimePermissionProviderTest, ClearAll) { + EXPECT_EQ(CONTENT_SETTING_DEFAULT, + TestUtils::GetContentSetting( + one_time_permission_provider_.get(), primary_url, secondary_url, + ContentSettingsType::GEOLOCATION, false)); + + one_time_permission_provider_->SetWebsiteSetting( + primary_pattern, ContentSettingsPattern::Wildcard(), + ContentSettingsType::GEOLOCATION, base::Value(CONTENT_SETTING_ALLOW), + one_time_constraints()); + + EXPECT_EQ(CONTENT_SETTING_ALLOW, + TestUtils::GetContentSetting( + one_time_permission_provider_.get(), primary_url, secondary_url, + ContentSettingsType::GEOLOCATION, false)); + + one_time_permission_provider_->ClearAllContentSettingsRules( + ContentSettingsType::GEOLOCATION); + + EXPECT_EQ(CONTENT_SETTING_DEFAULT, + TestUtils::GetContentSetting( + one_time_permission_provider_.get(), primary_url, secondary_url, + ContentSettingsType::GEOLOCATION, false)); +} + TEST_F(OneTimePermissionProviderTest, SetAndGetContentSettingWithoutOneTimeCapabilityDoesNotAllow) { EXPECT_EQ(CONTENT_SETTING_DEFAULT,
Regression Test / PoC
diff --git a/chrome/browser/content_settings/one_time_permission_provider_unittest.cc b/chrome/browser/content_settings/one_time_permission_provider_unittest.cc
index 3c46ff6..efa839b 100644
--- a/chrome/browser/content_settings/one_time_permission_provider_unittest.cc
+++ b/chrome/browser/content_settings/one_time_permission_provider_unittest.cc
@@ -148,6 +148,31 @@
ContentSettingsType::GEOLOCATION, false));
}
+TEST_F(OneTimePermissionProviderTest, ClearAll) {
+ EXPECT_EQ(CONTENT_SETTING_DEFAULT,
+ TestUtils::GetContentSetting(
+ one_time_permission_provider_.get(), primary_url, secondary_url,
+ ContentSettingsType::GEOLOCATION, false));
+
+ one_time_permission_provider_->SetWebsiteSetting(
+ primary_pattern, ContentSettingsPattern::Wildcard(),
+ ContentSettingsType::GEOLOCATION, base::Value(CONTENT_SETTING_ALLOW),
+ one_time_constraints());
+
+ EXPECT_EQ(CONTENT_SETTING_ALLOW,
+ TestUtils::GetContentSetting(
+ one_time_permission_provider_.get(), primary_url, secondary_url,
+ ContentSettingsType::GEOLOCATION, false));
+
+ one_time_permission_provider_->ClearAllContentSettingsRules(
+ ContentSettingsType::GEOLOCATION);
+
+ EXPECT_EQ(CONTENT_SETTING_DEFAULT,
+ TestUtils::GetContentSetting(
+ one_time_permission_provider_.get(), primary_url, secondary_url,
+ ContentSettingsType::GEOLOCATION, false));
+}
+
TEST_F(OneTimePermissionProviderTest,
SetAndGetContentSettingWithoutOneTimeCapabilityDoesNotAllow) {
EXPECT_EQ(CONTENT_SETTING_DEFAULT,
Original Bug Report
Privacy bypass: Inverted guard in OneTimePermissionProvider prevents clearing grants
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 without the security team.
Overview: A potential logic error exists in OneTimePermissionProvider::ClearAllContentSettingsRules due to an inverted conditional guard. This flaw causes the provider to return early when attempting to clear the exact content types it manages, such as camera and microphone one-time grants. As a result, ephemeral permissions survive “Clear Browsing Data (All Time)” and “Profile Reset” operations if the originating tab remains open.
Affected files:
chrome/browser/content_settings/one_time_permission_provider.cc
Estimated timestamp from git blame: 2024-06-18
Summary
Chrome’s OneTimePermissionProvider manages ephemeral “Allow this time” grants for sensitive permissions like Geolocation, Camera, and Microphone. When a user performs a global privacy reset (such as clearing browsing data for “All Time” or resetting their profile), these grants are supposed to be wiped from memory.
However, a potential logic error in the code prevents this from happening. A missing negation (!) in a guard condition causes the provider to abort the clearing process for the exact permission types it is responsible for managing. Consequently, an attacker who keeps their tab active can retain access to sensitive sensors even after the user explicitly clears their site data.
Root Cause
The issue is located in chrome/browser/content_settings/one_time_permission_provider.cc within the ClearAllContentSettingsRules function:
void OneTimePermissionProvider::ClearAllContentSettingsRules(
ContentSettingsType content_type) {
if (permissions::PermissionUtil::DoesStoreTemporaryGrantsInHcsm(
content_type)) {
return; // INVERTED GUARD: Returns early for types it manages!
}
base::AutoLock lock(value_map_.GetLock());
value_map_.DeleteValues(content_type);
}
For one-time permissions like MEDIASTREAM_CAMERA, DoesStoreTemporaryGrantsInHcsm(content_type) correctly evaluates to true. Because the if statement lacks a logical NOT (!), the condition evaluates to true, causing the function to immediately return.
This skips the value_map_.DeleteValues(content_type) call entirely. In all other methods within this class (e.g., GetRule, SetWebsiteSetting), the guard is correctly written as if (!permissions::PermissionUtil::DoesStoreTemporaryGrantsInHcsm(content_type)).
Potential Reproduction Steps
Note: These are suggested steps to trigger the vulnerability based on static analysis; our tooling agent does not yet have the ability to run code or execute a live proof-of-concept.
- The user navigates to a malicious site (e.g.,
https://attacker.example) that requests camera access. - The user selects “Allow this time” on the permission prompt.
- The attacker’s site gains camera access and intentionally keeps the tab active (e.g., in the background).
- The user, wishing to revoke all access, navigates to
chrome://settings/clearBrowserDataand clears “Site settings” for the “All time” time range (or performs a “Restore settings to their original defaults”). - This triggers
HostContentSettingsMap::ClearSettingsForOneType, which calls the flawedClearAllContentSettingsRulesmethod on all providers. - Due to the bug, the
OneTimePermissionProviderfails to clear the grant. - The user switches back to the attacker’s tab.
- The attacker’s page executes
navigator.mediaDevices.getUserMedia({video: true})again (or simply performs a same-origin reload). - Chrome silently grants the permission using the stale in-memory rule, completely bypassing the user’s explicit privacy reset.
Suggested Fix
Correct the guard condition in OneTimePermissionProvider::ClearAllContentSettingsRules by adding the missing negation (!), matching the pattern used in the rest of the class:
void OneTimePermissionProvider::ClearAllContentSettingsRules(
ContentSettingsType content_type) {
if (!permissions::PermissionUtil::DoesStoreTemporaryGrantsInHcsm(
content_type)) {
return;
}
base::AutoLock lock(value_map_.GetLock());
value_map_.DeleteValues(content_type);
}
Evaluated with Chrome root at commit: ff3d2b74fa39431785bd60e51463b08fcc71ee33
Results so far have been promising, but there can be wrong deductions. If this proves to be a false positive, please close as WAI; 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.