From 1284c3ae02acb17c5f7bcd32a551d37535f16079 Mon Sep 17 00:00:00 2001 From: Georgios Konstantopoulos Date: Fri, 9 Jan 2026 21:43:04 +0200 Subject: [PATCH] fix: support Brave cookies on macOS --- patches/@steipete__sweet-cookie.patch | 73 +++++++++++++++++++++++++-- 1 file changed, 68 insertions(+), 5 deletions(-) diff --git a/patches/@steipete__sweet-cookie.patch b/patches/@steipete__sweet-cookie.patch index 3e70cf3..b89afec 100644 --- a/patches/@steipete__sweet-cookie.patch +++ b/patches/@steipete__sweet-cookie.patch @@ -1,13 +1,76 @@ diff --git a/dist/providers/chromeSqliteMac.js b/dist/providers/chromeSqliteMac.js -index 71c815f77378d03e07061976ac372b3a55a61ac4..3a85a2fce102128d7e7b69145d97bc353f663008 100644 +index 71c815f77378d03e07061976ac372b3a55a61ac4..b21c15640955a8e7faa8f1d6ea6fed7ca8f04ddb 100644 --- a/dist/providers/chromeSqliteMac.js +++ b/dist/providers/chromeSqliteMac.js -@@ -15,7 +15,7 @@ export async function getCookiesFromChromeSqliteMac(options, origins, allowlistN +@@ -4,19 +4,37 @@ import { decryptChromiumAes128CbcCookieValue, deriveAes128CbcKeyFromPassword, } + import { getCookiesFromChromeSqliteDb } from './chromeSqlite/shared.js'; + import { readKeychainGenericPasswordFirst } from './chromium/macosKeychain.js'; + import { resolveCookiesDbFromProfileOrRoots } from './chromium/paths.js'; ++ ++function resolveKeychainForDb(dbPath) { ++ const lower = dbPath.toLowerCase(); ++ if (lower.includes('bravesoftware') || lower.includes('brave-browser') || lower.includes('brave browser')) { ++ return { ++ account: 'Brave', ++ services: ['Brave Safe Storage'], ++ label: 'Brave Safe Storage', ++ }; ++ } ++ return { ++ account: 'Chrome', ++ services: ['Chrome Safe Storage'], ++ label: 'Chrome Safe Storage', ++ }; ++} ++ + export async function getCookiesFromChromeSqliteMac(options, origins, allowlistNames) { + const dbPath = resolveChromeCookiesDb(options.profile); + if (!dbPath) { + return { cookies: [], warnings: ['Chrome cookies database not found.'] }; + } + const warnings = []; +- // On macOS, Chrome stores its "Safe Storage" secret in Keychain. ++ // On macOS, Chromium stores its "Safe Storage" secret in Keychain. + // `security find-generic-password` is stable and avoids any native Node keychain modules. ++ const keychain = resolveKeychainForDb(dbPath); const passwordResult = await readKeychainGenericPasswordFirst({ - account: 'Chrome', - services: ['Chrome Safe Storage'], +- account: 'Chrome', +- services: ['Chrome Safe Storage'], - timeoutMs: 3_000, +- label: 'Chrome Safe Storage', ++ account: keychain.account, ++ services: keychain.services, + timeoutMs: options.timeoutMs ?? 3_000, - label: 'Chrome Safe Storage', ++ label: keychain.label, }); if (!passwordResult.ok) { + warnings.push(passwordResult.error); +@@ -24,7 +42,7 @@ export async function getCookiesFromChromeSqliteMac(options, origins, allowlistN + } + const chromePassword = passwordResult.password.trim(); + if (!chromePassword) { +- warnings.push('macOS Keychain returned an empty Chrome Safe Storage password.'); ++ warnings.push(`macOS Keychain returned an empty ${keychain.label} password.`); + return { cookies: [], warnings }; + } + // Chromium uses PBKDF2(password, "saltysalt", 1003, 16, sha1) for AES-128-CBC cookie values on macOS. +@@ -46,15 +64,19 @@ export async function getCookiesFromChromeSqliteMac(options, origins, allowlistN + result.warnings.unshift(...warnings); + return result; + } ++ + function resolveChromeCookiesDb(profile) { + const home = homedir(); + /* c8 ignore next */ + const roots = process.platform === 'darwin' +- ? [path.join(home, 'Library', 'Application Support', 'Google', 'Chrome')] ++ ? [ ++ path.join(home, 'Library', 'Application Support', 'Google', 'Chrome'), ++ path.join(home, 'Library', 'Application Support', 'BraveSoftware', 'Brave-Browser'), ++ ] + : []; + const args = { roots }; + if (profile !== undefined) + args.profile = profile; + return resolveCookiesDbFromProfileOrRoots(args); + }