High chrome Logic Error 📄 Reporter bug report

Overview

High
Severity
CVSS
No
Exploited ITW
Embargoed
Fix Status
ImpactInappropriate implementation in Enterprise
DescriptionInappropriate implementation in Enterprise
ComponentEnterprise
Bug ClassLogic Error
Tracker513399832
CISA KEVNot listed
CreditedGoogle
Disclosed2026-06-30

Fix not yet public

No public source fix for this bug has been identified on the main branch yet — it is embargoed or not yet disclosed. Root-cause analysis is withheld until the fix commit is available.

Original Bug Report

reported by [email protected]

Potential cross-tenant PII and bearer token leak in SaasUsageBrowserReportUploaderDesktop

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 SaasUsageBrowserReportUploaderDesktop selects a reporting client from the first available loaded profile without verifying its affiliation with the browser’s management entity. This causes browser-level SaaS usage reports to include sensitive PII (GAIA email) and authentication credentials (User DM tokens) from unrelated profiles, which are then transmitted to the browser’s managing organization.

Affected files:

  • chrome/browser/enterprise/reporting/saas_usage/saas_usage_report_uploader_desktop.cc
  • chrome/browser/profiles/reporting_util.cc
  • chrome/browser/enterprise/connectors/reporting/realtime_reporting_client.cc
  • components/enterprise/connectors/core/realtime_reporting_client_base.cc

Estimated timestamp from git blame: 2026-02-18

Description

The SaasUsageBrowserReportUploaderDesktop class is responsible for uploading browser-level SaaS usage reports. When performing an upload, it must obtain an instance of RealtimeReportingClientBase. The current implementation of GetRealTimeReportingClient iterates through all currently loaded profiles and returns the client from the first one it finds:

// chrome/browser/enterprise/reporting/saas_usage/saas_usage_report_uploader_desktop.cc
enterprise_connectors::RealtimeReportingClientBase*
SaasUsageBrowserReportUploaderDesktop::GetRealTimeReportingClient() {
  for (auto* profile :
       g_browser_process->profile_manager()->GetLoadedProfiles()) {
    auto* client =
        enterprise_connectors::RealtimeReportingClientFactory::GetForProfile(
            profile);
    if (client) {
      return client;
    }
  }
  return nullptr;
}

On Desktop platforms, RealtimeReportingClient is a Profile-keyed service. When ReportSaasUsageEvent is called, it eventually invokes the virtual method CreateUploadEventsRequest() to generate the metadata for the reporting request. Since the client is bound to a specific profile, it populates the metadata using reporting::CreateUploadEventsRequest(Profile*) for that profile.

This metadata includes highly sensitive information:

  1. The profile’s GAIA email.
  2. The profile’s User Device Management (DM) token (a bearer credential used for policy retrieval and authentication).

If the browser is managed by Organization X (using a browser-level DM token), but the first loaded profile is a personal account or managed by Organization Y, the reporting stream for Organization X will receive the email and bearer credentials of the unrelated profile. This results in a cross-tenant information disclosure and credential leak.

Potential Impact

Administrators of Organization X can receive the GAIA emails and User DM tokens of accounts belonging to different organizations or personal users on the same device. User DM tokens are sensitive bearer credentials that can be used to authenticate as that user to Google’s Device Management server, potentially allowing unauthorized policy retrieval or further impersonation. Additionally, browser-level SaaS metrics are misattributed to whichever profile happens to be loaded first by the ProfileManager.

Suggested Potential Reproduction Steps

  1. Enroll a Chrome browser in Chrome Browser Cloud Management (CBCM) under Organization X.
  2. Enable SaaS usage reporting via the SaasUsageReportingDomainUrlsForBrowsers policy from Organization X’s console.
  3. Create or load a second profile (Profile B) that is either a personal Google account or managed by a different organization (Organization Y).
  4. Ensure Profile B’s directory name causes it to be sorted first in the ProfileManager (e.g., directory name is “Default”).
  5. Visit a URL matching the SaaS usage policy in any profile.
  6. Trigger the periodic report upload (e.g., by waiting for the 4-hour interval or manually resetting the last trigger time in Local State).
  7. Intercept the outgoing network request to the realtime-reporting endpoint. Observe that while the Authorization header uses Organization X’s browser DM token, the protobuf body contains the GAIA email and User DM token belonging to Profile B.

Suggested Fix

SaasUsageBrowserReportUploaderDesktop should ensure it only uses a reporting client from a profile that is affiliated with the browser’s management entity (using enterprise_util::IsProfileAffiliated). Alternatively, the RealtimeReportingClient should be updated to omit profile-specific PII and credentials when performing browser-level (non-per-profile) reporting if the profile is not affiliated.

Evaluated with Chrome root at commit: b3153093eb3c78c3e88ccf562bcbc20437a04b0e


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