Medium chrome Logic Error 📄 Reporter bug report 🔧 Commit mapped

Overview

Medium
Severity
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactInsufficient validation of untrusted input in Updater
DescriptionInsufficient validation of untrusted input in Updater
ComponentUpdater
Bug ClassLogic Error
Tracker498892267
Fix commit07a07ca1e523 (chromium/src) +15/-15
CISA KEVNot listed
CreditedGoogle
Disclosed2026-05-05

Files Changed

  • chrome/installer/setup/setup_main.cc
From 07a07ca1e5230ffcb12a361ed12858b6f80a2f6c Mon Sep 17 00:00:00 2001
From: David Bienvenu <davidbienvenu@chromium.org>
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 <ganesh@chromium.org>
Commit-Queue: David Bienvenu <davidbienvenu@chromium.org>
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();
Loading diff…

Original Bug Report

reported by vm...@google.com

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.cc
  • chrome/updater/app/server/win/com_classes_legacy.cc
  • chrome/installer/setup/install_worker.cc
  • chrome/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

  1. Unprivileged COM Access: The SYSTEM-scope COM server (GoogleUpdate3WebSystemClass) can be instantiated by standard interactive users. When the createInstalledApp method is called in chrome/updater/app/server/win/com_classes_legacy.cc, it hardcodes is_install = false. This bypasses the IsCOMCallerAllowed check, which otherwise enforces administrator rights.
  2. Insecure Command Registration: In chrome/installer/setup/install_worker.cc, the on-os-upgrade AppCommand is registered with a bare positional %1 placeholder (cmd_line.AppendArg("%1")).
  3. Verbatim Parameter Substitution: When an AppCommand is executed, AppCommandRunner::Run uses base::internal::DoReplaceStringPlaceholders to 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.
  4. Switch Precedence: In chrome/installer/setup/setup_main.cc, HandleNonInstallCmdLineOptions processes potentially dangerous switches like --register-chrome-browser and --remove-chrome-registration before the intended --on-os-upgrade switch.

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.

  1. As a standard unprivileged user, an attacker executes a script to instantiate the GoogleUpdate3WebSystemClass COM object.
  2. The attacker calls createInstalledApp with the Chrome AppID to obtain an IAppWeb interface, bypassing admin checks.
  3. The attacker calls get_command("on-os-upgrade") to retrieve the registered AppCommand object.
  4. 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.
  5. The updater substitutes the %1 placeholder and launches setup.exe as SYSTEM with the injected switch.
  6. setup.exe evaluates the injected --register-chrome-browser switch, writing the attacker’s executable path to global HKLM registry keys (e.g., Software\Classes\ChromeHTML\shell\open\command).
  7. 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.cc so the on-os-upgrade parameter is explicitly confined to a safe switch format, e.g., --previous-version=%1 instead of a bare %1.
  • Enforce COM Access Controls: Ensure that sensitive AppCommands are protected by access controls (e.g., re-introducing a WebAccessible gate or strictly checking caller privileges for all commands in GoogleUpdate3WebSystemClass).
  • Review Switch Evaluation Precedence: Ensure setup_main.cc prioritizes 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.

View on issue tracker