Theseus: page scans run in an isolated world; install sheet names the risk
The wiz:// page scan ran in the page's own world, where the page can replace RegExp, querySelectorAll or Set and shape what the wallet is handed; it now runs in an isolated world of its own and the results are checked again in main. The extension install sheet now says what a community extension can reach while the vault is unlocked (passwords and the wallet), since extensions still run in the main process.
This commit is contained in:
parent
f834fbf80a
commit
76d342797b
1 changed files with 11 additions and 4 deletions
15
main.js
15
main.js
|
|
@ -2804,7 +2804,10 @@ function initAddons() {
|
||||||
// Percent-encoded QR spelling: WIZ://%3FP%3D…
|
// Percent-encoded QR spelling: WIZ://%3FP%3D…
|
||||||
const qrSrc = `\\b${scheme}://(?:%[0-9A-Fa-f]{2}|[A-Za-z0-9._~$+-])+`;
|
const qrSrc = `\\b${scheme}://(?:%[0-9A-Fa-f]{2}|[A-Za-z0-9._~$+-])+`;
|
||||||
const arg = JSON.stringify({ plainSrc, qrSrc, limit });
|
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 { plainSrc, qrSrc, limit } = ${arg};
|
||||||
const out = new Set();
|
const out = new Set();
|
||||||
const plain = new RegExp(plainSrc, "gi");
|
const plain = new RegExp(plainSrc, "gi");
|
||||||
|
|
@ -2828,8 +2831,12 @@ function initAddons() {
|
||||||
for (const el of document.querySelectorAll("input,textarea")) scan(el.value);
|
for (const el of document.querySelectorAll("input,textarea")) scan(el.value);
|
||||||
scan(document.body ? document.body.innerText : "");
|
scan(document.body ? document.body.innerText : "");
|
||||||
return [...out].slice(0, limit);
|
return [...out].slice(0, limit);
|
||||||
})()`, true);
|
})()` }], true);
|
||||||
const uris = Array.isArray(found) ? found.filter((s) => typeof s === "string") : [];
|
// 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)`);
|
console.log(`[addons] ${addonId} scanned ${origin || "tab"} for ${scheme}:// — ${uris.length} match(es)`);
|
||||||
return { origin, uris };
|
return { origin, uris };
|
||||||
},
|
},
|
||||||
|
|
@ -5692,7 +5699,7 @@ async function installExtensionWithConsent(id, requester) {
|
||||||
? `Update ${card.name || id} ${installed.version} → ${card.latest}?`
|
? `Update ${card.name || id} ${installed.version} → ${card.latest}?`
|
||||||
: `Install ${card.name || id} ${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`
|
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,
|
buttons: ["Install", "Cancel"], defaultId: 1, cancelId: 1, noLink: true,
|
||||||
});
|
});
|
||||||
if (response !== 0) return { ok: false, error: "cancelled" };
|
if (response !== 0) return { ok: false, error: "cancelled" };
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue