From 542be8135a36b5adb813f53cfdb968b032f2eb86 Mon Sep 17 00:00:00 2001 From: eshmeshek Date: Sat, 16 May 2026 20:54:35 +0300 Subject: [PATCH] fix: whitelist Google/OAuth domains in adblock, spoof Sec-CH-UA brand MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two-part fix for Google login "Возможно, этот браузер небезопасны" error: 1. The adblocker was eating Google integrity-check resources (gstatic, google-analytics, googletagmanager — flagged by EasyPrivacy). Add @@ whitelist filters for Google, Yandex, Microsoft, Apple, Facebook, GitHub, VK, Mail.ru ecosystems. Also switch from non-existent addFilters() to updateFromDiff({added}) — previous TMDB whitelist was silently failing in a then().catch() and never applied. Adblock cache bumped to v3 so the new filters take effect. 2. Sec-CH-UA client-hints branding was leaking Electron app name as the browser brand. Override sec-ch-ua, sec-ch-ua-mobile, sec-ch-ua-platform headers via webRequest.onBeforeSendHeaders on all 3 sessions so embedded-browser detectors see real-Chrome brand list. Co-Authored-By: Claude Opus 4.7 (1M context) --- main.js | 67 +++++++++++++++++++++++++++++++++++++++------------- package.json | 2 +- 2 files changed, 52 insertions(+), 17 deletions(-) diff --git a/main.js b/main.js index 278ec2c..f105f43 100644 --- a/main.js +++ b/main.js @@ -7,7 +7,7 @@ const { ElectronBlocker, adsAndTrackingLists } = require('@cliqz/adblocker-elect const { autoUpdater } = require('electron-updater'); const CONFIG_PATH = path.join(os.homedir(), '.ESH-Media.json'); -const BLOCKER_CACHE_PATH = path.join(os.homedir(), '.ESH-Media-adblock-v2.bin'); +const BLOCKER_CACHE_PATH = path.join(os.homedir(), '.ESH-Media-adblock-v3.bin'); const DEFAULT_TRUSTED_DOMAINS = [ // Google ecosystem (OAuth) 'google.com', 'accounts.google.com', 'googleapis.com', 'googleusercontent.com', @@ -72,8 +72,26 @@ function getBlocker() { 'https://easylist-downloads.adblockplus.org/ruadlist+easylist.txt', // RuAdList ]; const b = await ElectronBlocker.fromLists(fetchFn, [...adsAndTrackingLists, ...russianLists]); - // Whitelist TMDB so the movie search API is not blocked - b.addFilters(['@@||api.themoviedb.org^', '@@||image.tmdb.org^', '@@||themoviedb.org^']); + // Whitelist domains that need ALL requests passed through unfiltered. + // Tracking-list false positives on these break critical functionality: + // • Google: OAuth/login integrity checks fail without gstatic + analytics endpoints + // → "Возможно, этот браузер или приложение небезопасны" error + // • Yandex/Mail/Microsoft/Apple: same OAuth-style integrity flows + // • TMDB: movie search API and poster CDN + const whitelist = [ + '@@||api.themoviedb.org^', '@@||image.tmdb.org^', '@@||themoviedb.org^', + '@@||google.com^', '@@||googleapis.com^', '@@||googleusercontent.com^', + '@@||gstatic.com^', '@@||youtube.com^', '@@||ytimg.com^', '@@||googlevideo.com^', + '@@||google-analytics.com^', '@@||googletagmanager.com^', + '@@||yandex.ru^', '@@||yandex.com^', '@@||yastatic.net^', '@@||mc.yandex.ru^', + '@@||github.com^', '@@||githubassets.com^', '@@||githubusercontent.com^', + '@@||vk.com^', '@@||vk.ru^', '@@||vkuser.net^', + '@@||mail.ru^', '@@||my.mail.ru^', '@@||imgsmail.ru^', + '@@||microsoft.com^', '@@||microsoftonline.com^', '@@||live.com^', '@@||office.com^', + '@@||apple.com^', '@@||icloud.com^', + '@@||facebook.com^', '@@||fbcdn.net^', + ]; + b.updateFromDiff({ added: whitelist }); fs.writeFileSync(BLOCKER_CACHE_PATH, Buffer.from(b.serialize())); console.log('[adblock] filter lists downloaded and cached'); return b; @@ -1172,20 +1190,37 @@ app.whenReady().then(async () => { app.userAgentFallback = cleanUserAgent; session.defaultSession.setUserAgent(cleanUserAgent); - // Add Referer to image requests so hotlink protection doesn't block them - session.defaultSession.webRequest.onBeforeSendHeaders( - { urls: ['https://*/*', 'http://*/*'] }, - (details, callback) => { - const headers = details.requestHeaders; - if (details.resourceType === 'image' && !headers['Referer'] && !headers['referer']) { - try { - const u = new URL(details.url); - headers['Referer'] = `${u.protocol}//${u.hostname}/`; - } catch (_) {} + // Chrome version from the cleaned UA — used for client hints below + const chromeVerMatch = cleanUserAgent.match(/Chrome\/(\d+)/); + const chromeMajor = chromeVerMatch ? chromeVerMatch[1] : '128'; + const secChUa = `"Not_A Brand";v="8", "Chromium";v="${chromeMajor}", "Google Chrome";v="${chromeMajor}"`; + + const installRequestHooks = (sess) => { + sess.webRequest.onBeforeSendHeaders( + { urls: ['https://*/*', 'http://*/*'] }, + (details, callback) => { + const headers = details.requestHeaders; + // Spoof Sec-CH-UA so embedded-browser detectors (Google login, etc.) see + // a real-Chrome brand list. Electron normally injects the app name as + // the brand which is how Google fingerprints us as "embedded/unsafe". + headers['sec-ch-ua'] = secChUa; + headers['sec-ch-ua-mobile'] = '?0'; + headers['sec-ch-ua-platform'] = '"Windows"'; + // Add Referer to image requests so hotlink protection doesn't block them + if (details.resourceType === 'image' && !headers['Referer'] && !headers['referer']) { + try { + const u = new URL(details.url); + headers['Referer'] = `${u.protocol}//${u.hostname}/`; + } catch (_) {} + } + callback({ requestHeaders: headers }); } - callback({ requestHeaders: headers }); - } - ); + ); + }; + + installRequestHooks(session.defaultSession); + installRequestHooks(getProxySession()); + installRequestHooks(getDirectSession()); // Apply proxy from config before blocker tries to download filter lists loadTrustedDomainsFromDisk(); diff --git a/package.json b/package.json index 1400c3c..ac8ad4a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ESH-Media", - "version": "1.0.3", + "version": "1.0.4", "private": true, "main": "main.js", "scripts": {