diff --git a/main.js b/main.js index 613448d..16418cb 100644 --- a/main.js +++ b/main.js @@ -381,6 +381,24 @@ function applyPermissions() { return true; }); } +// Cookie shim for cross-site embeds. Sites like the faucet hub's captcha-gated testnet +// faucets set session cookies with no SameSite attribute; Chromium defaults those to +// Lax and withholds them inside cross-site iframes, so cookie-bound captcha endpoints +// fail (tbch.googol.cash /captcha 500s without its session cookie). Rewriting their +// Set-Cookie to SameSite=None; Secure makes the cookie frame-eligible. Allowlist only — +// SameSite is CSRF protection, never relax it globally. NOTE: Electron keeps a single +// onHeadersReceived listener per session; if another is ever added, merge them. +const EMBED_COOKIE_SITES = ["https://tbch.googol.cash/*", "https://signetfaucet.com/*"]; +function applyEmbedCookieShim() { + session.defaultSession.webRequest.onHeadersReceived({ urls: EMBED_COOKIE_SITES }, (details, callback) => { + const headers = details.responseHeaders || {}; + for (const key of Object.keys(headers)) { + if (key.toLowerCase() !== "set-cookie") continue; + headers[key] = headers[key].map((c) => (/;\s*samesite=/i.test(c) ? c : c + "; SameSite=None; Secure")); + } + callback({ responseHeaders: headers }); + }); +} protocol.registerSchemesAsPrivileged([ { scheme: "bns", privileges: { standard: true, secure: true, supportFetchAPI: true, stream: true } }, @@ -1208,6 +1226,7 @@ if (!process.env.THESEUS_NO_AUTOSTART) { loadBookmarks(); loadCollisions(); applyPermissions(); + applyEmbedCookieShim(); applyAcceptLanguage(); protocol.handle("bns", serveBns); installDownloadTracker();