Low CVSS 8.8 firefox Logic Error 🔧 Commit mapped

Overview

Low
Severity
8.8
CVSS
No
Exploited ITW
Fixed
Fix Status
Impactlow
DescriptionWhen handling keypress events, an attacker may have been able to trick a user into bypassing the "Open Executable File?" confirmation dialog. This could have led to malicious code execution.
ComponentToolkit
Bug ClassLogic Error
Tracker1842187
Fix commit366f2f5d06b2 (firefox) +4/-1
CWECWE-94
CVSS vectorCVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H
CISA KEVNot listed
CreditedUmar Farooq
Disclosed2024-11-26

Background

`DownloadPrompter`
the Toolkit helper object (in DownloadUIHelper.sys.mjs) whose prototype methods display the download-related confirmation dialogs shown to the user.
`nsIPrompt.confirm`
a synchronous prompt API that shows a two-button OK/Cancel dialog whose buttons are enabled and focusable the instant the dialog appears.
`nsIPrompt.confirmEx`
a richer prompt API that accepts a flags bitmask, letting the caller control button labels, layout, and timing behavior.
`BUTTON_DELAY_ENABLE`
an nsIPrompt flag that disables the accept button for a short interval after the dialog opens, defeating queued or auto-repeating keystrokes.

Root Cause Analysis

The DownloadPrompter.prototype method that warns before launching an executable download rendered its “Open Executable File?” dialog through this._prompter.confirm(title, message), which presents the OK button as immediately actionable. Because the dialog inherited focus with no activation delay, a keypress (for example a held or scripted Enter/Space) that was already in flight or auto-repeating when the dialog appeared could dismiss it and confirm the launch before the user could read the warning. The security invariant — that a destructive confirmation must reflect a deliberate, informed user decision rather than a stray or attacker-timed keystroke — was therefore violated.

The fix replaces the call with this._prompter.confirmEx(title, message, flags, ...) and sets flags to Ci.nsIPrompt.BUTTON_DELAY_ENABLE | Ci.nsIPrompt.STD_OK_CANCEL_BUTTONS, so the accept button is briefly disabled after the dialog opens and pre-queued keystrokes can no longer auto-confirm it. It works because any keypress arriving during the enforced delay window is ignored by the button, forcing a fresh, post-delay interaction.

Key insight
The core mistake was showing a high-consequence confirmation dialog with no button-activation delay, so a race between the dialog appearing and an in-flight keypress could silently confirm it; adding BUTTON_DELAY_ENABLE via confirmEx closes that race by requiring input only after the button becomes live.

Attack Path

  1. Prime the executable download The attacker gets the victim to download or open a file that Firefox treats as executable, so the “Open Executable File?” warning will be triggered.
  2. Induce a rapid keystroke The attacker arranges for the user to be holding or repeatedly pressing Enter/Space (via a game, a fake CAPTCHA, or scripted key auto-repeat) just as the dialog is about to appear.
  3. Win the timing race The queued or auto-repeating keypress reaches the freshly shown confirm dialog whose OK button is already enabled and focused, activating it instantly.
  4. Bypass the warning The dialog is dismissed as confirmed before the user perceives or reads it, and the executable launches without an informed decision.

Impact Assessment

An attacker can bypass the executable-launch confirmation and achieve code execution in the context the launched file runs in, effectively the user’s own privileges outside the browser sandbox. Preconditions are that the attacker can stage an executable download and can lure the user into supplying a keystroke coincident with the dialog’s appearance, which limits reliability and accounts for the low severity rating.

Files Changed

  • toolkit/components/downloads/DownloadUIHelper.sys.mjs

Audit Directions

  • Immediate-enable confirmations
    Search for other nsIPrompt.confirm / confirmEx call sites guarding destructive or privileged actions that omit BUTTON_DELAY_ENABLE, since any of them can be defeated by keystroke-timing races.
  • Focus and default-button races
    Review dialogs that open with a default accept button focused while input events may already be queued, especially those triggered by page-initiated flows like downloads or permission grants.
  • Keypress-driven UI gating
    Audit security-relevant UI that becomes actionable synchronously on appearance and can be reached by keypress/auto-repeat, looking for missing debounce, delay, or explicit-interaction requirements.
diff --git a/toolkit/components/downloads/DownloadUIHelper.sys.mjs b/toolkit/components/downloads/DownloadUIHelper.sys.mjs
index 0d1d0e0a319..d4b903d3839 100644
--- a/toolkit/components/downloads/DownloadUIHelper.sys.mjs
+++ b/toolkit/components/downloads/DownloadUIHelper.sys.mjs
@@ -171,7 +171,10 @@ DownloadPrompter.prototype = {
       "download-ui-file-executable-security-warning",
       { executable: PathUtils.filename(path) }
     );
-    return this._prompter.confirm(title, message);
+    let flags =
+      Ci.nsIPrompt.BUTTON_DELAY_ENABLE | Ci.nsIPrompt.STD_OK_CANCEL_BUTTONS;
+    let nulls = Array(4).fill(null);
+    return 0 == this._prompter.confirmEx(title, message, flags, ...nulls, {});
   },
 
   /**
Loading diff…