
brizental pushed to branch tor-browser-140.2.0esr-15.0-1 at The Tor Project / Applications / Tor Browser Commits: 40fe2123 by Beatriz Rizental at 2025-08-21T14:45:59+02:00 fixup! BB 40926: Implemented the New Identity feature - - - - - ca116af7 by Beatriz Rizental at 2025-08-21T14:45:59+02:00 fixup! TB 8324: Prevent DNS proxy bypasses caused by Drag&Drop - - - - - 61f37354 by Beatriz Rizental at 2025-08-21T14:46:00+02:00 fixup! TB 27476: Implement about:torconnect captive portal within Tor Browser - - - - - db2882b1 by Beatriz Rizental at 2025-08-21T14:46:00+02:00 fixup! TB 7494: Create local home page for TBB. - - - - - 2e686601 by Beatriz Rizental at 2025-08-21T14:46:00+02:00 fixup! TB 23247: Communicating security expectations for .onion - - - - - 3e500e35 by Beatriz Rizental at 2025-08-21T14:46:01+02:00 fixup! TB 21952: Implement Onion-Location - - - - - 1b623002 by Beatriz Rizental at 2025-08-21T14:46:01+02:00 fixup! TB 40458: Implement .tor.onion aliases - - - - - 9 changed files: - browser/base/content/pageinfo/security.js - browser/components/abouttor/content/aboutTor.js - browser/components/newidentity/content/newidentity.js - browser/components/onionservices/OnionAliasStore.sys.mjs - browser/components/onionservices/OnionLocationChild.sys.mjs - browser/components/onionservices/TorRequestWatch.sys.mjs - browser/components/rulesets/content/aboutRulesets.js - toolkit/components/torconnect/TorConnectChild.sys.mjs - toolkit/modules/DragDropFilter.sys.mjs Changes: ===================================== browser/base/content/pageinfo/security.js ===================================== @@ -57,15 +57,15 @@ var security = { (Ci.nsIWebProgressListener.STATE_LOADED_MIXED_ACTIVE_CONTENT | Ci.nsIWebProgressListener.STATE_LOADED_MIXED_DISPLAY_CONTENT); var isEV = ui.state & Ci.nsIWebProgressListener.STATE_IDENTITY_EV_TOPLEVEL; - let uriInformation = new URL(gDocInfo.documentURIObject.spec); + let uriInformation = URL.parse(gDocInfo.documentURIObject.spec); // If the Onion site could not be loaded, the view-source will be also be // about:neterror. - if (uriInformation.protocol == "view-source:") { - uriInformation = new URL(uriInformation.pathname); + if (uriInformation?.protocol == "view-source:") { + uriInformation = URL.parse(uriInformation.pathname); } const isOnion = - ["http:", "https:"].includes(uriInformation.protocol) && - uriInformation.hostname.endsWith(".onion"); + ["http:", "https:"].includes(uriInformation?.protocol) && + uriInformation?.hostname.endsWith(".onion"); let retval = { cAName: "", ===================================== browser/components/abouttor/content/aboutTor.js ===================================== @@ -298,10 +298,11 @@ const SurveyArea = { */ init() { document.getElementById("survey-launch").addEventListener("click", () => { - if (!this._localeData) { + const url = URL.parse(this._urlBase); + if (!url || !this._localeData) { return; } - const url = new URL(this._urlBase); + url.searchParams.append("lang", this._localeData.urlCode); open(url.href); }); ===================================== browser/components/newidentity/content/newidentity.js ===================================== @@ -418,22 +418,21 @@ ChromeUtils.defineLazyGetter(this, "NewIdentityButton", () => { tbl.onLocationChange = (...args) => { tbl.onLocationChange = onLocationChange; tbl.onLocationChange(...args); - let displayAddress; - try { - const url = new URL(homeURL); - displayAddress = url.hostname; - if (!displayAddress) { - // no host, use full address and truncate if too long - const MAX_LEN = 32; - displayAddress = url.href; - if (displayAddress.length > MAX_LEN) { - displayAddress = `${displayAddress.substring(0, MAX_LEN)}…`; - } - } - } catch (e) { + const url = URL.parse(homeURL); + if (!url) { // malformed URL, bail out return; } + + let displayAddress = url.hostname; + if (!displayAddress) { + // no host, use full address and truncate if too long + const MAX_LEN = 32; + displayAddress = url.href; + if (displayAddress.length > MAX_LEN) { + displayAddress = `${displayAddress.substring(0, MAX_LEN)}…`; + } + } const callback = () => { Services.prefs.setStringPref(trustedHomePref, homeURL); win.BrowserHome(); ===================================== browser/components/onionservices/OnionAliasStore.sys.mjs ===================================== @@ -175,17 +175,15 @@ class Channel { ); return; } - let toHostname; - try { - const toUrl = new URL(rule.rule[0].to); - toHostname = toUrl.hostname; - } catch (err) { + const toHostname = URL.parse(rule.rule[0].to)?.hostname; + if (!toHostname) { log.error( - "Cannot detect the hostname from the to rule", - rule.rule[0].to, - err + "Unable to parse the URL and the hostname from the to rule", + rule.rule[0].to ); + return; } + let fromRe; try { fromRe = new RegExp(rule.rule[0].from); @@ -318,6 +316,7 @@ class _OnionAliasStore { throw Error("Name cannot be empty"); } + // This will throw if the URL is invalid. new URL(chanData.pathPrefix); const scope = new RegExp(chanData.scope); const ch = new Channel( ===================================== browser/components/onionservices/OnionLocationChild.sys.mjs ===================================== @@ -25,12 +25,12 @@ export class OnionLocationChild extends JSWindowActorChild { let onionLocationURI = doc.onionLocationURI; const refreshURI = docShell.QueryInterface(Ci.nsIRefreshURI); if (onionLocationURI && refreshURI) { - const docUrl = new URL(doc.URL); - let onionUrl = new URL(onionLocationURI.asciiSpec); + const docUrl = URL.parse(doc.URL); + let onionUrl = URL.parse(onionLocationURI.asciiSpec); // Keep consistent with Location - if (!onionUrl.hash && docUrl.hash) { + if (!onionUrl?.hash && docUrl?.hash) { onionUrl.hash = docUrl.hash; - onionLocationURI = Services.io.newURI(onionUrl.toString()); + onionLocationURI = Services.io.newURI(onionUrl?.toString() || ""); } refreshURI.refreshURI( onionLocationURI, ===================================== browser/components/onionservices/TorRequestWatch.sys.mjs ===================================== @@ -79,7 +79,14 @@ class RequestObserver { } isCrossOrigin(url1, url2) { - return new URL(url1).origin !== new URL(url2).origin; + const origin1 = URL.parse(url1)?.origin; + const origin2 = URL.parse(url2)?.origin; + + if (!origin1 || !origin2) { + return true; + } + + return origin1 !== origin2; } shouldBlindCrossOrigin(uri) { try { ===================================== browser/components/rulesets/content/aboutRulesets.js ===================================== @@ -210,8 +210,8 @@ class EditState { const pathPrefix = elements.pathPrefixInput.value.trim(); try { - const url = new URL(pathPrefix); - if (url.protocol !== "http:" && url.protocol !== "https:") { + const url = URL.parse(pathPrefix); + if (url?.protocol !== "http:" && url?.protocol !== "https:") { elements.pathPrefixInput.setCustomValidity( await document.l10n.formatValue("rulesets-details-path-input-invalid") ); ===================================== toolkit/components/torconnect/TorConnectChild.sys.mjs ===================================== @@ -30,20 +30,21 @@ export class TorConnectChild extends RemotePageChild { this.#redirected = true; const redirect = new URLSearchParams( - new URL(this.contentWindow.document.location.href).search + URL.parse(this.contentWindow.document.location.href)?.search ).get("redirect"); // Fallback in error cases: let replaceURI = "about:tor"; - try { - const url = new URL( - redirect - ? decodeURIComponent(redirect) - : // NOTE: We expect no redirect when address is entered manually, or - // about:torconnect is opened from preferences or urlbar. - // Go to the home page. - await this.sendQuery("torconnect:home-page") - ); + const url = URL.parse( + redirect + ? decodeURIComponent(redirect) + : // NOTE: We expect no redirect when address is entered manually, or + // about:torconnect is opened from preferences or urlbar. + // Go to the home page. + await this.sendQuery("torconnect:home-page") + ); + + if (url) { // Do not allow javascript URI. See tor-browser#41766 if ( ["about:", "file:", "https:", "http:"].includes(url.protocol) || @@ -55,8 +56,8 @@ export class TorConnectChild extends RemotePageChild { } else { console.error(`Scheme is not allowed "${redirect}"`); } - } catch (e) { - console.error(`Invalid redirect URL "${redirect}"`, e); + } else { + console.error(`Invalid redirect URL "${redirect}"`); } // Replace the destination to prevent "about:torconnect" entering the ===================================== toolkit/modules/DragDropFilter.sys.mjs ===================================== @@ -97,11 +97,7 @@ export const DragDropFilter = { const links = aDataTransfer.mozGetDataAt(urlType, i); // Skip DNS-safe URLs (no hostname, e.g. RFC 3966 tel:) const mayLeakDNS = links.split("\n").some(link => { - try { - return new URL(link).hostname; - } catch (e) { - return false; - } + return URL.parse(link)?.hostname ?? false; }); if (!mayLeakDNS) { continue; View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/compare/c29f471... -- View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/compare/c29f471... You're receiving this email because of your account on gitlab.torproject.org.