Chrome · Extensions
CVE-2026-14047
Logic Error in Extensions
Overview
Low
Severity
—
CVSS
No
Exploited ITW
Fixed
Fix Status
Changed Functions
| Function | Change | Notes |
|---|---|---|
of |
modified | |
switchchrome/browser/extensions/extension_management.cc |
modified | |
TEST_Pchrome/browser/extensions/mv2_deprecation_impact_checker_unittest.cc |
modified |
Files Changed
chrome/browser/extensions/extension_management.ccchrome/browser/extensions/mv2_deprecation_impact_checker_unittest.ccextensions/browser/mv2_deprecation_impact_checker.cc
Patch
From 72af0053522f6b7a10684d6692f156cd84c8cc3c Mon Sep 17 00:00:00 2001
From: Devlin Cronin <rdevlin.cronin@chromium.org>
Date: Wed, 13 May 2026 16:23:45 -0700
Subject: [PATCH] [Extensions] Include Manifest::TYPE_USER_SCRIPT in mv2 checker
Extensions of TYPE_USER_SCRIPT are largely treated as "extensions"
throughout Chrome -- they have access to extension APIs, are considered
extensions for feature availability, are shown in the
chrome://extensions page as extensions, etc.
Include them in the MV2DeprecationImpactChecker to ensure MV2 user
scripts are also disabled.
Very few* users have any extensions installed of TYPE_USER_SCRIPT, so
this shouldn't affect significant amounts of users, and any that are
affected are using deprecated extensions (thus, disabling them is
working as intended).
Note: This is not to be confused with *user script managers*, a
class of extension that leverages the browser.userScripts API.
*Internal stats only, sorry.
Bug: 498864176
Change-Id: I7310fa1f1411290dac935fd6d899bd72daafdcc0
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7846377
Reviewed-by: Tim <tjudkins@chromium.org>
Commit-Queue: Tim <tjudkins@chromium.org>
Auto-Submit: Devlin Cronin <rdevlin.cronin@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1630304}
---
diff --git a/chrome/browser/extensions/extension_management.cc b/chrome/browser/extensions/extension_management.cc
index aed401d..782658fd 100644
--- a/chrome/browser/extensions/extension_management.cc
+++ b/chrome/browser/extensions/extension_management.cc
@@ -375,10 +375,12 @@
extensions_features::kExtensionsManifestV3Only) ||
manifest_version >= 3;
- // Manifest version policy only supports normal extensions and Chrome OS login
- // screen extension.
+ // Manifest version policy only supports normal extensions, Chrome OS login
+ // screen extensions, and user scripts (which are largely treated as
+ // extensions).
if (manifest_type != Manifest::Type::TYPE_EXTENSION &&
- manifest_type != Manifest::Type::TYPE_LOGIN_SCREEN_EXTENSION) {
+ manifest_type != Manifest::Type::TYPE_LOGIN_SCREEN_EXTENSION &&
+ manifest_type != Manifest::Type::TYPE_USER_SCRIPT) {
return enabled_by_default;
}
switch (global_settings_->manifest_v2_setting) {
@@ -411,7 +413,8 @@
return false;
}
if (manifest_type != Manifest::Type::TYPE_EXTENSION &&
- manifest_type != Manifest::Type::TYPE_LOGIN_SCREEN_EXTENSION) {
+ manifest_type != Manifest::Type::TYPE_LOGIN_SCREEN_EXTENSION &&
+ manifest_type != Manifest::Type::TYPE_USER_SCRIPT) {
return false;
}
diff --git a/chrome/browser/extensions/mv2_deprecation_impact_checker_unittest.cc b/chrome/browser/extensions/mv2_deprecation_impact_checker_unittest.cc
index 00bbb1a7..8ad8b73e 100644
--- a/chrome/browser/extensions/mv2_deprecation_impact_checker_unittest.cc
+++ b/chrome/browser/extensions/mv2_deprecation_impact_checker_unittest.cc
@@ -511,6 +511,22 @@
EXPECT_FALSE(impact_checker()->IsExtensionAffected(*hosted_app));
}
+// Tests that user script MV2 extensions are properly considered affected by
+// the MV2 deprecation experiment.
+TEST_P(MV2DeprecationImpactCheckerUnitTest, UserScriptsAreAffected) {
+ scoped_refptr<const Extension> user_script =
+ ExtensionBuilder("user script")
+ .SetLocation(mojom::ManifestLocation::kInternal)
+ .SetManifestVersion(2)
+ .SetManifestKey("converted_from_user_script", true)
+ .Build();
+ ASSERT_EQ(Manifest::TYPE_USER_SCRIPT, user_script->GetType());
+
+ bool expected_affected = policy_level() != MV2PolicyLevel::kAllowed;
+ EXPECT_EQ(expected_affected,
+ impact_checker()->IsExtensionAffected(*user_script));
+}
+
// Tests the allowlist is taken into account.
TEST_P(MV2DeprecationImpactCheckerUnitTestWithAllowlist, AllowlistWorks) {
scoped_refptr<const Extension> ext_a =
diff --git a/extensions/browser/mv2_deprecation_impact_checker.cc b/extensions/browser/mv2_deprecation_impact_checker.cc
index 4b7d9ec8..36d21ed 100644
--- a/extensions/browser/mv2_deprecation_impact_checker.cc
+++ b/extensions/browser/mv2_deprecation_impact_checker.cc
@@ -62,9 +62,12 @@
return false;
}
- // Only extensions (not platform apps, etc).
+ // Only extensions (not platform apps, etc). User scripts are treated as
+ // extensions for the sake of APIs and in presentation to the user, so we
+ // include them here.
if (manifest_type != Manifest::TYPE_EXTENSION &&
- manifest_type != Manifest::TYPE_LOGIN_SCREEN_EXTENSION) {
+ manifest_type != Manifest::TYPE_LOGIN_SCREEN_EXTENSION &&
+ manifest_type != Manifest::TYPE_USER_SCRIPT) {
return false;
}
Loading diff…
Regression Test / PoC
shipped with the fix
diff --git a/chrome/browser/extensions/mv2_deprecation_impact_checker_unittest.cc b/chrome/browser/extensions/mv2_deprecation_impact_checker_unittest.cc
index 00bbb1a7..8ad8b73e 100644
--- a/chrome/browser/extensions/mv2_deprecation_impact_checker_unittest.cc
+++ b/chrome/browser/extensions/mv2_deprecation_impact_checker_unittest.cc
@@ -511,6 +511,22 @@
EXPECT_FALSE(impact_checker()->IsExtensionAffected(*hosted_app));
}
+// Tests that user script MV2 extensions are properly considered affected by
+// the MV2 deprecation experiment.
+TEST_P(MV2DeprecationImpactCheckerUnitTest, UserScriptsAreAffected) {
+ scoped_refptr<const Extension> user_script =
+ ExtensionBuilder("user script")
+ .SetLocation(mojom::ManifestLocation::kInternal)
+ .SetManifestVersion(2)
+ .SetManifestKey("converted_from_user_script", true)
+ .Build();
+ ASSERT_EQ(Manifest::TYPE_USER_SCRIPT, user_script->GetType());
+
+ bool expected_affected = policy_level() != MV2PolicyLevel::kAllowed;
+ EXPECT_EQ(expected_affected,
+ impact_checker()->IsExtensionAffected(*user_script));
+}
+
// Tests the allowlist is taken into account.
TEST_P(MV2DeprecationImpactCheckerUnitTestWithAllowlist, AllowlistWorks) {
scoped_refptr<const Extension> ext_a =
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