CVE-2026-4458
Overview
Background
- Declarative rules registry
RulesRegistryis 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’sRemoveRulesImpl().- `ChromeContentRulesRegistry`
- the
declarativeContentregistry that keeps rules incontent_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.
Attack Path
- Install an extension using declarative rules
the attacker controls an installed extension that can add
declarativeContentrules (the test uses apage_actionextension with adeclarativeContent.PageStateMatcherrule). - Add a rule
the extension registers a rule with a known ID (e.g.
"rule1"). - Remove with duplicate IDs
the extension requests removal with a list containing the same ID more than once, which flows through
RulesRegistry::RemoveRules()intoChromeContentRulesRegistry::RemoveRulesImpl(). - Double erase
the same
content_rules_iterator is collected twice inrules_to_eraseand erased twice, the second time on a freed node in the browser process; leveraging this for further memory corruption is (inferred).
Impact Assessment
Changed Functions
| Function | Change | Notes |
|---|---|---|
forchrome/browser/extensions/api/declarative_content/chrome_content_rules_registry.cc |
modified | |
TEST_Fchrome/browser/extensions/api/declarative_content/chrome_content_rules_registry_unittest.cc |
modified | |
forextensions/browser/api/declarative/rules_registry.cc |
modified |
Files Changed
chrome/browser/extensions/api/declarative_content/chrome_content_rules_registry.ccchrome/browser/extensions/api/declarative_content/chrome_content_rules_registry_unittest.ccextensions/browser/api/declarative/rules_registry.cc
Audit Directions
- Other `RemoveRulesImpl` overrides and direct callerscheck other
RulesRegistrysubclasses (e.g. declarative web request registries) and any code that callsRemoveRulesImpl()directly, bypassing the new deduplication inRulesRegistry::RemoveRules(). - Collect-then-erase iterator patternssearch 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 listsaudit other extension APIs that accept arrays of IDs (rules, alarms, context menus, tabs) for assumptions of uniqueness before lookups and deletions.
Patch
From 98a65b0c6572e8263e7d5a9cf91e9cba5d4d1350 Mon Sep 17 00:00:00 2001
From: Andrea Orru <andreaorru@chromium.org>
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 <rdevlin.cronin@chromium.org>
Commit-Queue: Andrea Orru <andreaorru@chromium.org>
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;
}
Regression Test / PoC
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
Original Bug Report
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
- https://chromium.googlesource.com/chromium/src/+/main/base/memory/raw_ptr.md
- https://www.googleapis.com/download/storage/v1/b/chromium-browser-asan/o/win32-release_x64%2Fasan-win32-release_x64-1591961.zip?generation=1772257263596065&alt=media
- https://www.googleapis.com/download/storage/v1/b/chromium-browser-asan/o/win32-release_x64/asan-win32-release_x64-1591961.zip?generation=1772257263596065&alt=media