An infomation overwrite vulnerability exists in the AddGenericPassword functionality of Chrome 148.0.7778.216 (Mac arm64). A keychain write from a same-user process can overwrite Chrome’s encryption key, leading to disclosure of sensitive information. An attacker can make a specially crafted keychain API call to trigger this vulnerability.
The versions below were either tested or verified to be vulnerable by Talos or confirmed to be vulnerable by the vendor.
Chrome (version(s): 148.0.7778.216 (Mac arm64))
Chrome - https://www.google.com/chrome/
5.3 - CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:L/I:L/A:L
CWE-285 - Improper Authorization
Google Chrome is a cross-platform web browser, developed by Google.
Google Chrome on macOS stores 16 random bytes, base64-encoded (24 characters), in the user’s file-based keychain (login.keychain-db) under the service name Chrome Safe Storage and account name Chrome. This value is fed into PBKDF2-HMAC-SHA1 (salt saltysalt, 1003 iterations) to derive a 128-bit AES-CBC key. Chrome uses this key to encrypt and decrypt sensitive data stored across several SQLite databases in the user profile (~/Library/Application Support/Google/Chrome/Default/):
Login Data, Login Data For Account)Cookies, Safe Browsing Cookies)Web Data, Account Web Data)Web Data, Account Web Data)The code responsible for creating the keychain entry is in crypto/apple/keychain_v2.mm, which implements AddGenericPassword:
OSStatus KeychainV2::AddGenericPassword(std::string_view service_name,
std::string_view account_name,
base::span<const uint8_t> password) {
[1] base::apple::ScopedCFTypeRef<CFDictionaryRef> query =
MakeGenericPasswordQuery(service_name, account_name);
// Check that there is not already a password.
OSStatus status = ItemCopyMatching(query.get(), /*result=*/nullptr);
if (status == errSecItemNotFound) {
// A new entry must be created.
[2] base::apple::ScopedCFTypeRef<CFDictionaryRef> keychain_data =
MakeKeychainData(service_name, account_name, password,
kKeychainActionCreate);
[3] status = ItemAdd(keychain_data.get(), /*result=*/nullptr);
} else if (status == noErr) {
// The entry already exists; only the value is updated.
keychain_data = MakeKeychainData(service_name, account_name, password,
kKeychainActionUpdate);
status = ItemUpdate(query.get(), keychain_data.get());
}
return status;
}
At [1] a dictionary is created to query the keychain and check whether the entry already exists. If it does not exist, the code at [2] is executed, and a dictionary like this is created:
kSecValueData = <24 bytes: base64-encoded random password>
kSecClass = kSecClassGenericPassword
kSecAttrAccessible = kSecAttrAccessibleWhenUnlocked
kSecAttrService = "Chrome Safe Storage"
kSecAttrAccount = "Chrome"
Then, at [3] this dictionary is passed to ItemAdd (a thin wrapper around SecItemAdd, the macOS Keychain Services API), effectively creating a keychain entry with the following ACLs:
access: 5 entries
entry 0:
authorizations (1): encrypt
don't-require-password
description: Chrome Safe Storage
applications: <null>
entry 1:
authorizations (6): decrypt derive export_clear export_wrapped mac sign
don't-require-password
description: Chrome Safe Storage
applications (1):
0: /Applications/Google Chrome.app (OK)
requirement: (identifier "com.google.Chrome" or identifier "com.google.Chrome.beta" or identifier "com.google.Chrome.dev" or identifier "com.google.Chrome.canary") and anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] /* exists */ and certificate leaf[field.1.2.840.113635.100.6.1.13] /* exists */ and certificate leaf[subject.OU] = EQHXZ8M8AV
entry 2:
authorizations (1): integrity
don't-require-password
description: 1c607402c145612717ee9f25e45093d87e315499030f9d5cc51d623696483adb
applications: <null>
entry 3:
authorizations (1): partition_id
don't-require-password
description: teamid:EQHXZ8M8AV
applications: <null>
entry 4:
authorizations (1): change_acl
don't-require-password
description: Chrome Safe Storage
applications (0):
These ACLs essentially tell the following (simplified):
change_acl): no application can change this ACLdecrypt derive export_clear export_wrapped mac sign): the only parties authorized to read or use the value of this entry are Chrome and its release variants, enforced through code signature verificationencrypt): any application can overwrite this entry’s value (applications: <null> means unrestricted, as opposed to applications (0): which means no application is allowed)Chrome does not specify any access control attributes in the dictionary passed to SecItemAdd (note the absence of kSecAttrAccess or kSecAttrAccessControl in the dictionary at [2]). The ACLs shown above are entirely populated by macOS defaults: the system automatically restricts decrypt to the calling application’s code signature and leaves encrypt open to any process. Note that the update path (kKeychainActionUpdate) sets only kSecValueData; the ACL is therefore fixed at creation time and is never re-applied or tightened on update.
This means that an attacker running a process with the same privileges as the user can silently overwrite the Chrome Safe Storage entry. On the next launch, Chrome reads the attacker-controlled value from the keychain, derives a new AES key via PBKDF2-HMAC-SHA1, and uses it for all subsequent encryption. Data previously encrypted with the original key becomes unreadable to Chrome, and all new sensitive data (passwords, cookies, tokens) is encrypted with the attacker-known key. The attacker can then decrypt these databases offline using the same PBKDF2-HMAC-SHA1 derivation.
Note that this vulnerability requires the user keychain to be unlocked. If it is locked, macOS shows the standard password prompt and the user must authenticate. However, in typical conditions, login.keychain-db is already unlocked while the user is logged into the macOS GUI session. This means a malicious app can usually perform the overwrite without additional prompts.
Vendor Link: https://chromium.googlesource.com/chromium/src/+/HEAD/docs/security/faq.md#if-there_s-a-way-to-see-stored-passwords-without-entering-a-password_is-this-a-security-bug
Vendor Notes: Google does not considered this a security vulnerability; see https://chromium.googlesource.com/chromium/src/+/HEAD/docs/security/faq.md#if-there_s-a-way-to-see-stored-passwords-without-entering-a-password_is-this-a-security-bug and similar faq entries.
2026-06-15 - Initial Vendor Contact 2026-06-15 - Vendor Disclosure 2026-06-16 - Public Release
This vulnerability has not been disclosed and cannot be viewed at this time.