diff --git a/main.js b/main.js index 53af0e73..196e25e5 100644 --- a/main.js +++ b/main.js @@ -2804,7 +2804,10 @@ function initAddons() { // Percent-encoded QR spelling: WIZ://%3FP%3D… const qrSrc = `\\b${scheme}://(?:%[0-9A-Fa-f]{2}|[A-Za-z0-9._~$+-])+`; const arg = JSON.stringify({ plainSrc, qrSrc, limit }); - const found = await wc.executeJavaScript(`(() => { + // Run in an isolated world of our own (the inject preload uses 999): + // the page shares the DOM but not its globals, so it cannot replace + // RegExp, querySelectorAll or Set to shape what the scan returns. + const found = await wc.executeJavaScriptInIsolatedWorld(1001, [{ code: `(() => { const { plainSrc, qrSrc, limit } = ${arg}; const out = new Set(); const plain = new RegExp(plainSrc, "gi"); @@ -2828,8 +2831,12 @@ function initAddons() { for (const el of document.querySelectorAll("input,textarea")) scan(el.value); scan(document.body ? document.body.innerText : ""); return [...out].slice(0, limit); - })()`, true); - const uris = Array.isArray(found) ? found.filter((s) => typeof s === "string") : []; + })()` }], true); + // And checked again here, whatever came back. + const want = scheme.toLowerCase() + "://"; + const uris = (Array.isArray(found) ? found : []) + .filter((s) => typeof s === "string" && s.length <= 2048 && s.toLowerCase().startsWith(want)) + .slice(0, Math.max(0, Number(limit) || 0)); console.log(`[addons] ${addonId} scanned ${origin || "tab"} for ${scheme}:// — ${uris.length} match(es)`); return { origin, uris }; }, @@ -5692,7 +5699,7 @@ async function installExtensionWithConsent(id, requester) { ? `Update ${card.name || id} ${installed.version} → ${card.latest}?` : `Install ${card.name || id} ${card.latest}?`, detail: `${from}Published by ${card.publisher}. Theseus verifies the package signature against ${card.publisher}'s current owner in its own chain index before anything is written.\n\n` - + `A community extension runs with the same access as any add-on — treat it like a program from that publisher.`, + + `A community extension runs inside Theseus with the same access as Theseus itself: while your vault is unlocked it can reach your saved passwords and your Aegis wallet. Install it only if you would install a program from this publisher.`, buttons: ["Install", "Cancel"], defaultId: 1, cancelId: 1, noLink: true, }); if (response !== 0) return { ok: false, error: "cancelled" };