CVE-2026-7990
Overview
Files Changed
chrome/installer/setup/setup_main.cc
Patch
From 07a07ca1e5230ffcb12a361ed12858b6f80a2f6c Mon Sep 17 00:00:00 2001 From: David Bienvenu <[email protected]> Date: Fri, 03 Apr 2026 13:07:10 -0700 Subject: [PATCH] win installer: reorder handling of on-os-upgrade Bug: 498892267 Change-Id: Ib764cb9c3759fa4993efd9113b29d16d677184cb Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7729007 Reviewed-by: S Ganesh <[email protected]> Commit-Queue: David Bienvenu <[email protected]> Cr-Commit-Position: refs/heads/main@{#1609926} --- diff --git a/chrome/installer/setup/setup_main.cc b/chrome/installer/setup/setup_main.cc index 8248498..accfea5 100644 --- a/chrome/installer/setup/setup_main.cc +++ b/chrome/installer/setup/setup_main.cc @@ -945,6 +945,21 @@ CreateEulaSentinel(); } } + } else if (cmd_line.HasSwitch(installer::switches::kOnOsUpgrade)) { + installer::InstallStatus status = installer::INVALID_STATE_FOR_OPTION; + std::unique_ptr<FileVersionInfo> version_info( + FileVersionInfo::CreateFileVersionInfo(setup_exe)); + const base::Version installed_version( + base::UTF16ToUTF8(version_info->product_version())); + if (installed_version.IsValid()) { + installer::HandleOsUpgradeForBrowser(*installer_state, installed_version, + setup_exe); + status = installer::INSTALL_REPAIRED; + } else { + LOG(DFATAL) << "Failed to extract product version from " + << setup_exe.value(); + } + *exit_code = InstallUtil::GetInstallReturnCode(status); } else if (cmd_line.HasSwitch(installer::switches::kConfigureUserSettings)) { // NOTE: Should the work done here, on kConfigureUserSettings, change: // kActiveSetupVersion in install_worker.cc needs to be increased for Active @@ -1058,21 +1073,6 @@ installer::DeleteChromeRegistrationKeys(*installer_state, HKEY_LOCAL_MACHINE, suffix, &tmp); *exit_code = tmp; - } else if (cmd_line.HasSwitch(installer::switches::kOnOsUpgrade)) { - installer::InstallStatus status = installer::INVALID_STATE_FOR_OPTION; - std::unique_ptr<FileVersionInfo> version_info( - FileVersionInfo::CreateFileVersionInfo(setup_exe)); - const base::Version installed_version( - base::UTF16ToUTF8(version_info->product_version())); - if (installed_version.IsValid()) { - installer::HandleOsUpgradeForBrowser(*installer_state, installed_version, - setup_exe); - status = installer::INSTALL_REPAIRED; - } else { - LOG(DFATAL) << "Failed to extract product version from " - << setup_exe.value(); - } - *exit_code = InstallUtil::GetInstallReturnCode(status); } else if (cmd_line.HasSwitch(installer::switches::kReenableAutoupdates)) { // setup.exe has been asked to attempt to reenable updates for Chrome. bool updates_enabled = GoogleUpdateSettings::ReenableAutoupdates();
Original Bug Report
Potential Argument Injection in Updater AppCommand leads to SYSTEM EoP
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 without the security team.
Overview: A potential argument injection vulnerability exists in the Chrome Updater’s handling of the on-os-upgrade AppCommand. An unprivileged user can leverage a SYSTEM-level COM server to inject arbitrary command-line switches into a SYSTEM process. This can lead to a persistent local privilege escalation to SYSTEM.
Affected files:
chrome/updater/win/app_command_runner.ccchrome/updater/app/server/win/com_classes_legacy.ccchrome/installer/setup/install_worker.ccchrome/installer/setup/setup_main.cc
Estimated timestamp from git blame: 2024-12-19
A potential argument injection vulnerability exists in the Chrome Updater on Windows, allowing a standard unprivileged user to escalate privileges to SYSTEM. This occurs due to a combination of insecure command registration, bypassed COM access checks, and switch precedence issues in the installer.
Root Causes
- Unprivileged COM Access: The SYSTEM-scope COM server (
GoogleUpdate3WebSystemClass) can be instantiated by standard interactive users. When thecreateInstalledAppmethod is called inchrome/updater/app/server/win/com_classes_legacy.cc, it hardcodesis_install = false. This bypasses theIsCOMCallerAllowedcheck, which otherwise enforces administrator rights. - Insecure Command Registration: In
chrome/installer/setup/install_worker.cc, theon-os-upgradeAppCommand is registered with a bare positional%1placeholder (cmd_line.AppendArg("%1")). - Verbatim Parameter Substitution: When an AppCommand is executed,
AppCommandRunner::Runusesbase::internal::DoReplaceStringPlaceholdersto substitute%1. Because the parameter is not confined (e.g.,--switch=%1), an attacker can supply a string starting with--that will be parsed as a brand new switch by the child process. - Switch Precedence: In
chrome/installer/setup/setup_main.cc,HandleNonInstallCmdLineOptionsprocesses potentially dangerous switches like--register-chrome-browserand--remove-chrome-registrationbefore the intended--on-os-upgradeswitch.
Potential Attack Steps
Note: These are suggested steps based on static code analysis; our tooling does not yet have the ability to run code to provide a working Proof of Concept.
- As a standard unprivileged user, an attacker executes a script to instantiate the
GoogleUpdate3WebSystemClassCOM object. - The attacker calls
createInstalledAppwith the Chrome AppID to obtain anIAppWebinterface, bypassing admin checks. - The attacker calls
get_command("on-os-upgrade")to retrieve the registered AppCommand object. - The attacker calls
execute()on the command, providing a malicious argument for the first substitution parameter, such as--register-chrome-browser=C:\path\to\evil.exe. - The updater substitutes the
%1placeholder and launchessetup.exeas SYSTEM with the injected switch. setup.exeevaluates the injected--register-chrome-browserswitch, writing the attacker’s executable path to global HKLM registry keys (e.g.,Software\Classes\ChromeHTML\shell\open\command).- The attacker achieves persistent SYSTEM-level code execution triggered whenever any user opens a file or URL associated with Chrome.
Suggested Fix
- Confine the Placeholder: Modify
chrome/installer/setup/install_worker.ccso theon-os-upgradeparameter is explicitly confined to a safe switch format, e.g.,--previous-version=%1instead of a bare%1. - Enforce COM Access Controls: Ensure that sensitive AppCommands are protected by access controls (e.g., re-introducing a
WebAccessiblegate or strictly checking caller privileges for all commands inGoogleUpdate3WebSystemClass). - Review Switch Evaluation Precedence: Ensure
setup_main.ccprioritizes specific action switches (like--on-os-upgrade) in a mutually exclusive or safe manner so that unexpected combinations of switches do not lead to unintended side effects.
Evaluated with Chrome root at commit: ff3d2b74fa39431785bd60e51463b08fcc71ee33
Results so far have been promising, but there can be wrong deductions. If this proves to be a false positive, please close as WAI; 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.