Medium CVSS 6.5 firefox Spoofing 🔧 Commit mapped

Overview

Medium
Severity
6.5
CVSS
No
Exploited ITW
Fixed
Fix Status
Impactmoderate
DescriptionTruncation of a long URL could have allowed origin spoofing in a permission prompt.
ComponentToolkit
Bug ClassSpoofing
Tracker1920423
Fix commite650f827ea35 (firefox) +12/-2
CWECWE-290
CVSS vectorCVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:H/A:N
CISA KEVNot listed
CreditedHafiizh
Disclosed2024-10-29

Background

PopupNotification
Firefox’s reusable doorhanger UI used to request user consent for privileged capabilities such as geolocation, camera, or notification access.
Permission prompt
a PopupNotification instance whose localized message embeds the requesting site’s origin (its name) so the user can decide whether to trust that origin.
`popup-notification-description`
the <description> container element that holds the prompt’s message, assembled from alternating <html:span> label fragments and <html:b> substitution fragments.
`word-break`
a CSS property that controls where text may wrap; break-all permits a break at any character, forcing an over-long token to wrap instead of overflowing or being truncated.

Root Cause Analysis

The vulnerable code path is the rendering of a PopupNotification’s message inside the popup-notification-description element, where the site origin is injected as the name property into a <html:b> fragment via the widget’s attribute-inheritance map in popupnotification.js. The origin string was placed in a bold element that had no wrapping rule, so a very long hostname was visually truncated (clipped or cut off) rather than wrapped, violating the invariant that the security-relevant origin must be fully and unambiguously presented to the user. Because the displayed portion could be attacker-controlled and end at a deceptive boundary, a malicious site could craft a hostname whose visible prefix impersonates a trusted origin.

The fix gives the origin fragment the dedicated class popup-notification-description-name and adds a CSS rule setting word-break: break-all, so the full hostname wraps and remains readable in its entirety. This works because the user now always sees the complete origin, removing the spoofing surface created by silent truncation.

Key insight
The single core mistake was rendering the security-critical origin name in an element that could truncate long hostnames instead of wrapping them; the fix targets that element with a stable class and forces word-break: break-all so the entire origin is always shown.

Attack Path

  1. Register a deceptive hostname The attacker controls a domain whose long name begins with a string resembling a trusted origin (e.g. a trusted-looking prefix followed by attacker-controlled continuation).
  2. Trigger a permission prompt The malicious page requests a permission-gated capability, causing Firefox to open a PopupNotification that substitutes the attacker’s origin into the name fragment.
  3. Exploit the missing wrap rule Because the <html:b> origin fragment lacks a wrapping rule, the over-long hostname is truncated in the popup-notification-description, hiding the attacker-controlled tail.
  4. Induce misplaced trust The user reads only the visible truncated prefix, believes the request comes from the trusted origin, and grants the permission.

Impact Assessment

An attacker gains origin spoofing in a security-decision UI, tricking the user into granting a permission (such as geolocation or notifications) to a malicious origin under the belief it is a trusted one. This occurs in the browser chrome’s permission-prompt context and requires the user to visit the attacker’s page and act on the prompt, with a hostname long enough to trigger truncation. The impact is rated moderate because it depends on user interaction and a crafted long URL rather than yielding direct code execution.

Files Changed

  • toolkit/content/widgets/popupnotification.js
  • toolkit/themes/shared/popupnotification.css

Audit Directions

  • Truncated security strings
    Review any UI that displays origins, URLs, certificate subjects, or file names in security decisions and confirm long values wrap fully rather than being clipped or ellipsized.
  • Attribute-inheritance substitution
    Audit other PopupNotification and doorhanger fragments assembled via attribute-inheritance maps for substitution slots that lack wrapping or overflow handling.
  • Origin-in-element styling
    Look for security-relevant text placed in <b>, <span>, or fixed-width containers whose CSS omits word-break/overflow-wrap, allowing attacker-controlled content to be visually cut off.
diff --git a/toolkit/content/widgets/popupnotification.js b/toolkit/content/widgets/popupnotification.js
index 8de832a1553..5b18465529a 100644
--- a/toolkit/content/widgets/popupnotification.js
+++ b/toolkit/content/widgets/popupnotification.js
@@ -16,7 +16,7 @@
         ".popup-notification-description": "popupid,id=descriptionid",
         ".popup-notification-description > span:first-of-type":
           "text=label,popupid",
-        ".popup-notification-description > b:first-of-type":
+        ".popup-notification-description > .popup-notification-description-name":
           "text=name,popupid",
         ".popup-notification-description > span:nth-of-type(2)":
           "text=endlabel,popupid",
@@ -81,7 +81,7 @@
           <!-- These need to be on the same line to avoid creating
               whitespace between them (whitespace is added in the
               localization file, if necessary). -->
-          <description class="popup-notification-description"><html:span></html:span><html:b></html:b><html:span></html:span><html:b></html:b><html:span></html:span></description>
+          <description class="popup-notification-description"><html:span></html:span><html:b class="popup-notification-description-name"></html:b><html:span></html:span><html:b></html:b><html:span></html:span></description>
           <description class="popup-notification-hint-text"></description>
           <vbox class="popup-notification-bottom-content" align="start">
             <label class="popup-notification-learnmore-link" is="text-link" data-l10n-id="popup-notification-learn-more"></label>
diff --git a/toolkit/themes/shared/popupnotification.css b/toolkit/themes/shared/popupnotification.css
index 6a3c52a915f..4e25b887246 100644
--- a/toolkit/themes/shared/popupnotification.css
+++ b/toolkit/themes/shared/popupnotification.css
@@ -53,6 +53,16 @@ popupnotificationcontent {
   flex: 1 auto;
 }
 
+/*
+ * Ensure that host names in PopupNotifications wrap. This targets the "name"
+ * element in the description container which is the "name" property of the
+ * PopupNotification. Name is what gets substituted from the l10n string using
+ * the placeholder <>.
+ */
+.popup-notification-description-name {
+  word-break: break-all;
+}
+
 .popup-notification-closebutton {
   margin-inline-end: -8px;
   margin-top: -8px;
Loading diff…