Medium chrome Logic Error 📄 Reporter bug report 🔧 Commit mapped

Overview

Medium
Severity
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactInappropriate implementation in Chrome for iOS
DescriptionInappropriate implementation in Chrome for iOS
ComponentChrome for iOS
Bug ClassLogic Error
Tracker517801739
Fix commit9d6ffeabeac7 (chromium/src) +119/-37
CISA KEVNot listed
CreditedGoogle
Disclosed2026-07-29

Changed Functions

FunctionChangeNotes
switch
components/signin/ios/browser/account_consistency_service.mm
modified
if
components/signin/ios/browser/account_consistency_service.mm
modified

Files Changed

  • components/signin/ios/browser/account_consistency_service.mm
  • components/signin/ios/browser/account_consistency_service_unittest.mm
  • components/signin/ios/browser/manage_accounts_delegate.h
  • ios/chrome/browser/prerender/model/prerender_browser_agent.mm
  • ios/chrome/browser/signin/model/account_consistency_browser_agent.h
  • ios/chrome/browser/signin/model/account_consistency_browser_agent.mm
From 9d6ffeabeac7c7baf11c710905f9ffb22b87e51d Mon Sep 17 00:00:00 2001
From: Arthur Milchior <arthurmilchior@google.com>
Date: Mon, 15 Jun 2026 08:48:01 -0700
Subject: [PATCH] [iOS] Verify active WebState in AccountConsistencyHandler

Verify that the WebState initiating the request is the active tab before
executing any delegated actions in AccountConsistencyHandler.

This ensures that a background tab can’t open a native menu by
redirecting to a page that is intercepted by Chrome.

TAG=agy

Fixed: 517801739
Change-Id: I761f6cac37a4ce88eaddfb35eb76dd368f519600
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7925891
Auto-Submit: Arthur Milchior <arthurmilchior@chromium.org>
Commit-Queue: Arthur Milchior <arthurmilchior@chromium.org>
Reviewed-by: Gauthier Ambard <gambard@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1646842}
---

diff --git a/components/signin/ios/browser/account_consistency_service.mm b/components/signin/ios/browser/account_consistency_service.mm
index b4e545d2..e30aa59 100644
--- a/components/signin/ios/browser/account_consistency_service.mm
+++ b/components/signin/ios/browser/account_consistency_service.mm
@@ -276,7 +276,7 @@
   switch (params.service_type) {
     case signin::GAIA_SERVICE_TYPE_INCOGNITO: {
       if (delegate_) {
-        delegate_->OnGoIncognito(continue_url);
+        delegate_->OnGoIncognito(continue_url, web_state_);
       }
       break;
     }
@@ -296,13 +296,13 @@
         }
       }
       if (delegate_) {
-        delegate_->OnAddAccount(continue_url, params.email);
+        delegate_->OnAddAccount(continue_url, params.email, web_state_);
       }
       break;
     case signin::GAIA_SERVICE_TYPE_SIGNOUT:
     case signin::GAIA_SERVICE_TYPE_DEFAULT:
       if (delegate_) {
-        delegate_->OnManageAccounts(continue_url);
+        delegate_->OnManageAccounts(continue_url, web_state_);
       }
       break;
     case signin::GAIA_SERVICE_TYPE_NONE:
@@ -328,7 +328,7 @@
     // is not in an inconsistent state (where the identities on the device
     // are different than those on the web). Fallback to asking the user to
     // add an account.
-    delegate_->OnAddAccount(url, email);
+    delegate_->OnAddAccount(url, email, web_state_);
     return;
   }
   web_state_->OpenURL(web::WebState::OpenURLParams(
diff --git a/components/signin/ios/browser/account_consistency_service_unittest.mm b/components/signin/ios/browser/account_consistency_service_unittest.mm
index 9df98b3..ad6c7d87 100644
--- a/components/signin/ios/browser/account_consistency_service_unittest.mm
+++ b/components/signin/ios/browser/account_consistency_service_unittest.mm
@@ -103,11 +103,12 @@
   ~FakeManageAccountsDelegate() override = default;
 
   void OnRestoreGaiaCookies() override { restore_cookies_call_count_++; }
-  void OnManageAccounts(const GURL& url) override {
+  void OnManageAccounts(const GURL& url, web::WebState* web_state) override {
     manage_accounts_call_count_++;
   }
   void OnAddAccount(const GURL& url,
-                    const std::string& prefilled_email) override {
+                    const std::string& prefilled_email,
+                    web::WebState* web_state) override {
     add_account_call_count_++;
     add_account_email_ = prefilled_email;
   }
@@ -115,7 +116,9 @@
                               web::WebState* webState) override {
     show_promo_call_count_++;
   }
-  void OnGoIncognito(const GURL& url) override { go_incognito_call_count_++; }
+  void OnGoIncognito(const GURL& url, web::WebState* web_state) override {
+    go_incognito_call_count_++;
+  }
   bool SigninEnabled() const override { return true; }
 
   int total_call_count() {
diff --git a/components/signin/ios/browser/manage_accounts_delegate.h b/components/signin/ios/browser/manage_accounts_delegate.h
index 72c40b8..f0edd4b 100644
--- a/components/signin/ios/browser/manage_accounts_delegate.h
+++ b/components/signin/ios/browser/manage_accounts_delegate.h
@@ -25,7 +25,7 @@
   // property.
   // |url| is the continuation URL received from the server. If it is valid,
   // then this delegate should navigate to |url|.
-  virtual void OnManageAccounts(const GURL& url) = 0;
+  virtual void OnManageAccounts(const GURL& url, web::WebState* web_state) = 0;
 
   // Called when the user taps on an add account button in a Google web
   // property.
@@ -33,20 +33,21 @@
   // then this delegate should navigate to |url|.
   // |prefilled_email| is the email to pre-fill, if available.
   virtual void OnAddAccount(const GURL& url,
-                            const std::string& prefilled_email) = 0;
+                            const std::string& prefilled_email,
+                            web::WebState* web_state) = 0;
 
   // Called when the user taps a sign-in or add account button in a Google web
   // property.
   // |url| is the continuation URL received from the server. If it is valid,
   // then this delegate should navigate to |url|.
   virtual void OnShowConsistencyPromo(const GURL& url,
-                                      web::WebState* webState) = 0;
+                                      web::WebState* web_state) = 0;
 
   // Called when the user taps on go incognito button in a Google web property.
   // |url| is the continuation URL received from the server. If it is valid,
   // then this delegate should open an incognito tab and navigate to |url|.
   // If it is not valid, then this delegate should open a new incognito tab.
-  virtual void OnGoIncognito(const GURL& url) = 0;
+  virtual void OnGoIncognito(const GURL& url, web::WebState* web_state) = 0;
 
   // Whether the sign-in is not disabled.
   virtual bool SigninEnabled() const = 0;
diff --git a/ios/chrome/browser/prerender/model/prerender_browser_agent.mm b/ios/chrome/browser/prerender/model/prerender_browser_agent.mm
index 9701aa8..9526dec 100644
--- a/ios/chrome/browser/prerender/model/prerender_browser_agent.mm
+++ b/ios/chrome/browser/prerender/model/prerender_browser_agent.mm
@@ -365,16 +365,18 @@
 
   // ManageAccountsDelegate implementation.
   void OnRestoreGaiaCookies() final { agent_->ScheduleCancelPrerender(); }
-  void OnManageAccounts(const GURL& url) final {
+  void OnManageAccounts(const GURL& url, web::WebState* web_state) final {
     agent_->ScheduleCancelPrerender();
   }
-  void OnAddAccount(const GURL& url, const std::string& prefilled_email) final {
+  void OnAddAccount(const GURL& url,
+                    const std::string& prefilled_email,
+                    web::WebState* web_state) final {
     agent_->ScheduleCancelPrerender();
   }
-  void OnShowConsistencyPromo(const GURL& url, web::WebState* webState) final {
+  void OnShowConsistencyPromo(const GURL& url, web::WebState* web_state) final {
     agent_->ScheduleCancelPrerender();
   }
-  void OnGoIncognito(const GURL& url) final {
+  void OnGoIncognito(const GURL& url, web::WebState* web_state) final {
     agent_->ScheduleCancelPrerender();
   }
   bool SigninEnabled() const final {
diff --git a/ios/chrome/browser/signin/model/account_consistency_browser_agent.h b/ios/chrome/browser/signin/model/account_consistency_browser_agent.h
index 71e21ad..64d71d4 100644
--- a/ios/chrome/browser/signin/model/account_consistency_browser_agent.h
+++ b/ios/chrome/browser/signin/model/account_consistency_browser_agent.h
@@ -40,12 +40,13 @@
 
   // ManageAccountsDelegate
   void OnRestoreGaiaCookies() override;
-  void OnManageAccounts(const GURL& url) override;
+  void OnManageAccounts(const GURL& url, web::WebState* web_state) override;
   void OnAddAccount(const GURL& url,
-                    const std::string& prefilled_email) override;
+                    const std::string& prefilled_email,
+                    web::WebState* web_state) override;
   void OnShowConsistencyPromo(const GURL& url,
-                              web::WebState* webState) override;
-  void OnGoIncognito(const GURL& url) override;
+                              web::WebState* web_state) override;
+  void OnGoIncognito(const GURL& url, web::WebState* web_state) override;
   bool SigninEnabled() const override;
 
  private:
@@ -76,6 +77,9 @@
   // that's in a different profile).
   void ShowAccountMenu(const GURL& url);
 
+  // Whether `web_state` is the active one.
+  bool IsActiveWebstate(web::WebState* web_state);
+
   UIViewController* base_view_controller_;
   id<SceneCommands> application_handler_;
   id<SettingsCommands> settings_handler_;
diff --git a/ios/chrome/browser/signin/model/account_consistency_browser_agent.mm b/ios/chrome/browser/signin/model/account_consistency_browser_agent.mm
index b3043cc..2e52b06 100644
--- a/ios/chrome/browser/signin/model/account_consistency_browser_agent.mm
+++ b/ios/chrome/browser/signin/model/account_consistency_browser_agent.mm
@@ -99,7 +99,9 @@
       showSigninAccountNotificationFromViewController:base_view_controller_];
 }
 
-void AccountConsistencyBrowserAgent::OnManageAccounts(const GURL& url) {
+void AccountConsistencyBrowserAgent::OnManageAccounts(
+    const GURL& url,
+    web::WebState* web_state) {
   Browser::Type browser_type = browser_->type();
Loading diff…

Regression Test / PoC

shipped with the fix
diff --git a/components/signin/ios/browser/account_consistency_service_unittest.mm b/components/signin/ios/browser/account_consistency_service_unittest.mm
index 9df98b3..ad6c7d87 100644
--- a/components/signin/ios/browser/account_consistency_service_unittest.mm
+++ b/components/signin/ios/browser/account_consistency_service_unittest.mm
@@ -103,11 +103,12 @@
   ~FakeManageAccountsDelegate() override = default;
 
   void OnRestoreGaiaCookies() override { restore_cookies_call_count_++; }
-  void OnManageAccounts(const GURL& url) override {
+  void OnManageAccounts(const GURL& url, web::WebState* web_state) override {
     manage_accounts_call_count_++;
   }
   void OnAddAccount(const GURL& url,
-                    const std::string& prefilled_email) override {
+                    const std::string& prefilled_email,
+                    web::WebState* web_state) override {
     add_account_call_count_++;
     add_account_email_ = prefilled_email;
   }
@@ -115,7 +116,9 @@
                               web::WebState* webState) override {
     show_promo_call_count_++;
   }
-  void OnGoIncognito(const GURL& url) override { go_incognito_call_count_++; }
+  void OnGoIncognito(const GURL& url, web::WebState* web_state) override {
+    go_incognito_call_count_++;
+  }
   bool SigninEnabled() const override { return true; }
 
   int total_call_count() {
diff --git a/ios/chrome/browser/signin/model/account_consistency_browser_agent_unittest.mm b/ios/chrome/browser/signin/model/account_consistency_browser_agent_unittest.mm
index 6c2956c..3fc6cc1c 100644
--- a/ios/chrome/browser/signin/model/account_consistency_browser_agent_unittest.mm
+++ b/ios/chrome/browser/signin/model/account_consistency_browser_agent_unittest.mm
@@ -29,6 +29,7 @@
 #import "ios/chrome/browser/signin/model/identity_manager_factory.h"
 #import "ios/chrome/browser/web/model/web_navigation_browser_agent.h"
 #import "ios/chrome/test/ios_chrome_scoped_testing_local_state.h"
+#import "ios/web/public/test/fakes/fake_navigation_manager.h"
 #import "ios/web/public/test/fakes/fake_web_state.h"
 #import "ios/web/public/test/web_task_environment.h"
 #import "testing/platform_test.h"
@@ -72,8 +73,11 @@
 
     WebStateList* web_state_list = browser_.get()->GetWebStateList();
     auto test_web_state = std::make_unique<web::FakeWebState>();
+    test_web_state->SetNavigationManager(
+        std::make_unique<web::FakeNavigationManager>());
     web_state_list->InsertWebState(std::move(test_web_state),
                                    WebStateList::InsertionParams::AtIndex(0));
+    web_state_list->ActivateWebStateAt(0);
   }
 
   void TearDown() override {
@@ -116,7 +120,8 @@
   __block OpenNewTabCommand* received_command = nil;
   OCMExpect([mock_scene_handler_
       openURLInNewTab:AssignValueToVariable(received_command)]);
-  agent_->OnGoIncognito(GURL());
+  agent_->OnGoIncognito(GURL(),
+                        browser_->GetWebStateList()->GetActiveWebState());
   EXPECT_NE(received_command, nil);
   EXPECT_TRUE(received_command.inIncognito);
   EXPECT_FALSE(received_command.inBackground);
@@ -129,7 +134,7 @@
   __block OpenNewTabCommand* received_command = nil;
   OCMExpect([mock_scene_handler_
       openURLInNewTab:AssignValueToVariable(received_command)]);
-  agent_->OnGoIncognito(url_);
+  agent_->OnGoIncognito(url_, browser_->GetWebStateList()->GetActiveWebState());
   EXPECT_NE(received_command, nil);
   EXPECT_TRUE(received_command.inIncognito);
   EXPECT_FALSE(received_command.inBackground);
@@ -142,7 +147,8 @@
 TEST_F(AccountConsistencyBrowserAgentTest, OnAddAccountWithPresentedView) {
   OCMStub([base_view_controller_mock_ presentedViewController])
       .andReturn([[UIViewController alloc] init]);
-  agent_->OnAddAccount(GURL(), "");
+  agent_->OnAddAccount(GURL(), "",
+                       browser_->GetWebStateList()->GetActiveWebState());
   // Expect [mock_scene_handler_ showSignin:baseViewController:] to not
   // be called. This is ensured by TearDown because mock_scene_handler_
   // is a strict mock.
@@ -158,7 +164,8 @@
   OCMExpect([browser_coordinator_commands_mock_
       showAddAccountWithAccessPoint:access_point
                      prefilledEmail:@"test"]);
-  agent_->OnAddAccount(GURL(), "test");
+  agent_->OnAddAccount(GURL(), "test",
+                       browser_->GetWebStateList()->GetActiveWebState());
 }
 
 TEST_F(AccountConsistencyBrowserAgentTest, OnAddAccountShowsAccountMenu) {
@@ -181,7 +188,8 @@
   OCMExpect([mock_scene_handler_ showAccountMenuFromWebWithURL:url_]);
   // The expected email is foo2@gmail.com. Using foo.2 instead allows to check
   // adding account with a non-canonical email.
-  agent_->OnAddAccount(url_, "foo.2@gmail.com");
+  agent_->OnAddAccount(url_, "foo.2@gmail.com",
+                       browser_->GetWebStateList()->GetActiveWebState());
 }
 
 // Tests that calling the `OnRestoreGaiaCookies()` callback invokes the account
@@ -216,7 +224,8 @@
   OCMExpect([browser_coordinator_commands_mock_
       showAddAccountWithAccessPoint:access_point
                      prefilledEmail:email]);
-  agent_->OnAddAccount(url_, base::SysNSStringToUTF8(email));
+  agent_->OnAddAccount(url_, base::SysNSStringToUTF8(email),
+                       browser_->GetWebStateList()->GetActiveWebState());
 }
 
 // Tests that calling the `OnManageAccounts()` callback invokes the account
@@ -225,7 +234,8 @@
   OCMExpect([settings_commands_mock_
       showAccountsSettingsFromViewController:base_view_controller_mock_
                         skipIfUINotAvailable:YES]);
-  agent_->OnManageAccounts(GURL());
+  agent_->OnManageAccounts(GURL(),
+                           browser_->GetWebStateList()->GetActiveWebState());
   // Expect -showAccountsSettingsFromViewController:skipIfUINotAvailable: to
   // have been called. This is ensured by TearDown because
   // settings_commands_mock_ is a strict mock.
@@ -243,7 +253,8 @@
   // Since there is another profile, the agent should trigger the account menu
   // instead of the manage accounts screen.
   OCMExpect([mock_scene_handler_ showAccountMenuFromWebWithURL:url_]);
-  agent_->OnManageAccounts(url_);
+  agent_->OnManageAccounts(url_,
+                           browser_->GetWebStateList()->GetActiveWebState());
   // Expect showAccountsSettingsFromViewController:skipIfUINotAvailable: to not
   // be called. This is ensured by TearDown because mock_scene_handler_
   // is a strict mock.
@@ -287,3 +298,45 @@
   // This is ensured by TearDown because mock_scene_handler_ is a strict
   // mock.
 }
+
+// Tests that calling the `OnManageAccounts()` callback with a non-active
+// web state does not invoke any command.
+TEST_F(AccountConsistencyBrowserAgentTest, OnManageAccountsWithOtherWebState) {
+  WebStateList* web_state_list = browser_.get()->GetWebStateList();
+  web_state_list->ActivateWebStateAt(0);
+  auto test_web_state = std::make_unique<web::FakeWebState>();
+  WebStateOpener opener;
+  web_state_list->InsertWebState(
+      std::move(test_web_state),
+      WebStateList::InsertionParams::AtIndex(1).WithOpener(opener));
+  web::WebState* web_state = web_state_list->GetWebStateAt(1);
+  agent_->OnManageAccounts(url_, web_state);
+}
+
+// Tests that calling the `OnAddAccount()` callback with a non-active
+// web state does not invoke any command.
+TEST_F(AccountConsistencyBrowserAgentTest, OnAddAccountWithOtherWebState) {
+  WebStateList* web_state_list = browser_.get()->GetWebStateList();
+  web_state_list->ActivateWebStateAt(0);
+  auto test_web_state = std::make_unique<web::FakeWebState>();
+  WebStateOpener opener;
+  web_state_list->InsertWebState(
+      std::move(test_web_state),
+      WebStateList::InsertionParams::AtIndex(1).WithOpener(opener));
+  web::WebState* web_state = web_state_list->GetWebStateAt(1);
+  agent_->OnAddAccount(url_, "test", web_state);
+}
+
+// Tests that calling the `OnGoIncognito()` callback with a non-active
+// web state does not invoke any command.
+TEST_F(AccountConsistencyBrowserAgentTest, OnGoIncognitoWithOtherWebState) {
+  WebStateList* web_state_list = browser_.get()->GetWebStateList();
+  web_state_list->ActivateWebStateAt(0);
+  auto test_web_state = std::make_unique<web::FakeWebState>();
+  WebStateOpener opener;
+  web_state_list->InsertWebState(
+      std::move(test_web_state),
+      WebStateList::InsertionParams::AtIndex(1).WithOpener(opener));
+  web::WebState* web_state = web_state_list->GetWebStateAt(1);
+  agent_->OnGoIncognito(url_, web_state);
+}
Loading diff…

Original Bug Report

reported by vm...@google.com

iOS: Potential missing active-tab gate in signin mirror-header handler

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. Please see https://chromium.googlesource.com/chromium/src/+/main/docs/security/ai-generated-security-bugs-faq.md for more information.

Overview: The account consistency handler on Chrome for iOS processes Mirror headers received in background tabs without verifying if the associated tab is currently active. This allows background-tab navigations to potentially trigger trusted native Google account-management, add-account, or settings UI overlays over arbitrary foreground tabs. Additionally, background-tab navigations can trigger an unexpected back-navigation on the active foreground tab.

Affected files:

  • components/signin/ios/browser/account_consistency_service.mm
  • ios/chrome/browser/signin/model/account_consistency_browser_agent.mm
  • components/signin/ios/browser/manage_accounts_delegate.h

Estimated timestamp from git blame: 2015-09-07

Summary

A potential cross-tab isolation and UI spoofing vulnerability exists in Google Chrome for iOS due to a missing active-tab guard during the handling of Mirror header (X-Chrome-Manage-Accounts) actions. When a background tab initiates a navigation to a Google Gaia endpoint, Chrome processes the Mirror header responses in the background without validating whether the invoking web::WebState is the active, foremost tab. This allows a background tab to potentially trigger native, trusted settings or sign-in dialogs over an arbitrary foreground tab, or force an unsolicited back-navigation on the active foreground tab.

Root Cause Analysis

In components/signin/ios/browser/account_consistency_service.mm, the AccountConsistencyService::AccountConsistencyHandler::ShouldAllowResponse method intercepts responses from Gaia containing the X-Chrome-Manage-Accounts header (such as action=DEFAULT, action=ADDSESSION, or action=INCOGNITO):

void AccountConsistencyService::AccountConsistencyHandler::ShouldAllowResponse(
    NSURLResponse* response,
    web::WebStatePolicyDecider::ResponseInfo response_info,
    web::WebStatePolicyDecider::PolicyDecisionCallback callback) {
...
  switch (params.service_type) {
    case signin::GAIA_SERVICE_TYPE_INCOGNITO:
      if (delegate_) delegate_->OnGoIncognito(continue_url);
      break;
    ...

The issue is that ShouldAllowResponse does not check if the associated web_state_ is the active foreground tab before invoking these delegate methods. In addition, the delegate methods OnManageAccounts, OnAddAccount, and OnGoIncognito defined in components/signin/ios/browser/manage_accounts_delegate.h do not accept a web::WebState* parameter, preventing the delegate from performing the active-tab check at the sink level:

virtual void OnManageAccounts(const GURL& url) = 0;
virtual void OnAddAccount(const GURL& url, const std::string& email) = 0;
virtual void OnGoIncognito(const GURL& url) = 0;

In contrast, OnShowConsistencyPromo does accept a web::WebState* parameter and implements a proper check in ios/chrome/browser/signin/model/account_consistency_browser_agent.mm:

void AccountConsistencyBrowserAgent::OnShowConsistencyPromo(
    const GURL& url, web::WebState* web_state) {
  web::WebState* current_web_state =
      browser_->GetWebStateList()->GetActiveWebState();
  if (current_web_state == web_state) {
    [application_handler_ showWebSigninPromoFromViewController:base_view_controller_ URL:url];
  }
}

Without a similar check for the other actions:

  1. OnGoIncognito calls WebNavigationBrowserAgent::FromBrowser(browser_)->GoBack(); which operates directly on the active foreground WebState rather than the background WebState that initiated the action. This can force an unsolicited back-navigation on the active tab.
  2. OnManageAccounts and OnAddAccount present native dialogs (e.g., settings sheet, sign-in promo, or add-account controller) using base_view_controller_, which overlays the trusted UI directly over whichever foreground tab is currently active.

Potential Attack Scenario

Please note that these are suggested/potential steps as our analysis is based on code inspection and our tooling does not have the ability to run code.

  1. A victim is signed in to Chrome on iOS (making the CHROME_CONNECTED cookie present on accounts.google.com).
  2. The victim visits attacker.com (Tab B), which opens a new tab/popup pointing to attacker.com/lure (Tab C). Tab C becomes the active foreground tab, while Tab B is pushed into the background.
  3. Tab B initiates a background main-frame navigation to a Gaia URL, such as https://accounts.google.com/SignOutOptions or https://accounts.google.com/AddSession.
  4. The background tab’s WKWebView processes the navigation, transmitting the CHROME_CONNECTED cookie.
  5. The Gaia server returns a response with the X-Chrome-Manage-Accounts header.
  6. AccountConsistencyHandler::ShouldAllowResponse intercepts this response in the background. Because there is no active-tab check, it dispatches the action to the delegate.
  7. The browser presents native, trusted UIs (such as the SSO add-account dialog) over the active foreground tab (Tab C) or forces a back-navigation on it, depending on the action specified in the header.

Suggested Fix

To mitigate this potential vulnerability, Chrome for iOS should verify that the WebState initiating the request is the active/foremost tab before executing any of the delegated actions. This can be achieved by:

  1. Modifying the ManageAccountsDelegate interface to pass the source web::WebState* as a parameter to OnManageAccounts, OnAddAccount, and OnGoIncognito.
  2. Inside AccountConsistencyBrowserAgent, verifying that the passed WebState is equal to browser_->GetWebStateList()->GetActiveWebState() before displaying any UI or triggering navigation.

Evaluated with Chrome root at commit: 5133b93d189b383c37805b1cf3a9d2dbfe8d7379


Results so far have been promising, but there can be wrong deductions. Feel free to adjust as follows:

  • If you are familiar with the severity guidelines, you may adjust the severity.
  • If this is a false positive, and there’s no work to be done, please close as WAI.
  • If there is work to do here but not a vulnerability, please change the issue type to Task/Bug/FR.

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