High watch CVSS 8.8 chrome UAF 📄 Reporter bug report 🔧 Commit mapped

Overview

High
Severity
8.8
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactUse after free in Extensions
DescriptionUse after free in Extensions
ComponentExtensions
Sub-componentExtensions
Bug ClassUAF
Action tierwatch — corruption primitive but gated (uncommon) — not default-reachable
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.
Tracker489619753
Fix commit98a65b0c6572 (chromium/src) +57/-5
CWECWE-416 (Use-after-free)
CVSS vectorCVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H
CISA KEVNot listed
CreditedShaheen Fazim
Reported2026-03-04 (per vendor advisory)
Fix landed2026-03-06 (public git)
Disclosed2026-03-18
Patch gap12 days — fix public in source before the advisory

Background

Declarative rules registry
RulesRegistry is the browser-side store for rules that extensions add and remove through declarative event APIs; RulesRegistry::RemoveRules() is the generic entry point and delegates to a subclass’s RemoveRulesImpl().
`ChromeContentRulesRegistry`
the declarativeContent registry that keeps rules in content_rules_, a map keyed by (extension_id, rule_id).
Iterator invalidation on erase
erasing a node-based map element frees that node, so a second erase() through an iterator to the same element operates on freed memory.
`rule_identifiers`
the caller-supplied list of rule IDs to remove, which before the patch was used as-is and could contain duplicates.

Root Cause Analysis

ChromeContentRulesRegistry::RemoveRulesImpl() looped over rule_identifiers, looked each one up with content_rules_.find(std::make_pair(extension_id, id)), and collected the resulting iterators in std::vector<RulesMap::iterator> rules_to_erase for later erasure. Because the input was not deduplicated, a list such as {"rule1", "rule1"} pushed the same iterator twice; per the commit message, the second erase operates on the now-dangling iterator, causing a heap use-after-free. The violated invariant is that each map element is erased exactly once, which requires the ID list to be a set.

The fix deduplicates at two layers: RemoveRulesImpl() now iterates a std::set<std::string> deduplicated_rule_identifiers, and RulesRegistry::RemoveRules() (identified by the commit message; the hunk header shows only its parameter list) sorts and std::uniques a copy of rule_identifiers and passes that copy to the manifest-rule check, RemoveRulesImpl(), the rules_.erase() loop, and RemoveUsedRuleIdentifiers(). The deduplication runs before any lookup or erase, so the duplicate never reaches the iterator vector.

Key insight
An untrusted list of rule IDs was treated as unique, so duplicate IDs produced duplicate map iterators that were erased twice; the fix deduplicates the IDs before any lookup or erase.

Attack Path

  1. Install an extension using declarative rules the attacker controls an installed extension that can add declarativeContent rules (the test uses a page_action extension with a declarativeContent.PageStateMatcher rule).
  2. Add a rule the extension registers a rule with a known ID (e.g. "rule1").
  3. Remove with duplicate IDs the extension requests removal with a list containing the same ID more than once, which flows through RulesRegistry::RemoveRules() into ChromeContentRulesRegistry::RemoveRulesImpl().
  4. Double erase the same content_rules_ iterator is collected twice in rules_to_erase and erased twice, the second time on a freed node in the browser process; leveraging this for further memory corruption is (inferred).

Impact Assessment

The use-after-free occurs in the browser process, which hosts the rules registries; any exploitation beyond memory corruption (e.g. code execution) is (inferred). The precondition is a malicious or compromised installed extension that can call the declarative rules API (ordinary web content does not reach this path per the diff). The vendor rates this as high severity; the advisory provided does not state in-the-wild exploitation.

Changed Functions

FunctionChangeNotes
for
chrome/browser/extensions/api/declarative_content/chrome_content_rules_registry.cc
modified
TEST_F
chrome/browser/extensions/api/declarative_content/chrome_content_rules_registry_unittest.cc
modified
for
extensions/browser/api/declarative/rules_registry.cc
modified

Files Changed

  • chrome/browser/extensions/api/declarative_content/chrome_content_rules_registry.cc
  • chrome/browser/extensions/api/declarative_content/chrome_content_rules_registry_unittest.cc
  • extensions/browser/api/declarative/rules_registry.cc

Audit Directions

  • Other `RemoveRulesImpl` overrides and direct callers
    check other RulesRegistry subclasses (e.g. declarative web request registries) and any code that calls RemoveRulesImpl() directly, bypassing the new deduplication in RulesRegistry::RemoveRules().
  • Collect-then-erase iterator patterns
    search for code that gathers map/set iterators into a vector from caller-supplied keys and erases them later; duplicate keys or overlapping ranges yield double erases.
  • Extension-supplied ID lists
    audit other extension APIs that accept arrays of IDs (rules, alarms, context menus, tabs) for assumptions of uniqueness before lookups and deletions.
From 98a65b0c6572e8263e7d5a9cf91e9cba5d4d1350 Mon Sep 17 00:00:00 2001
From: Andrea Orru <[email protected]>
Date: Fri, 06 Mar 2026 15:50:15 -0800
Subject: [PATCH] [Extensions] Deduplicate rule identifiers in RemoveRules

When removing declarative content rules, a given list of rule
identifiers may contain duplicates. Both RulesRegistry::RemoveRules and
ChromeContentRulesRegistry::RemoveRulesImpl previously processed the
incoming rule_identifiers list without deduplicating it.

When the same rule ID appears multiple times, the function looks up the
same map iterator multiple times, and the second erase call on the same
(now-dangling) iterator results in a heap-use-after-free.

This CL creates a deduplicated vector to ensure each rule ID is
processed and erased exactly once, preventing memory corruption.

Fixed: 489619753
Change-Id: Ib23e3b9771fdd64d3e1342ddc8d097d5ebc0cc04
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7644438
Reviewed-by: Devlin Cronin <[email protected]>
Commit-Queue: Andrea Orru <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1595764}
---

diff --git a/chrome/browser/extensions/api/declarative_content/chrome_content_rules_registry.cc b/chrome/browser/extensions/api/declarative_content/chrome_content_rules_registry.cc
index 2b0263b..bf9e03f 100644
--- a/chrome/browser/extensions/api/declarative_content/chrome_content_rules_registry.cc
+++ b/chrome/browser/extensions/api/declarative_content/chrome_content_rules_registry.cc
@@ -324,9 +324,14 @@
   // rule multiple times.
   EvaluationScope evaluation_scope(this, IGNORE_REQUESTS);
 
+  // Deduplicate the list of rule identifiers to prevent removing the same
+  // rule multiple times and invalidating iterators.
+  std::set<std::string> deduplicated_rule_identifiers(rule_identifiers.begin(),
+                                                      rule_identifiers.end());
+
   std::vector<RulesMap::iterator> rules_to_erase;
   std::vector<const void*> predicate_groups_to_stop_tracking;
-  for (const std::string& id : rule_identifiers) {
+  for (const std::string& id : deduplicated_rule_identifiers) {
     // Skip unknown rules.
     auto content_rules_entry =
         content_rules_.find(std::make_pair(extension_id, id));
diff --git a/chrome/browser/extensions/api/declarative_content/chrome_content_rules_registry_unittest.cc b/chrome/browser/extensions/api/declarative_content/chrome_content_rules_registry_unittest.cc
index 7b767eb..9c486ba 100644
--- a/chrome/browser/extensions/api/declarative_content/chrome_content_rules_registry_unittest.cc
+++ b/chrome/browser/extensions/api/declarative_content/chrome_content_rules_registry_unittest.cc
@@ -219,4 +219,38 @@
   EXPECT_EQ(0u, registry->GetActiveRulesCountForTesting());
 }
 
+TEST_F(DeclarativeChromeContentRulesRegistryTest, RemoveDuplicateRules) {
+  TestPredicateEvaluator* evaluator = nullptr;
+  scoped_refptr<ChromeContentRulesRegistry> registry(
+      new ChromeContentRulesRegistry(
+          env()->profile(), nullptr,
+          base::BindOnce(&CreateTestEvaluator, &evaluator)));
+
+  auto rule = api::events::Rule::FromValue(base::test::ParseJsonDict(R"({
+          "id": "rule1",
+          "priority": 100,
+          "conditions": [
+           {
+             "instanceType": "declarativeContent.PageStateMatcher",
+             "test_predicate": []
+           }],
+          "actions": [
+            {"instanceType": "declarativeContent.ShowAction"}
+          ]
+      })"));
+  ASSERT_TRUE(rule.has_value());
+  std::vector<const api::events::Rule*> rules({&rule.value()});
+
+  const Extension* extension =
+      env()->MakeExtension(base::test::ParseJsonDict("{\"page_action\": {}}"));
+  registry->AddRulesImpl(extension->id(), rules);
+
+  // Removing duplicate rule IDs should not cause memory corruption.
+  // This test validates that passing the same rule ID multiple times
+  // into RemoveRulesImpl does not result in the same internal rule
+  // iterator being erased more than once.
+  std::vector<std::string> remove_rules_dup = {"rule1", "rule1"};
+  registry->RemoveRulesImpl(extension->id(), remove_rules_dup);
+}
+
 }  // namespace extensions
diff --git a/extensions/browser/api/declarative/rules_registry.cc b/extensions/browser/api/declarative/rules_registry.cc
index 81159eae..8419a16 100644
--- a/extensions/browser/api/declarative/rules_registry.cc
+++ b/extensions/browser/api/declarative/rules_registry.cc
@@ -4,6 +4,7 @@
 
 #include "extensions/browser/api/declarative/rules_registry.h"
 
+#include <algorithm>
 #include <memory>
 #include <utility>
 
@@ -165,26 +166,38 @@
     const std::vector<std::string>& rule_identifiers) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
+  // Deduplicate the list of rule identifiers to prevent removing the same
+  // rule multiple times and invalidating iterators.
+  std::vector<std::string> deduplicated_rule_identifiers = rule_identifiers;
+  std::sort(deduplicated_rule_identifiers.begin(),
+            deduplicated_rule_identifiers.end());
+  deduplicated_rule_identifiers.erase(
+      std::unique(deduplicated_rule_identifiers.begin(),
+                  deduplicated_rule_identifiers.end()),
+      deduplicated_rule_identifiers.end());
+
   // Check if any of the rules are non-removable.
-  for (const RuleId& rule_id : rule_identifiers) {
+  for (const RuleId& rule_id : deduplicated_rule_identifiers) {
     RulesDictionaryKey lookup_key(extension_id, rule_id);
     auto itr = manifest_rules_.find(lookup_key);
     if (itr != manifest_rules_.end())
       return kErrorCannotRemoveManifestRules;
   }
 
-  std::string error = RemoveRulesImpl(extension_id, rule_identifiers);
+  std::string error =
+      RemoveRulesImpl(extension_id, deduplicated_rule_identifiers);
 
   if (!error.empty())
     return error;
 
-  for (auto i = rule_identifiers.cbegin(); i != rule_identifiers.cend(); ++i) {
+  for (auto i = deduplicated_rule_identifiers.cbegin();
+       i != deduplicated_rule_identifiers.cend(); ++i) {
     RulesDictionaryKey lookup_key(extension_id, *i);
     rules_.erase(lookup_key);
   }
 
   MaybeProcessChangedRules(extension_id);
-  RemoveUsedRuleIdentifiers(extension_id, rule_identifiers);
+  RemoveUsedRuleIdentifiers(extension_id, deduplicated_rule_identifiers);
   return kSuccess;
 }
 
Loading diff…

Regression Test / PoC

shipped with the fix
diff --git a/chrome/browser/extensions/api/declarative_content/chrome_content_rules_registry_unittest.cc b/chrome/browser/extensions/api/declarative_content/chrome_content_rules_registry_unittest.cc
index 7b767eb..9c486ba 100644
--- a/chrome/browser/extensions/api/declarative_content/chrome_content_rules_registry_unittest.cc
+++ b/chrome/browser/extensions/api/declarative_content/chrome_content_rules_registry_unittest.cc
@@ -219,4 +219,38 @@
   EXPECT_EQ(0u, registry->GetActiveRulesCountForTesting());
 }
 
+TEST_F(DeclarativeChromeContentRulesRegistryTest, RemoveDuplicateRules) {
+  TestPredicateEvaluator* evaluator = nullptr;
+  scoped_refptr<ChromeContentRulesRegistry> registry(
+      new ChromeContentRulesRegistry(
+          env()->profile(), nullptr,
+          base::BindOnce(&CreateTestEvaluator, &evaluator)));
+
+  auto rule = api::events::Rule::FromValue(base::test::ParseJsonDict(R"({
+          "id": "rule1",
+          "priority": 100,
+          "conditions": [
+           {
+             "instanceType": "declarativeContent.PageStateMatcher",
+             "test_predicate": []
+           }],
+          "actions": [
+            {"instanceType": "declarativeContent.ShowAction"}
+          ]
+      })"));
+  ASSERT_TRUE(rule.has_value());
+  std::vector<const api::events::Rule*> rules({&rule.value()});
+
+  const Extension* extension =
+      env()->MakeExtension(base::test::ParseJsonDict("{\"page_action\": {}}"));
+  registry->AddRulesImpl(extension->id(), rules);
+
+  // Removing duplicate rule IDs should not cause memory corruption.
+  // This test validates that passing the same rule ID multiple times
+  // into RemoveRulesImpl does not result in the same internal rule
+  // iterator being erased more than once.
+  std::vector<std::string> remove_rules_dup = {"rule1", "rule1"};
+  registry->RemoveRulesImpl(extension->id(), remove_rules_dup);
+}
+
 }  // namespace extensions
Loading diff…

Original Bug Report

reported by [email protected]

heap-use-after-free in extensions::ChromeContentRulesRegistry::RemoveRulesImpl

=================================================================
==63616==ERROR: AddressSanitizer: heap-use-after-free on address 0x12170e631828 at pc 0x7ffa468cf5ba bp 0x00b79e3fd7e0 sp 0x00b79e3fd828
READ of size 8 at 0x12170e631828 thread T0
    #0 0x7ffa468cf5b9 in extensions::ChromeContentRulesRegistry::RemoveRulesImpl C:\b\s\w\ir\cache\builder\src\chrome\browser\extensions\api\declarative_content\chrome_content_rules_registry.cc:363
    #1 0x7ffa43b8d764 in extensions::RulesRegistry::RemoveRules C:\b\s\w\ir\cache\builder\src\extensions\browser\api\declarative\rules_registry.cc:176
    #2 0x7ffa43b84299 in extensions::EventsEventRemoveRulesFunction::RunInternal C:\b\s\w\ir\cache\builder\src\extensions\browser\api\declarative\declarative_api.cc:256
    #3 0x7ffa43b8229b in extensions::RulesFunction::Run C:\b\s\w\ir\cache\builder\src\extensions\browser\api\declarative\declarative_api.cc:193
    #4 0x7ffa43dddffa in ExtensionFunction::RunWithValidation C:\b\s\w\ir\cache\builder\src\extensions\browser\extension_function.cc:494
    #5 0x7ffa43dee30e in extensions::ExtensionFunctionDispatcher::DispatchWithCallbackInternal C:\b\s\w\ir\cache\builder\src\extensions\browser\extension_function_dispatcher.cc:458
    #6 0x7ffa43def06d in extensions::ExtensionFunctionDispatcher::DispatchForServiceWorker C:\b\s\w\ir\cache\builder\src\extensions\browser\extension_function_dispatcher.cc:248
    #7 0x7ffa43f60171 in extensions::ServiceWorkerHost::RequestWorker C:\b\s\w\ir\cache\builder\src\extensions\browser\service_worker\service_worker_host.cc:278
    #8 0x7ffa440ea7ad in extensions::mojom::ServiceWorkerHostStubDispatch::AcceptWithResponder C:\b\s\w\ir\cache\builder\src\out\069a-Win_ASan_Releas\gen\extensions\common\mojom\service_worker_host.mojom.cc:1648
    #9 0x7ffa43f638dc in extensions::mojom::ServiceWorkerHostStub<mojo::RawPtrImplRefTraits<extensions::mojom::ServiceWorkerHost> >::AcceptWithResponder C:\b\s\w\ir\cache\builder\src\out\069a-Win_ASan_Releas\gen\extensions\common\mojom\service_worker_host.mojom.h:201
    #10 0x7ffa4baaa26d in mojo::InterfaceEndpointClient::HandleValidatedMessage C:\b\s\w\ir\cache\builder\src\mojo\public\cpp\bindings\lib\interface_endpoint_client.cc:1036
    #11 0x7ffa4baa703d in mojo::MessageDispatcher::Accept C:\b\s\w\ir\cache\builder\src\mojo\public\cpp\bindings\lib\message_dispatcher.cc:44
    #12 0x7ffa4bab09ae in mojo::InterfaceEndpointClient::HandleIncomingMessage C:\b\s\w\ir\cache\builder\src\mojo\public\cpp\bindings\lib\interface_endpoint_client.cc:747
    #13 0x7ffa4ba91e61 in mojo::internal::MultiplexRouter::ProcessIncomingMessage C:\b\s\w\ir\cache\builder\src\mojo\public\cpp\bindings\lib\multiplex_router.cc:1204
    #14 0x7ffa4ba903de in mojo::internal::MultiplexRouter::Accept C:\b\s\w\ir\cache\builder\src\mojo\public\cpp\bindings\lib\multiplex_router.cc:790
    #15 0x7ffa4baa703d in mojo::MessageDispatcher::Accept C:\b\s\w\ir\cache\builder\src\mojo\public\cpp\bindings\lib\message_dispatcher.cc:44
    #16 0x7ffa4baceebe in mojo::Connector::DispatchMessageW C:\b\s\w\ir\cache\builder\src\mojo\public\cpp\bindings\lib\connector.cc:568
    #17 0x7ffa4bad07b8 in mojo::Connector::ReadAllAvailableMessages C:\b\s\w\ir\cache\builder\src\mojo\public\cpp\bindings\lib\connector.cc:629
    #18 0x7ffa4bad1550 in base::internal::Invoker<base::internal::FunctorTraits<void (mojo::Connector::*&&)(),base::WeakPtr<mojo::Connector> &&>,base::internal::BindState<1,1,0,void (mojo::Connector::*)(),base::WeakPtr<mojo::Connector> >,void ()>::RunOnce C:\b\s\w\ir\cache\builder\src\base\functional\bind_internal.h:982
    #19 0x7ffa4bd84f08 in base::TaskAnnotator::RunTaskImpl C:\b\s\w\ir\cache\builder\src\base\task\common\task_annotator.cc:229
    #20 0x7ffa4bd551e1 in base::sequence_manager::internal::ThreadControllerWithMessagePumpImpl::DoWorkImpl C:\b\s\w\ir\cache\builder\src\base\task\sequence_manager\thread_controller_with_message_pump_impl.cc:475
    #21 0x7ffa4bd54043 in base::sequence_manager::internal::ThreadControllerWithMessagePumpImpl::DoWork C:\b\s\w\ir\cache\builder\src\base\task\sequence_manager\thread_controller_with_message_pump_impl.cc:346
    #22 0x7ffa4bbdb82c in base::MessagePumpForUI::DoRunLoop C:\b\s\w\ir\cache\builder\src\base\message_loop\message_pump_win.cc:260
    #23 0x7ffa4bbd91e4 in base::MessagePumpWin::Run C:\b\s\w\ir\cache\builder\src\base\message_loop\message_pump_win.cc:87
    #24 0x7ffa4bd56f2f in base::sequence_manager::internal::ThreadControllerWithMessagePumpImpl::Run C:\b\s\w\ir\cache\builder\src\base\task\sequence_manager\thread_controller_with_message_pump_impl.cc:650
    #25 0x7ffa4bdfc89c in base::RunLoop::Run C:\b\s\w\ir\cache\builder\src\base\run_loop.cc:135
    #26 0x7ffa41097977 in content::BrowserMainLoop::RunMainMessageLoop C:\b\s\w\ir\cache\builder\src\content\browser\browser_main_loop.cc:1103
    #27 0x7ffa4109f779 in content::BrowserMainRunnerImpl::Run C:\b\s\w\ir\cache\builder\src\content\browser\browser_main_runner_impl.cc:151
    #28 0x7ffa4108ddf6 in content::BrowserMain C:\b\s\w\ir\cache\builder\src\content\browser\browser_main.cc:32
    #29 0x7ffa47982f6a in content::RunBrowserProcessMain C:\b\s\w\ir\cache\builder\src\content\app\content_main_runner_impl.cc:696
    #30 0x7ffa479865ec in content::ContentMainRunnerImpl::RunBrowser C:\b\s\w\ir\cache\builder\src\content\app\content_main_runner_impl.cc:1320
    #31 0x7ffa47985c72 in content::ContentMainRunnerImpl::Run C:\b\s\w\ir\cache\builder\src\content\app\content_main_runner_impl.cc:1150
    #32 0x7ffa47979a1f in content::RunContentProcess C:\b\s\w\ir\cache\builder\src\content\app\content_main.cc:358
    #33 0x7ffa4797a1c2 in content::ContentMain C:\b\s\w\ir\cache\builder\src\content\app\content_main.cc:371
    #34 0x7ffa377c2b06 in ChromeMain C:\b\s\w\ir\cache\builder\src\chrome\app\chrome_main.cc:191
    #35 0x7ff601ef4807 in MainDllLoader::Launch C:\b\s\w\ir\cache\builder\src\chrome\app\main_dll_loader_win.cc:204
    #36 0x7ff601ef2074 in main C:\b\s\w\ir\cache\builder\src\chrome\app\chrome_exe_main_win.cc:351
    #37 0x7ff6023ed91f in __scrt_common_main_seh D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:288
    #38 0x7ffb9f6ae8d6 in BaseThreadInitThunk+0x16 (C:\WINDOWS\System32\KERNEL32.DLL+0x18002e8d6)
    #39 0x7ffba07ac40b in RtlUserThreadStart+0x2b (C:\WINDOWS\SYSTEM32\ntdll.dll+0x18008c40b)

0x12170e631828 is located 8 bytes inside of 88-byte region [0x12170e631820,0x12170e631878)
freed by thread T0 here:
    #0 0x7ffab848f036 in operator delete+0x96 (C:\Users\Admin\Downloads\chrome-asan\clang_rt.asan_dynamic-x86_64.dll+0x18005f036)
    #1 0x7ffa468cf23c in extensions::ChromeContentRulesRegistry::RemoveRulesImpl C:\b\s\w\ir\cache\builder\src\chrome\browser\extensions\api\declarative_content\chrome_content_rules_registry.cc:363
    #2 0x7ffa43b8d764 in extensions::RulesRegistry::RemoveRules C:\b\s\w\ir\cache\builder\src\extensions\browser\api\declarative\rules_registry.cc:176
    #3 0x7ffa43b84299 in extensions::EventsEventRemoveRulesFunction::RunInternal C:\b\s\w\ir\cache\builder\src\extensions\browser\api\declarative\declarative_api.cc:256
    #4 0x7ffa43b8229b in extensions::RulesFunction::Run C:\b\s\w\ir\cache\builder\src\extensions\browser\api\declarative\declarative_api.cc:193
    #5 0x7ffa43dddffa in ExtensionFunction::RunWithValidation C:\b\s\w\ir\cache\builder\src\extensions\browser\extension_function.cc:494
    #6 0x7ffa43dee30e in extensions::ExtensionFunctionDispatcher::DispatchWithCallbackInternal C:\b\s\w\ir\cache\builder\src\extensions\browser\extension_function_dispatcher.cc:458
    #7 0x7ffa43def06d in extensions::ExtensionFunctionDispatcher::DispatchForServiceWorker C:\b\s\w\ir\cache\builder\src\extensions\browser\extension_function_dispatcher.cc:248
    #8 0x7ffa43f60171 in extensions::ServiceWorkerHost::RequestWorker C:\b\s\w\ir\cache\builder\src\extensions\browser\service_worker\service_worker_host.cc:278
    #9 0x7ffa440ea7ad in extensions::mojom::ServiceWorkerHostStubDispatch::AcceptWithResponder C:\b\s\w\ir\cache\builder\src\out\069a-Win_ASan_Releas\gen\extensions\common\mojom\service_worker_host.mojom.cc:1648
    #10 0x7ffa43f638dc in extensions::mojom::ServiceWorkerHostStub<mojo::RawPtrImplRefTraits<extensions::mojom::ServiceWorkerHost> >::AcceptWithResponder C:\b\s\w\ir\cache\builder\src\out\069a-Win_ASan_Releas\gen\extensions\common\mojom\service_worker_host.mojom.h:201
    #11 0x7ffa4baaa26d in mojo::InterfaceEndpointClient::HandleValidatedMessage C:\b\s\w\ir\cache\builder\src\mojo\public\cpp\bindings\lib\interface_endpoint_client.cc:1036
    #12 0x7ffa4baa703d in mojo::MessageDispatcher::Accept C:\b\s\w\ir\cache\builder\src\mojo\public\cpp\bindings\lib\message_dispatcher.cc:44
    #13 0x7ffa4bab09ae in mojo::InterfaceEndpointClient::HandleIncomingMessage C:\b\s\w\ir\cache\builder\src\mojo\public\cpp\bindings\lib\interface_endpoint_client.cc:747
    #14 0x7ffa4ba91e61 in mojo::internal::MultiplexRouter::ProcessIncomingMessage C:\b\s\w\ir\cache\builder\src\mojo\public\cpp\bindings\lib\multiplex_router.cc:1204
    #15 0x7ffa4ba903de in mojo::internal::MultiplexRouter::Accept C:\b\s\w\ir\cache\builder\src\mojo\public\cpp\bindings\lib\multiplex_router.cc:790
    #16 0x7ffa4baa703d in mojo::MessageDispatcher::Accept C:\b\s\w\ir\cache\builder\src\mojo\public\cpp\bindings\lib\message_dispatcher.cc:44
    #17 0x7ffa4baceebe in mojo::Connector::DispatchMessageW C:\b\s\w\ir\cache\builder\src\mojo\public\cpp\bindings\lib\connector.cc:568
    #18 0x7ffa4bad07b8 in mojo::Connector::ReadAllAvailableMessages C:\b\s\w\ir\cache\builder\src\mojo\public\cpp\bindings\lib\connector.cc:629
    #19 0x7ffa4bad1550 in base::internal::Invoker<base::internal::FunctorTraits<void (mojo::Connector::*&&)(),base::WeakPtr<mojo::Connector> &&>,base::internal::BindState<1,1,0,void (mojo::Connector::*)(),base::WeakPtr<mojo::Connector> >,void ()>::RunOnce C:\b\s\w\ir\cache\builder\src\base\functional\bind_internal.h:982
    #20 0x7ffa4bd84f08 in base::TaskAnnotator::RunTaskImpl C:\b\s\w\ir\cache\builder\src\base\task\common\task_annotator.cc:229
    #21 0x7ffa4bd551e1 in base::sequence_manager::internal::ThreadControllerWithMessagePumpImpl::DoWorkImpl C:\b\s\w\ir\cache\builder\src\base\task\sequence_manager\thread_controller_with_message_pump_impl.cc:475
    #22 0x7ffa4bd54043 in base::sequence_manager::internal::ThreadControllerWithMessagePumpImpl::DoWork C:\b\s\w\ir\cache\builder\src\base\task\sequence_manager\thread_controller_with_message_pump_impl.cc:346
    #23 0x7ffa4bbdb82c in base::MessagePumpForUI::DoRunLoop C:\b\s\w\ir\cache\builder\src\base\message_loop\message_pump_win.cc:260
    #24 0x7ffa4bbd91e4 in base::MessagePumpWin::Run C:\b\s\w\ir\cache\builder\src\base\message_loop\message_pump_win.cc:87
    #25 0x7ffa4bd56f2f in base::sequence_manager::internal::ThreadControllerWithMessagePumpImpl::Run C:\b\s\w\ir\cache\builder\src\base\task\sequence_manager\thread_controller_with_message_pump_impl.cc:650
    #26 0x7ffa4bdfc89c in base::RunLoop::Run C:\b\s\w\ir\cache\builder\src\base\run_loop.cc:135
    #27 0x7ffa41097977 in content::BrowserMainLoop::RunMainMessageLoop C:\b\s\w\ir\cache\builder\src\content\browser\browser_main_loop.cc:1103

previously allocated by thread T0 here:
    #0 0x7ffab848e46f in operator new+0x8f (C:\Users\Admin\Downloads\chrome-asan\clang_rt.asan_dynamic-x86_64.dll+0x18005e46f)
    #1 0x7ffa468d0615 in std::__Cr::__tree<std::__Cr::__value_type<std::__Cr::pair<std::__Cr::basic_string<char,std::__Cr::char_traits<char>,std::__Cr::allocator<char> >,std::__Cr::basic_string<char,std::__Cr::char_traits<char>,std::__Cr::allocator<char> > >,std::__Cr::unique_ptr<const extensions::ChromeContentRulesRegistry::ContentRule,std::__Cr::default_delete<const extensions::ChromeContentRulesRegistry::ContentRule> > >,std::__Cr::__map_value_compare<std::__Cr::pair<std::__Cr::basic_string<char,std::__Cr::char_traits<char>,std::__Cr::allocator<char> >,std::__Cr::basic_string<char,std::__Cr::char_traits<char>,std::__Cr::allocator<char> > >,std::__Cr::pair<const std::__Cr::pair<std::__Cr::basic_string<char,std::__Cr::char_traits<char>,std::__Cr::allocator<char> >,std::__Cr::basic_string<char,std::__Cr::char_traits<char>,std::__Cr::allocator<char> > >,std::__Cr::unique_ptr<const extensions::ChromeContentRulesRegistry::ContentRule,std::__Cr::default_delete<const extensions::ChromeContentRulesRegistry::ContentRule> > >,std::__Cr::less<std::__Cr::pair<std::__Cr::basic_string<char,std::__Cr::char_traits<char>,std::__Cr::allocator<char> >,std::__Cr::basic_string<char,std::__Cr::char_traits<char>,std::__Cr::allocator<char> > > > >,std::__Cr::allocator<std::__Cr::pair<const std::__Cr::pair<std::__Cr::basic_string<char,std::__Cr::char_traits<char>,std::__Cr::allocator<char> >,std::__Cr::basic_string<char,std::__Cr::char_traits<char>,std::__Cr::allocator<char> > >,std::__Cr::unique_ptr<const extensions::ChromeContentRulesRegistry::ContentRule,std::__Cr::default_delete<const extensions::ChromeContentRulesRegistry::ContentRule> > > > >::__insert_range_unique<std::__Cr::move_iterator<std::__Cr::__map_iterator<std::__Cr::__tree_iterator<std::__Cr::__value_type<std::__Cr::pair<std::__Cr::basic_string<char,std::__Cr::char_traits<char>,std::__Cr::allocator<char> >,std::__Cr::basic_string<char,std::__Cr::char_traits<char>,std::__Cr::allocator<char> > >,std::__Cr::unique_ptr<const extensions::ChromeContentR C:\b\s\w\ir\cache\builder\src\third_party\libc++\src\include\__tree:1131
    #2 0x7ffa468cdce1 in extensions::ChromeContentRulesRegistry::AddRulesImpl C:\b\s\w\ir\cache\builder\src\chrome\browser\extensions\api\declarative_content\chrome_content_rules_registry.cc:307
    #3 0x7ffa43b8b740 in extensions::RulesRegistry::AddRulesNoFill C:\b\s\w\ir\cache\builder\src\extensions\browser\api\declarative\rules_registry.cc:114
    #4 0x7ffa43b8ca41 in extensions::RulesRegistry::AddRulesInternal C:\b\s\w\ir\cache\builder\src\extensions\browser\api\declarative\rules_registry.cc:159
    #5 0x7ffa43b8c70c in extensions::RulesRegistry::AddRules C:\b\s\w\ir\cache\builder\src\extensions\browser\api\declarative\rules_registry.cc:143
    #6 0x7ffa43b833bf in extensions::EventsEventAddRulesFunction::RunInternal C:\b\s\w\ir\cache\builder\src\extensions\browser\api\declarative\declarative_api.cc:212
    #7 0x7ffa43b8229b in extensions::RulesFunction::Run C:\b\s\w\ir\cache\builder\src\extensions\browser\api\declarative\declarative_api.cc:193
    #8 0x7ffa43dddffa in ExtensionFunction::RunWithValidation C:\b\s\w\ir\cache\builder\src\extensions\browser\extension_function.cc:494
    #9 0x7ffa43dee30e in extensions::ExtensionFunctionDispatcher::DispatchWithCallbackInternal C:\b\s\w\ir\cache\builder\src\extensions\browser\extension_function_dispatcher.cc:458
    #10 0x7ffa43def06d in extensions::ExtensionFunctionDispatcher::DispatchForServiceWorker C:\b\s\w\ir\cache\builder\src\extensions\browser\extension_function_dispatcher.cc:248
    #11 0x7ffa43f60171 in extensions::ServiceWorkerHost::RequestWorker C:\b\s\w\ir\cache\builder\src\extensions\browser\service_worker\service_worker_host.cc:278
    #12 0x7ffa440ea7ad in extensions::mojom::ServiceWorkerHostStubDispatch::AcceptWithResponder C:\b\s\w\ir\cache\builder\src\out\069a-Win_ASan_Releas\gen\extensions\common\mojom\service_worker_host.mojom.cc:1648
    #13 0x7ffa43f638dc in extensions::mojom::ServiceWorkerHostStub<mojo::RawPtrImplRefTraits<extensions::mojom::ServiceWorkerHost> >::AcceptWithResponder C:\b\s\w\ir\cache\builder\src\out\069a-Win_ASan_Releas\gen\extensions\common\mojom\service_worker_host.mojom.h:201
    #14 0x7ffa4baaa26d in mojo::InterfaceEndpointClient::HandleValidatedMessage C:\b\s\w\ir\cache\builder\src\mojo\public\cpp\bindings\lib\interface_endpoint_client.cc:1036
    #15 0x7ffa4baa703d in mojo::MessageDispatcher::Accept C:\b\s\w\ir\cache\builder\src\mojo\public\cpp\bindings\lib\message_dispatcher.cc:44
    #16 0x7ffa4bab09ae in mojo::InterfaceEndpointClient::HandleIncomingMessage C:\b\s\w\ir\cache\builder\src\mojo\public\cpp\bindings\lib\interface_endpoint_client.cc:747
    #17 0x7ffa4ba91e61 in mojo::internal::MultiplexRouter::ProcessIncomingMessage C:\b\s\w\ir\cache\builder\src\mojo\public\cpp\bindings\lib\multiplex_router.cc:1204
    #18 0x7ffa4ba903de in mojo::internal::MultiplexRouter::Accept C:\b\s\w\ir\cache\builder\src\mojo\public\cpp\bindings\lib\multiplex_router.cc:790
    #19 0x7ffa4baa703d in mojo::MessageDispatcher::Accept C:\b\s\w\ir\cache\builder\src\mojo\public\cpp\bindings\lib\message_dispatcher.cc:44
    #20 0x7ffa4baceebe in mojo::Connector::DispatchMessageW C:\b\s\w\ir\cache\builder\src\mojo\public\cpp\bindings\lib\connector.cc:568
    #21 0x7ffa4bad07b8 in mojo::Connector::ReadAllAvailableMessages C:\b\s\w\ir\cache\builder\src\mojo\public\cpp\bindings\lib\connector.cc:629
    #22 0x7ffa4bad1550 in base::internal::Invoker<base::internal::FunctorTraits<void (mojo::Connector::*&&)(),base::WeakPtr<mojo::Connector> &&>,base::internal::BindState<1,1,0,void (mojo::Connector::*)(),base::WeakPtr<mojo::Connector> >,void ()>::RunOnce C:\b\s\w\ir\cache\builder\src\base\functional\bind_internal.h:982
    #23 0x7ffa4bd84f08 in base::TaskAnnotator::RunTaskImpl C:\b\s\w\ir\cache\builder\src\base\task\common\task_annotator.cc:229
    #24 0x7ffa4bd551e1 in base::sequence_manager::internal::ThreadControllerWithMessagePumpImpl::DoWorkImpl C:\b\s\w\ir\cache\builder\src\base\task\sequence_manager\thread_controller_with_message_pump_impl.cc:475
    #25 0x7ffa4bd54043 in base::sequence_manager::internal::ThreadControllerWithMessagePumpImpl::DoWork C:\b\s\w\ir\cache\builder\src\base\task\sequence_manager\thread_controller_with_message_pump_impl.cc:346
    #26 0x7ffa4bbdb82c in base::MessagePumpForUI::DoRunLoop C:\b\s\w\ir\cache\builder\src\base\message_loop\message_pump_win.cc:260
    #27 0x7ffa4bbd91e4 in base::MessagePumpWin::Run C:\b\s\w\ir\cache\builder\src\base\message_loop\message_pump_win.cc:87

SUMMARY: AddressSanitizer: heap-use-after-free C:\b\s\w\ir\cache\builder\src\chrome\browser\extensions\api\declarative_content\chrome_content_rules_registry.cc:363 in extensions::ChromeContentRulesRegistry::RemoveRulesImpl
Shadow bytes around the buggy address:
  0x12170e631580: fa fa f7 fa fd fd fd fd fd fd fd fd fd fd fd fd
  0x12170e631600: fa fa f7 fa fd fd fd fd fd fd fd fd fd fd fd fd
  0x12170e631680: fa fa f7 fa fd fd fd fd fd fd fd fd fd fd fd fd
  0x12170e631700: fa fa f7 fa fd fd fd fd fd fd fd fd fd fd fd fa
  0x12170e631780: fa fa f7 fa fd fd fd fd fd fd fd fd fd fd fd fa
=>0x12170e631800: fa fa f7 fa fd[fd]fd fd fd fd fd fd fd fd fd fa
  0x12170e631880: fa fa f7 fa 00 00 00 00 00 00 00 00 00 00 00 fa
  0x12170e631900: fa fa f7 fa fd fd fd fd fd fd fd fd fd fd fd fd
  0x12170e631980: fa fa f7 fa fd fd fd fd fd fd fd fd fd fd fd fd
  0x12170e631a00: fa fa f7 fa 00 00 00 00 00 00 00 00 00 00 00 00
  0x12170e631a80: fa fa f7 fa 00 00 00 00 00 00 00 00 00 00 00 00
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb

==63616==ADDITIONAL INFO

==63616==Note: Please include this section with the ASan report.
Task trace:
    #0 0x7ffa4bad11d2 in mojo::Connector::ScheduleDispatchOfPendingMessagesOrWaitForMore C:\b\s\w\ir\cache\builder\src\mojo\public\cpp\bindings\lib\connector.cc:612
    #1 0x7ffa4bad11d2 in mojo::Connector::ScheduleDispatchOfPendingMessagesOrWaitForMore C:\b\s\w\ir\cache\builder\src\mojo\public\cpp\bindings\lib\connector.cc:612
    #2 0x7ffa4c3a823b in mojo::SimpleWatcher::Context::Notify C:\b\s\w\ir\cache\builder\src\mojo\public\cpp\system\simple_watcher.cc:103


Command line: `"C:\Users\Admin\Downloads\chrome-asan\chrome.exe" --disable-extensions-except="C:\Users\Admin\Downloads\Extension" --load-extension="C:\Users\Admin\Downloads\Extension" --user-data-dir="C:\\Users\\Admin\\AppData\\Local\\Temp\\tmpuzg50refsdsddsdd" --flag-switches-begin --flag-switches-end --file-url-path-alias="/gen=C:\Users\Admin\Downloads\chrome-asan\gen"`


MiraclePtr Status: NOT PROTECTED
No raw_ptr<T> access to this region was detected prior to this crash.
This crash is still exploitable with MiraclePtr.
Refer to https://chromium.googlesource.com/chromium/src/+/main/base/memory/raw_ptr.md for details.

==63616==END OF ADDITIONAL INFO

==63616==ABORTING

VERSION

Version 147.0.7710.0 (Developer Build) (64-bit)

REPRODUCTION CASE

Build: asan-win32-release_x64-1591961

>Note: Download the attached files background.js and manifest.json into a folder named Extension and load them using the command below.

Run: .\chrome-asan\chrome.exe --disable-extensions-except=C:\Users\Admin\Downloads\Extension --load-extension=C:\Users\Admin\Downloads\Extension


Reporter credit: Shaheen Fazim

View on issue tracker