fix(1.0.7): disable Trusted Types engine-wide via Blink feature flag

The 1.0.6 fix (strip require-trusted-types-for from CSP via
onHeadersReceived) didn't take effect: cliqz/adblocker calls
session.webRequest.onHeadersReceived during enableBlockingInSession,
overwriting our hook (Electron permits only one listener per session).

Replace with engine-level kill switch:
  app.commandLine.appendSwitch('disable-blink-features', 'TrustedDOMTypes')

Makes the entire Trusted Types runtime feature inert, so
require-trusted-types-for CSP becomes a no-op site-wide. Safe in this
kiosk/single-user context; only relaxes one security boundary that
sites use to harden against XSS via adblocker-style script injection —
which is exactly what we need to neutralize for cliqz's anti-anti-adblock
scriptlets on YouTube.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-16 22:14:19 +03:00
parent c9c9e1171b
commit e80704c534
2 changed files with 14 additions and 34 deletions

46
main.js
View File

@@ -6,6 +6,16 @@ const cheerio = require('cheerio');
const { ElectronBlocker, adsAndTrackingLists } = require('@cliqz/adblocker-electron');
const { autoUpdater } = require('electron-updater');
// Disable Trusted Types CSP enforcement engine-wide.
// YouTube sends `Content-Security-Policy: require-trusted-types-for 'script'`,
// which blocks the cliqz adblocker's scriptlet injection (it uses plain
// `script.text = ...`) → 52+ console errors and broken anti-adblock neutralizers.
// Stripping the CSP header via webRequest doesn't work — the adblocker's own
// onHeadersReceived hook overwrites ours (Electron allows only one listener
// per session). Disabling the Blink feature is the cleanest fix; safe in a
// kiosk single-user context.
app.commandLine.appendSwitch('disable-blink-features', 'TrustedDOMTypes');
const CONFIG_PATH = path.join(os.homedir(), '.ESH-Media.json');
const BLOCKER_CACHE_PATH = path.join(os.homedir(), '.ESH-Media-adblock-v3.bin');
const DEFAULT_TRUSTED_DOMAINS = [
@@ -1228,39 +1238,9 @@ app.whenReady().then(async () => {
}
);
// Strip Trusted Types directives from CSP for sites that enforce them
// (YouTube, Gmail, etc.). The cliqz adblocker injects inline scriptlets to
// neutralize anti-adblock tricks; those injections use plain script.text
// assignment which TT blocks → "An HTMLScriptElement was directly modified
// and will not be executed" (52+ console errors on YouTube). Without TT
// the adblocker's scripts run and YouTube works normally.
const TT_STRIP_HOSTS = [
'youtube.com', 'youtu.be', 'youtubekids.com',
'google.com', 'gmail.com', 'mail.google.com',
];
const stripTrustedTypes = (sess) => {
sess.webRequest.onHeadersReceived(
{ urls: ['https://*/*'] },
(details, callback) => {
let host = '';
try { host = new URL(details.url).hostname; } catch {}
const match = TT_STRIP_HOSTS.some(d => host === d || host.endsWith('.' + d));
const headers = details.responseHeaders;
if (!match || !headers) return callback({});
for (const k of Object.keys(headers)) {
if (/^content-security-policy(-report-only)?$/i.test(k)) {
headers[k] = headers[k].map(v => v
.replace(/require-trusted-types-for[^;]*;?\s*/gi, '')
.replace(/trusted-types[^;]*;?\s*/gi, ''));
}
}
callback({ responseHeaders: headers });
}
);
};
stripTrustedTypes(session.defaultSession);
stripTrustedTypes(getProxySession());
stripTrustedTypes(getDirectSession());
// (Trusted Types now handled engine-wide via --disable-blink-features
// command-line switch at file top. webRequest.onHeadersReceived strip
// was tried in 1.0.6 but the cliqz adblocker overwrites the listener.)
// Apply proxy from config before blocker tries to download filter lists
loadTrustedDomainsFromDisk();

View File

@@ -1,6 +1,6 @@
{
"name": "ESH-Media",
"version": "1.0.6",
"version": "1.0.7",
"private": true,
"main": "main.js",
"scripts": {