From 129e4c6729a40d6042c664adedbb20de549ca4a0 Mon Sep 17 00:00:00 2001 From: Local Dev Date: Sat, 3 Oct 2026 21:17:38 +0200 Subject: [PATCH] Aegis: the ETH and SOL bridge went missing on most pages, for good The main-world bridge is appended at document_start, which often runs before the page has an element. The append threw on null, and the catch marked the origin as Trusted-Types-blocked in localStorage, so every later visit skipped window.ethereum, window.solana and the EIP-6963 announcement on that site. On example.com it failed on 6 of 6 loads. Wait for with a MutationObserver (it fires at the microtask checkpoint before the first parser-inserted script, so the bridge is still first), remember only real Trusted Types refusals, and use a new key so the origins wrongly marked by the old one get the bridge back. --- bundled-addons/aegis/wallet-inject.js | 33 +++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/bundled-addons/aegis/wallet-inject.js b/bundled-addons/aegis/wallet-inject.js index ce47ffdf..2e370b7c 100644 --- a/bundled-addons/aegis/wallet-inject.js +++ b/bundled-addons/aegis/wallet-inject.js @@ -560,14 +560,20 @@ const mainWorldSource = `(function () { // the big enforcing sites (no report at all), plus a per-origin memory for // any other site that rejected us once (one report, never again). const NO_BRIDGE_HOSTS = /(^|\.)(google\.[a-z.]+|googleapis\.com|gstatic\.com|youtube\.com|googleusercontent\.com|microsoftonline\.com|microsoft\.com|live\.com|office\.com|github\.com|apple\.com|icloud\.com)$/i; +// +// The memory used to be "aegis:bridge-blocked", set on ANY failure. The +// commonest failure was ours: this preload often runs before the page has an +// element, so the append threw on null and the origin lost the bridge +// for good. That key is ignored now; only a Trusted Types refusal is kept. +const BLOCKED_KEY = "aegis:bridge-blocked-tt"; function bridgeAllowedHere() { try { if (NO_BRIDGE_HOSTS.test(location.hostname)) return false; - if (localStorage.getItem("aegis:bridge-blocked") === "1") return false; + if (localStorage.getItem(BLOCKED_KEY) === "1") return false; } catch {} return true; } -if (bridgeAllowedHere()) { +function installBridge() { try { let src = mainWorldSource; // Where Trusted Types exist but are not enforced, a policy keeps the @@ -581,7 +587,26 @@ if (bridgeAllowedHere()) { (document.head || document.documentElement).appendChild(s); s.remove(); } catch (e) { - try { localStorage.setItem("aegis:bridge-blocked", "1"); } catch {} - console.warn("[aegis] main-world bridge install failed (this origin is now skipped):", e && e.message || e); + const msg = String(e && e.message || e); + if (/trusted/i.test(msg)) { + try { localStorage.setItem(BLOCKED_KEY, "1"); } catch {} + console.warn("[aegis] this site enforces Trusted Types; the wallet bridge stays off here:", msg); + } else { + console.warn("[aegis] main-world bridge install failed:", msg); + } + } +} +if (bridgeAllowedHere()) { + if (document.documentElement) installBridge(); + else { + // The parser inserts before it runs any page script, and + // observer callbacks run at the microtask checkpoint that precedes each + // parser-inserted script, so the bridge is still first. + const mo = new MutationObserver(() => { + if (!document.documentElement) return; + mo.disconnect(); + installBridge(); + }); + mo.observe(document, { childList: true }); } }