CVE-2026-78957
Overview
Changed Functions
| Function | Change | Notes |
|---|---|---|
ifios/chrome/browser/signin/model/system_account_updater.mm |
modified |
Files Changed
ios/chrome/browser/signin/model/system_account_updater.mmios/chrome/common/app_group/app_group_helper.mm
Patch
From d0d5365551873437d63fd49fc63ea55560d6fecc Mon Sep 17 00:00:00 2001 From: Olivier Robin <[email protected]> Date: Fri, 10 Jul 2026 08:58:13 -0700 Subject: [PATCH] Exclude Widget app group avatar from iCloud backup The file contain gaiaID so uploading them to iCloud can be considered as a leak. Fixed: 533123348 Change-Id: Id2767c82b69f8263c17b006bafd460264db19619 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/8074063 Commit-Queue: Federica Germinario <[email protected]> Auto-Submit: Olivier Robin <[email protected]> Reviewed-by: Gauthier Ambard <[email protected]> Reviewed-by: Federica Germinario <[email protected]> Cr-Commit-Position: refs/heads/main@{#1660314} --- diff --git a/ios/chrome/browser/signin/model/system_account_updater.mm b/ios/chrome/browser/signin/model/system_account_updater.mm index 767c9ed..b6bdcf1 100644 --- a/ios/chrome/browser/signin/model/system_account_updater.mm +++ b/ios/chrome/browser/signin/model/system_account_updater.mm @@ -4,6 +4,8 @@ #import "ios/chrome/browser/signin/model/system_account_updater.h" +#import "base/apple/backup_util.h" +#import "base/apple/foundation_util.h" #import "base/barrier_callback.h" #import "base/check_deref.h" #import "base/check_is_test.h" @@ -159,6 +161,7 @@ if (data) { NSURL* path = info.avatar_path(avatar_folder); if ([data writeToURL:path atomically:YES]) { + base::apple::SetBackupExclusion(base::apple::NSURLToFilePath(path)); [avatars addObject:path]; } } @@ -187,7 +190,9 @@ NSURL* path = info.avatar_path(avatar_folder); if (NSData* data = info.avatar_data()) { - [data writeToURL:path atomically:YES]; + if ([data writeToURL:path atomically:YES]) { + base::apple::SetBackupExclusion(base::apple::NSURLToFilePath(path)); + } } else { NSFileManager* manager = [NSFileManager defaultManager]; [manager removeItemAtURL:path error:nil]; diff --git a/ios/chrome/common/app_group/app_group_helper.mm b/ios/chrome/common/app_group/app_group_helper.mm index 5f11bb5..c52b3cc 100644 --- a/ios/chrome/common/app_group/app_group_helper.mm +++ b/ios/chrome/common/app_group/app_group_helper.mm @@ -4,7 +4,9 @@ #import "ios/chrome/common/app_group/app_group_helper.h" +#import "base/apple/backup_util.h" #import "base/apple/bundle_locations.h" +#import "base/apple/foundation_util.h" #import "base/check.h" #import "ios/chrome/common/ios_app_bundle_id_prefix_buildflags.h" @@ -70,6 +72,7 @@ error:nil]) { return nil; } + base::apple::SetBackupExclusion(base::apple::NSURLToFilePath(pictureDataURL)); return pictureDataURL; }
Original Bug Report
Potential backup leak of unhashed Gaia IDs and avatars via iOS App Group container
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: In Chrome for iOS, the widgets avatar folder is created and written to within the shared App Group container without backup exclusion attributes. As a result, the stable, unhashed Google Gaia IDs and avatar image files of all signed-in Google accounts are included in iCloud and unencrypted local backups. Anyone who obtains access to these backups can deanonymize the device owner and other linked accounts.
Affected files:
ios/chrome/common/app_group/app_group_helper.mmios/chrome/browser/signin/model/system_account_updater.mm
Estimated timestamp from git blame: 2025-02-10
Description
On iOS, files written to the shared App Group container are included in iCloud and iTunes/Finder backups by default unless they are explicitly marked with the backup exclusion attribute (NSURLIsExcludedFromBackupKey) or placed in specific non-backed-up directories (like Library/Caches or tmp).
Chrome for iOS creates a folder at {AppGroup}/Chrome/AvatarData/ to cache 32x32 PNG avatar images of signed-in accounts for widgets. However, during the creation of this folder and the subsequent file writes, the backup exclusion attribute is never set.
Furthermore, the avatar files are named using the user’s unhashed, cleartext Google Gaia ID (e.g., {GaiaID}.png), and contain their profile picture. This allows any adversary with access to device backups to deanonymize the user and identify any work, personal, or secondary Google accounts signed into the browser.
Code Analysis
1. Folder Creation without Exclusion
In ios/chrome/common/app_group/app_group_helper.mm:54-74, the directory is created but is not excluded from backups:
+ (NSURL*)widgetsAvatarFolder {
NSString* applicationGroup = [AppGroupHelper applicationGroup];
if (!applicationGroup) { return nil; }
NSURL* groupURL = [[NSFileManager defaultManager]
containerURLForSecurityApplicationGroupIdentifier:applicationGroup];
NSURL* chromeURL = [groupURL URLByAppendingPathComponent:@"Chrome" isDirectory:YES];
NSURL* pictureDataURL = [chromeURL URLByAppendingPathComponent:@"AvatarData"
isDirectory:YES];
if (![[NSFileManager defaultManager] createDirectoryAtPath:pictureDataURL.path
withIntermediateDirectories:YES
attributes:nil error:nil]) {
return nil;
}
return pictureDataURL; // <-- Missing base::apple::SetBackupExclusion()
}
2. Filename is the Cleartext Gaia ID
In ios/chrome/browser/signin/model/system_account_updater.mm:91-95, the filename is constructed directly using the cleartext Gaia ID:
NSURL* avatar_path(NSURL* directory) const {
return [directory URLByAppendingPathComponent:
[gaia_id_.ToNSString() stringByAppendingPathExtension:@"png"]];
}
3. Writing Files without Exclusion
In ios/chrome/browser/signin/model/system_account_updater.mm:147-177, the avatar image data is written atomically to disk without applying the backup exclusion key to individual files:
for (const SystemIdentityInfoData& info : list) {
NSData* data = info.avatar_data();
if (data) {
NSURL* path = info.avatar_path(avatar_folder);
if ([data writeToURL:path atomically:YES]) {
[avatars addObject:path];
}
}
}
Potential Trigger Path (Suggested Steps)
Note: The following steps are potential and suggested; our tooling does not currently have the capability to execute live code to verify this Proof of Concept.
- A user launches Chrome on iOS and signs into one or more Google accounts.
- Upon startup or identity change,
SystemAccountUpdateris initialized unconditionally, registering as an observer ofSystemIdentityManager. SystemAccountUpdater::UpdateLoadedAccounts()retrieves the active identities and schedules a background task runningWriteAvatars.WriteAvatarscreates{AppGroup}/Chrome/AvatarData/and writes{GaiaID}.pngfiles into it.- The user backs up the device via iCloud or performs an unencrypted backup via iTunes/Finder on a computer.
- An attacker gains access to the backup, extracts the App Group container contents, and locates the folder
Chrome/AvatarData/to recover the unhashed Gaia IDs and profile photos of the signed-in accounts.
Suggested Fix
Exclude the AvatarData directory from backups once it is created in +[AppGroupHelper widgetsAvatarFolder]. Import base/apple/backup_util.h and call base::apple::SetBackupExclusion on the folder URL:
#import "base/apple/backup_util.h"
#import "base/apple/foundation_util.h"
// ... inside +[AppGroupHelper widgetsAvatarFolder] ...
if (![[NSFileManager defaultManager] createDirectoryAtPath:pictureDataURL.path
withIntermediateDirectories:YES
attributes:nil error:nil]) {
return nil;
}
base::apple::SetBackupExclusion(base::apple::NSURLToFilePath(pictureDataURL));
return pictureDataURL;
Evaluated with Chrome root at commit: 84065d9121f6e48f67755f0ae963cc09617e5c85
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.