Low chrome Logic Error 🔧 Commit mapped

Overview

Low
Severity
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactIncorrect authorization in Web Authentication
DescriptionIncorrect authorization in Web Authentication
ComponentWeb Authentication
Bug ClassLogic Error
Tracker499217288
Fix commit7f59498d7097 (chromium/src) +53/-18
CISA KEVNot listed
CreditedGoogle
Disclosed2026-09-08

Files Changed

  • content/browser/webauth/authenticator_impl_unittest.cc
  • content/browser/webauth/webauth_request_security_checker_impl.cc
From 7f59498d7097ca3905b4401463347e139bc905c5 Mon Sep 17 00:00:00 2001
From: Martin Kreichgauer <martinkr@google.com>
Date: Fri, 31 Jul 2026 14:20:44 -0700
Subject: [PATCH] webauthn: gate remoteDesktopClientOverride for all caller types

ValidateDomainAndRelyingPartyID returned early for callers whose
origin/RP-ID validation is delegated to the embedder (e.g.
chrome-extension:// origins) without first evaluating
OriginMayUseRemoteDesktopClientOverride against the caller. As a result,
such a caller could supply the remoteDesktopClientOverride extension and
have its origin written into the browser-generated clientDataJSON
regardless of whether the caller origin was on the device-level
allowlist.

In practice, OverrideCallerOriginAndRelyingPartyIdValidation severely
limits the set of origins an extension could claim by doing this, but
nevertheless it is a good idea to tighten this up.

Hoist the policy check to the start of the function so that it runs
before every early-return path, and replace the now redundant inline
check with a value_or() for the relying-party-origin assignment.

BUG=499217288
TAG=agy
CONV=b7e1564f-5289-478d-bba4-48195f9673f6

Change-Id: I4a423db7677e3abd875219621daec6ca9b95c884
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/8140023
Reviewed-by: Ken Buchanan <kenrb@chromium.org>
Commit-Queue: Martin Kreichgauer <martinkr@google.com>
Cr-Commit-Position: refs/heads/main@{#1672106}
---

diff --git a/content/browser/webauth/authenticator_impl_unittest.cc b/content/browser/webauth/authenticator_impl_unittest.cc
index 5e9f2feb..6ef94c5 100644
--- a/content/browser/webauth/authenticator_impl_unittest.cc
+++ b/content/browser/webauth/authenticator_impl_unittest.cc
@@ -3249,6 +3249,40 @@
   }
 }
 
+// A Chrome extension should not be authorized to use the
+// remoteDesktopClientOverride request extension.
+TEST_F(AuthenticatorImplRemoteDesktopClientOverrideTest,
+       ExtensionCallerOrigin) {
+  static const std::string kExtensionOrigin =
+      base::StrCat({kExtensionScheme, "://abcdefg"});
+  test_client_.GetTestWebAuthenticationDelegate()->permit_extensions = true;
+
+  {
+    PublicKeyCredentialCreationOptionsPtr options =
+        GetTestPublicKeyCredentialCreationOptions();
+    options->relying_party.id = kExampleRpId;
+    options->remote_desktop_client_override = RemoteDesktopClientOverride::New(
+        url::Origin::Create(GURL(kExampleOrigin)), true);
+    EXPECT_EQ(
+        AuthenticatorMakeCredential(std::move(options)).status,
+        AuthenticatorStatus::REMOTE_DESKTOP_CLIENT_OVERRIDE_NOT_AUTHORIZED);
+  }
+
+  {
+    PublicKeyCredentialRequestOptionsPtr options =
+        GetTestPublicKeyCredentialRequestOptions();
+    options->relying_party_id = kExampleRpId;
+    options->extensions->remote_desktop_client_override =
+        RemoteDesktopClientOverride::New(
+            url::Origin::Create(GURL(kExampleOrigin)), true);
+    ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectRegistration(
+        options->allow_credentials[0].id, kExtensionOrigin));
+    EXPECT_EQ(
+        AuthenticatorGetAssertion(std::move(options)).status,
+        AuthenticatorStatus::REMOTE_DESKTOP_CLIENT_OVERRIDE_NOT_AUTHORIZED);
+  }
+}
+
 TEST_F(AuthenticatorImplRemoteDesktopClientOverrideTest,
        GetAssertionImmediateMediation) {
   // Verify that an authorized origin may not use the extension with immediate
diff --git a/content/browser/webauth/webauth_request_security_checker_impl.cc b/content/browser/webauth/webauth_request_security_checker_impl.cc
index 8e49065..a40d72b 100644
--- a/content/browser/webauth/webauth_request_security_checker_impl.cc
+++ b/content/browser/webauth/webauth_request_security_checker_impl.cc
@@ -159,6 +159,23 @@
     RequestType request_type,
     const std::optional<url::Origin>& remote_desktop_client_override_origin,
     base::OnceCallback<void(blink::mojom::AuthenticatorStatus)> callback) {
+  if (remote_desktop_client_override_origin.has_value()) {
+    // SECURITY: `remote_desktop_client_override_origin` comes from the renderer
+    // process and should not be trusted by default. We only allow its use when
+    // the `caller_origin` is explicitly allowlisted through device level
+    // enterprise policy.
+    if (!GetContentClient()
+             ->browser()
+             ->GetWebAuthenticationDelegate()
+             ->OriginMayUseRemoteDesktopClientOverride(
+                 render_frame_host_->GetBrowserContext(), caller_origin)) {
+      std::move(callback).Run(
+          blink::mojom::AuthenticatorStatus::
+              REMOTE_DESKTOP_CLIENT_OVERRIDE_NOT_AUTHORIZED);
+      return nullptr;
+    }
+  }
+
 #if !BUILDFLAG(IS_ANDROID)
   // Extensions are not supported on Android.
   if (GetContentClient()
@@ -188,24 +205,8 @@
     return nullptr;
   }
 
-  url::Origin relying_party_origin = caller_origin;
-  if (remote_desktop_client_override_origin.has_value()) {
-    // SECURITY: `remote_desktop_client_override_origin` comes from the renderer
-    // process and should not be trusted by default. We only allow its use when
-    // the `caller_origin` is explicitly allowlisted through device level
-    // enterprise policy.
-    if (!GetContentClient()
-             ->browser()
-             ->GetWebAuthenticationDelegate()
-             ->OriginMayUseRemoteDesktopClientOverride(
-                 render_frame_host_->GetBrowserContext(), caller_origin)) {
-      std::move(callback).Run(
-          blink::mojom::AuthenticatorStatus::
-              REMOTE_DESKTOP_CLIENT_OVERRIDE_NOT_AUTHORIZED);
-      return nullptr;
-    }
-    relying_party_origin = remote_desktop_client_override_origin.value();
-  }
+  url::Origin relying_party_origin =
+      remote_desktop_client_override_origin.value_or(caller_origin);
 
   if (webauthn::OriginIsAllowedToClaimRelyingPartyId(relying_party_id,
                                                      relying_party_origin)) {
Loading diff…

Regression Test / PoC

shipped with the fix
diff --git a/content/browser/webauth/authenticator_impl_unittest.cc b/content/browser/webauth/authenticator_impl_unittest.cc
index 5e9f2feb..6ef94c5 100644
--- a/content/browser/webauth/authenticator_impl_unittest.cc
+++ b/content/browser/webauth/authenticator_impl_unittest.cc
@@ -3249,6 +3249,40 @@
   }
 }
 
+// A Chrome extension should not be authorized to use the
+// remoteDesktopClientOverride request extension.
+TEST_F(AuthenticatorImplRemoteDesktopClientOverrideTest,
+       ExtensionCallerOrigin) {
+  static const std::string kExtensionOrigin =
+      base::StrCat({kExtensionScheme, "://abcdefg"});
+  test_client_.GetTestWebAuthenticationDelegate()->permit_extensions = true;
+
+  {
+    PublicKeyCredentialCreationOptionsPtr options =
+        GetTestPublicKeyCredentialCreationOptions();
+    options->relying_party.id = kExampleRpId;
+    options->remote_desktop_client_override = RemoteDesktopClientOverride::New(
+        url::Origin::Create(GURL(kExampleOrigin)), true);
+    EXPECT_EQ(
+        AuthenticatorMakeCredential(std::move(options)).status,
+        AuthenticatorStatus::REMOTE_DESKTOP_CLIENT_OVERRIDE_NOT_AUTHORIZED);
+  }
+
+  {
+    PublicKeyCredentialRequestOptionsPtr options =
+        GetTestPublicKeyCredentialRequestOptions();
+    options->relying_party_id = kExampleRpId;
+    options->extensions->remote_desktop_client_override =
+        RemoteDesktopClientOverride::New(
+            url::Origin::Create(GURL(kExampleOrigin)), true);
+    ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectRegistration(
+        options->allow_credentials[0].id, kExtensionOrigin));
+    EXPECT_EQ(
+        AuthenticatorGetAssertion(std::move(options)).status,
+        AuthenticatorStatus::REMOTE_DESKTOP_CLIENT_OVERRIDE_NOT_AUTHORIZED);
+  }
+}
+
 TEST_F(AuthenticatorImplRemoteDesktopClientOverrideTest,
        GetAssertionImmediateMediation) {
   // Verify that an authorized origin may not use the extension with immediate
Loading diff…

Original Bug Report

The reporter's bug is still restricted on the tracker. Chrome de-restricts security bugs ~30–90 days after the fix ships; a later run will backfill it here.