Firefox · DOM
CVE-2026-0890
Logic Error in DOM
Overview
Low
Severity
—
CVSS
No
Exploited ITW
Fixed
Fix Status
Changed Functions
| Function | Change | Notes |
|---|---|---|
ifbrowser/base/content/browser.js |
modified | |
add_taskdom/events/test/clipboard/browser_navigator_clipboard_contextmenu_dismiss.js |
modified |
Files Changed
browser/base/content/browser.jsdom/events/test/clipboard/browser.tomldom/events/test/clipboard/browser_navigator_clipboard_contextmenu_dismiss.jstoolkit/modules/ClipboardContextMenu.sys.mjs
Patch
diff --git a/browser/base/content/browser.js b/browser/base/content/browser.js
index 76c996f69ec..b4755a2e5ae 100644
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -2250,7 +2250,7 @@ var XULBrowserWindow = {
// Ensure we close any remaining open locationspecific panels
if (!isSameDocument) {
- closeOpenPanels("panel[locationspecific='true']");
+ closeOpenPanels(":is(panel, menupopup)[locationspecific='true']");
}
gPermissionPanel.onLocationChange();
diff --git a/dom/events/test/clipboard/browser.toml b/dom/events/test/clipboard/browser.toml
index 21c5d85a911..cf4ff51406d 100644
--- a/dom/events/test/clipboard/browser.toml
+++ b/dom/events/test/clipboard/browser.toml
@@ -17,6 +17,12 @@ run-if = [
"os != 'win'", # The popupmenus dismiss when access keys for disabled items are pressed on windows
]
+["browser_navigator_clipboard_contextmenu_dismiss.js"]
+support-files = [
+ "file_toplevel.html",
+ "file_iframe.html",
+]
+
["browser_navigator_clipboard_contextmenu_suppression.js"]
support-files = [
"file_toplevel.html",
diff --git a/dom/events/test/clipboard/browser_navigator_clipboard_contextmenu_dismiss.js b/dom/events/test/clipboard/browser_navigator_clipboard_contextmenu_dismiss.js
new file mode 100644
index 00000000000..f09c2a9f153
--- /dev/null
+++ b/dom/events/test/clipboard/browser_navigator_clipboard_contextmenu_dismiss.js
@@ -0,0 +1,56 @@
+/* -*- Mode: JavaScript; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict";
+
+const kContentFileUrl = kBaseUrlForContent + "file_toplevel.html";
+
+async function readText(aBrowser) {
+ return SpecialPowers.spawn(aBrowser, [], () => {
+ content.document.notifyUserGestureActivation();
+ content.eval(`navigator.clipboard.readText();`);
+ });
+}
+
+add_task(async function test_context_menu_dimiss_tab_navigate() {
+ await BrowserTestUtils.withNewTab(kContentFileUrl, async aBrowser => {
+ info(`Randomized text to avoid overlappings with other tests`);
+ await promiseWritingRandomTextToClipboard();
+
+ info(`Wait for paste context menu is shown`);
+ let pasteButtonIsShown = promisePasteButtonIsShown();
+ await readText(aBrowser);
+ await pasteButtonIsShown;
+
+ info("Navigate tab");
+ let pasteButtonIsHidden = promisePasteButtonIsHidden();
+ aBrowser.loadURI(Services.io.newURI("https://example.com/"), {
+ triggeringPrincipal: Services.scriptSecurityManager.getSystemPrincipal(),
+ });
+
+ info(`Wait for paste context menu is hidden`);
+ await pasteButtonIsHidden;
+ });
+});
+
+add_task(async function test_context_menu_dimiss_tab_reload() {
+ await BrowserTestUtils.withNewTab(kContentFileUrl, async aBrowser => {
+ info(`Randomized text to avoid overlappings with other tests`);
+ await promiseWritingRandomTextToClipboard();
+
+ info(`Wait for paste context menu is shown`);
+ let pasteButtonIsShown = promisePasteButtonIsShown();
+ await readText(aBrowser);
+ await pasteButtonIsShown;
+
+ info("Reload tab");
+ let pasteButtonIsHidden = promisePasteButtonIsHidden();
+ await BrowserTestUtils.reloadTab(gBrowser.selectedTab);
+
+ info(`Wait for paste context menu is hidden`);
+ await pasteButtonIsHidden;
+ });
+});
diff --git a/toolkit/modules/ClipboardContextMenu.sys.mjs b/toolkit/modules/ClipboardContextMenu.sys.mjs
index 2175da37eb5..080b87fecbf 100644
--- a/toolkit/modules/ClipboardContextMenu.sys.mjs
+++ b/toolkit/modules/ClipboardContextMenu.sys.mjs
@@ -164,6 +164,7 @@ export var ClipboardContextMenu = {
let menupopup = aChromeDoc.createXULElement("menupopup");
menupopup.id = this.MENU_POPUP_ID;
menupopup.setAttribute("tabspecific", "true");
+ menupopup.setAttribute("locationspecific", "true");
menupopup.appendChild(menuitem);
return menupopup;
},
Loading diff…
Regression Test / PoC
shipped with the fix
diff --git a/dom/events/test/clipboard/browser.toml b/dom/events/test/clipboard/browser.toml
index 21c5d85a911..cf4ff51406d 100644
--- a/dom/events/test/clipboard/browser.toml
+++ b/dom/events/test/clipboard/browser.toml
@@ -17,6 +17,12 @@ run-if = [
"os != 'win'", # The popupmenus dismiss when access keys for disabled items are pressed on windows
]
+["browser_navigator_clipboard_contextmenu_dismiss.js"]
+support-files = [
+ "file_toplevel.html",
+ "file_iframe.html",
+]
+
["browser_navigator_clipboard_contextmenu_suppression.js"]
support-files = [
"file_toplevel.html",
diff --git a/dom/events/test/clipboard/browser_navigator_clipboard_contextmenu_dismiss.js b/dom/events/test/clipboard/browser_navigator_clipboard_contextmenu_dismiss.js
new file mode 100644
index 00000000000..f09c2a9f153
--- /dev/null
+++ b/dom/events/test/clipboard/browser_navigator_clipboard_contextmenu_dismiss.js
@@ -0,0 +1,56 @@
+/* -*- Mode: JavaScript; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict";
+
+const kContentFileUrl = kBaseUrlForContent + "file_toplevel.html";
+
+async function readText(aBrowser) {
+ return SpecialPowers.spawn(aBrowser, [], () => {
+ content.document.notifyUserGestureActivation();
+ content.eval(`navigator.clipboard.readText();`);
+ });
+}
+
+add_task(async function test_context_menu_dimiss_tab_navigate() {
+ await BrowserTestUtils.withNewTab(kContentFileUrl, async aBrowser => {
+ info(`Randomized text to avoid overlappings with other tests`);
+ await promiseWritingRandomTextToClipboard();
+
+ info(`Wait for paste context menu is shown`);
+ let pasteButtonIsShown = promisePasteButtonIsShown();
+ await readText(aBrowser);
+ await pasteButtonIsShown;
+
+ info("Navigate tab");
+ let pasteButtonIsHidden = promisePasteButtonIsHidden();
+ aBrowser.loadURI(Services.io.newURI("https://example.com/"), {
+ triggeringPrincipal: Services.scriptSecurityManager.getSystemPrincipal(),
+ });
+
+ info(`Wait for paste context menu is hidden`);
+ await pasteButtonIsHidden;
+ });
+});
+
+add_task(async function test_context_menu_dimiss_tab_reload() {
+ await BrowserTestUtils.withNewTab(kContentFileUrl, async aBrowser => {
+ info(`Randomized text to avoid overlappings with other tests`);
+ await promiseWritingRandomTextToClipboard();
+
+ info(`Wait for paste context menu is shown`);
+ let pasteButtonIsShown = promisePasteButtonIsShown();
+ await readText(aBrowser);
+ await pasteButtonIsShown;
+
+ info("Reload tab");
+ let pasteButtonIsHidden = promisePasteButtonIsHidden();
+ await BrowserTestUtils.reloadTab(gBrowser.selectedTab);
+
+ info(`Wait for paste context menu is hidden`);
+ await pasteButtonIsHidden;
+ });
+});
Loading diff…
References
On This Page