Overview

Low
Severity
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactInappropriate implementation in Permissions
DescriptionInappropriate implementation in Permissions
ComponentPermissions
Bug ClassLogic Error
Tracker498405554
Fix commit399c4bfed9ec (chromium/src) +26/-1
CISA KEVNot listed
CreditedGoogle
Disclosed2026-06-02

Changed Functions

FunctionChangeNotes
TEST_F
chrome/browser/content_settings/one_time_permission_provider_unittest.cc
modified

Files Changed

  • chrome/browser/content_settings/one_time_permission_provider.cc
  • chrome/browser/content_settings/one_time_permission_provider_unittest.cc
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,
Loading diff…

Regression Test / PoC

shipped with the fix
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,
Loading diff…

Original Bug Report

reported by [email protected]

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.

  1. The user navigates to a malicious site (e.g., https://attacker.example) that requests camera access.
  2. The user selects “Allow this time” on the permission prompt.
  3. The attacker’s site gains camera access and intentionally keeps the tab active (e.g., in the background).
  4. The user, wishing to revoke all access, navigates to chrome://settings/clearBrowserData and clears “Site settings” for the “All time” time range (or performs a “Restore settings to their original defaults”).
  5. This triggers HostContentSettingsMap::ClearSettingsForOneType, which calls the flawed ClearAllContentSettingsRules method on all providers.
  6. Due to the bug, the OneTimePermissionProvider fails to clear the grant.
  7. The user switches back to the attacker’s tab.
  8. The attacker’s page executes navigator.mediaDevices.getUserMedia({video: true}) again (or simply performs a same-origin reload).
  9. 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.

View on issue tracker