Medium chrome Logic Error 📄 Reporter bug report 🔧 Commit mapped

Overview

Medium
Severity
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactInappropriate implementation in Extensions
DescriptionInappropriate implementation in Extensions
ComponentExtensions
Bug ClassLogic Error
Tracker514071697
Fix commit222c202865a7 (chromium/src) +23/-0
CISA KEVNot listed
CreditedGoogle
Disclosed2026-06-30

Changed Functions

FunctionChangeNotes
TEST
extensions/common/extension_unittest.cc
modified

Files Changed

  • extensions/common/extension.cc
  • extensions/common/extension_unittest.cc
From 222c202865a728e8954c5546c0e3ff9c03ddd6f4 Mon Sep 17 00:00:00 2001
From: Andrea Orru <[email protected]>
Date: Mon, 01 Jun 2026 14:57:42 -0700
Subject: [PATCH] [Extensions] Sanitize extension short name in LoadShortName

Fix a vulnerability where Extension::LoadShortName failed to sanitize
the extension's short name, allowing unterminated bidirectional control
characters and newlines.

Fixed: 514071697
Change-Id: Ibf1d62da2456d1d96512da90818b1e54f363aa49
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7885964
Commit-Queue: Andrea Orru <[email protected]>
Reviewed-by: Solomon Kinard <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1639701}
---

diff --git a/extensions/common/extension.cc b/extensions/common/extension.cc
index b98a852..921ca88 100644
--- a/extensions/common/extension.cc
+++ b/extensions/common/extension.cc
@@ -774,6 +774,8 @@
     }
     std::u16string localized_short_name =
         base::UTF8ToUTF16(*localized_short_name_utf8);
+    localized_short_name = base::CollapseWhitespace(localized_short_name, true);
+    base::i18n::SanitizeUserSuppliedString(&localized_short_name);
     base::i18n::AdjustStringForLocaleDirection(&localized_short_name);
     short_name_ = base::UTF16ToUTF8(localized_short_name);
   } else {
diff --git a/extensions/common/extension_unittest.cc b/extensions/common/extension_unittest.cc
index f3e53b2..40e1dbc 100644
--- a/extensions/common/extension_unittest.cc
+++ b/extensions/common/extension_unittest.cc
@@ -388,4 +388,25 @@
   EXPECT_TRUE(RunVersionFailure("-0.0"));
 }
 
+// Verifies that short_name is sanitized by collapsing whitespace and
+// terminating bidirectional control characters.
+// Regression test for crbug.com/514071697.
+TEST(ExtensionTest, ExtensionShortNameSanitization) {
+  base::DictValue manifest =
+      base::DictValue()
+          .Set(manifest_keys::kName, "My Extension")
+          .Set(manifest_keys::kShortName, "Sec\n\nUpdate\u202E")
+          .Set(manifest_keys::kVersion, "0.1")
+          .Set(manifest_keys::kManifestVersion, 3);
+
+  std::u16string error;
+  scoped_refptr<const Extension> extension =
+      Extension::Create(base::FilePath(), ManifestLocation::kInternal, manifest,
+                        Extension::NO_FLAGS, &error);
+  ASSERT_TRUE(extension) << "Extension creation failed: " << error;
+
+  EXPECT_EQ(std::string("SecUpdate") + "\xE2\x80\xAE" + "\xE2\x80\xAC",
+            extension->short_name());
+}
+
 }  // namespace extensions
Loading diff…

Regression Test / PoC

shipped with the fix
diff --git a/extensions/common/extension_unittest.cc b/extensions/common/extension_unittest.cc
index f3e53b2..40e1dbc 100644
--- a/extensions/common/extension_unittest.cc
+++ b/extensions/common/extension_unittest.cc
@@ -388,4 +388,25 @@
   EXPECT_TRUE(RunVersionFailure("-0.0"));
 }
 
+// Verifies that short_name is sanitized by collapsing whitespace and
+// terminating bidirectional control characters.
+// Regression test for crbug.com/514071697.
+TEST(ExtensionTest, ExtensionShortNameSanitization) {
+  base::DictValue manifest =
+      base::DictValue()
+          .Set(manifest_keys::kName, "My Extension")
+          .Set(manifest_keys::kShortName, "Sec\n\nUpdate\u202E")
+          .Set(manifest_keys::kVersion, "0.1")
+          .Set(manifest_keys::kManifestVersion, 3);
+
+  std::u16string error;
+  scoped_refptr<const Extension> extension =
+      Extension::Create(base::FilePath(), ManifestLocation::kInternal, manifest,
+                        Extension::NO_FLAGS, &error);
+  ASSERT_TRUE(extension) << "Extension creation failed: " << error;
+
+  EXPECT_EQ(std::string("SecUpdate") + "\xE2\x80\xAE" + "\xE2\x80\xAC",
+            extension->short_name());
+}
+
 }  // namespace extensions
Loading diff…

Original Bug Report

reported by [email protected]

UI Spoofing and BiDi Leakage via Unsanitized Extension short_name

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. Please see https://chromium.googlesource.com/chromium/src/+/main/docs/security/ai-generated-security-bugs-faq.md for more information.

Overview: The Extension::LoadShortName function fails to sanitize the extension’s short name, allowing it to contain unterminated bidirectional control characters and newlines. This enables malicious extensions to manipulate browser UI layout and forge content in security-sensitive surfaces like permission dialogs and the Omnibox.

Affected files:

  • extensions/common/extension.cc
  • chrome/browser/ui/views/certificate_selector.cc
  • chrome/browser/ui/views/platform_keys_certificate_selector_chromeos.cc
  • chrome/browser/ui/views/side_panel/extensions/extension_side_panel_manager.cc
  • chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_page_handler.cc
  • chrome/browser/extensions/api/omnibox/omnibox_api.cc
  • chrome/browser/ui/extensions/hosted_app_browser_controller.cc
  • chrome/browser/apps/app_service/publishers/extension_apps_base.cc

Estimated timestamp from git blame: 2018-02-13

Summary

A potential vulnerability exists in the extension manifest loading logic where the short_name field is not properly sanitized. Unlike the primary name field, short_name bypasses whitespace collapsing and bidirectional (BiDi) formatting termination. This allows an extension to include newlines and unterminated BiDi control characters (e.g., Right-to-Left Override) that can leak into and manipulate surrounding browser-process UI text.

Root Cause Analysis

In extensions/common/extension.cc, Extension::LoadName correctly sanitizes the input by calling base::CollapseWhitespace and base::i18n::SanitizeUserSuppliedString. The latter ensures that directional formatting is terminated, preventing directional state from leaking beyond the string.

However, Extension::LoadShortName (lines 768-783) only calls base::i18n::AdjustStringForLocaleDirection. This function does not terminate directional formatting if the string contains only LTR-strong characters (like a Latin-based spoofing payload). Consequently, characters like U+202E (RLO) remain unterminated, and newlines are preserved.

Potential Impact and Affected UI Sinks

An attacker could potentially use a malicious short_name to spoof identity or forge content in several UI components:

  1. Omnibox Placeholder (chrome/browser/ui/views/omnibox/omnibox_view_views.cc:444): An unterminated RLO in the short name can leak into the “Search $1 or type a URL” prompt, reversing the visual order of the remaining text and misleading the user about the Omnibox’s state.
  2. ChromeOS PlatformKeys Dialog (chrome/browser/ui/views/platform_keys_certificate_selector_chromeos.cc): This sink uses views::StyledLabel to display which extension is requesting certificate access. Newlines in the short_name can be used to push the legitimate security prompt out of the visible area or into a scrollable region, while providing forged text that appears to be part of the native UI.
  3. Side Panel and Search Engine Settings: Various other sinks concatenate the short name with localized strings without applying BiDi isolation, potentially leading to visual corruption or spoofing.

Suggested Reproduction Steps

Note: These are potential steps based on code analysis as our environment does not support executing a live Chromium instance.

  1. Create an extension with a manifest containing a malicious short_name payload: "short_name": "Security Update\n\n[Forged Content]\u202E".
  2. Load the extension in Chrome.
  3. Trigger a UI sink that displays the short name, such as making the extension the default search provider and viewing the Omnibox placeholder, or invoking the chrome.platformKeys API on ChromeOS.
  4. Observe if the newlines manipulate the dialog layout and if the unterminated RLO affects the visual order of adjacent browser text.

Update Extension::LoadShortName in extensions/common/extension.cc to match the sanitization logic used in LoadName. Specifically, call base::CollapseWhitespace and base::i18n::SanitizeUserSuppliedString (or its underlying termination logic) before storing the short name.

Evaluated with Chrome root at commit: 1a8d40fc44df2088d5945c0bf53584038aa1614a


Results so far have been promising, but there can be wrong deductions. Feel free to adjust as follows:

  • If you are familiar with the severity guidelines, you may adjust the severity.
  • If this is a false positive, and there’s no work to be done, please close as WAI.
  • If there is work to do here but not a vulnerability, please change the issue type to Task/Bug/FR.

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