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
-
ca116af7
by Beatriz Rizental at 2025-08-21T14:45:59+02:00
-
61f37354
by Beatriz Rizental at 2025-08-21T14:46:00+02:00
-
db2882b1
by Beatriz Rizental at 2025-08-21T14:46:00+02:00
-
2e686601
by Beatriz Rizental at 2025-08-21T14:46:00+02:00
-
3e500e35
by Beatriz Rizental at 2025-08-21T14:46:01+02:00
-
1b623002
by Beatriz Rizental at 2025-08-21T14:46:01+02:00
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:
| ... | ... | @@ -57,15 +57,15 @@ var security = { |
| 57 | 57 | (Ci.nsIWebProgressListener.STATE_LOADED_MIXED_ACTIVE_CONTENT |
|
| 58 | 58 | Ci.nsIWebProgressListener.STATE_LOADED_MIXED_DISPLAY_CONTENT);
|
| 59 | 59 | var isEV = ui.state & Ci.nsIWebProgressListener.STATE_IDENTITY_EV_TOPLEVEL;
|
| 60 | - let uriInformation = new URL(gDocInfo.documentURIObject.spec);
|
|
| 60 | + let uriInformation = URL.parse(gDocInfo.documentURIObject.spec);
|
|
| 61 | 61 | // If the Onion site could not be loaded, the view-source will be also be
|
| 62 | 62 | // about:neterror.
|
| 63 | - if (uriInformation.protocol == "view-source:") {
|
|
| 64 | - uriInformation = new URL(uriInformation.pathname);
|
|
| 63 | + if (uriInformation?.protocol == "view-source:") {
|
|
| 64 | + uriInformation = URL.parse(uriInformation.pathname);
|
|
| 65 | 65 | }
|
| 66 | 66 | const isOnion =
|
| 67 | - ["http:", "https:"].includes(uriInformation.protocol) &&
|
|
| 68 | - uriInformation.hostname.endsWith(".onion");
|
|
| 67 | + ["http:", "https:"].includes(uriInformation?.protocol) &&
|
|
| 68 | + uriInformation?.hostname.endsWith(".onion");
|
|
| 69 | 69 | |
| 70 | 70 | let retval = {
|
| 71 | 71 | cAName: "",
|
| ... | ... | @@ -298,10 +298,11 @@ const SurveyArea = { |
| 298 | 298 | */
|
| 299 | 299 | init() {
|
| 300 | 300 | document.getElementById("survey-launch").addEventListener("click", () => {
|
| 301 | - if (!this._localeData) {
|
|
| 301 | + const url = URL.parse(this._urlBase);
|
|
| 302 | + if (!url || !this._localeData) {
|
|
| 302 | 303 | return;
|
| 303 | 304 | }
|
| 304 | - const url = new URL(this._urlBase);
|
|
| 305 | + |
|
| 305 | 306 | url.searchParams.append("lang", this._localeData.urlCode);
|
| 306 | 307 | open(url.href);
|
| 307 | 308 | });
|
| ... | ... | @@ -418,22 +418,21 @@ ChromeUtils.defineLazyGetter(this, "NewIdentityButton", () => { |
| 418 | 418 | tbl.onLocationChange = (...args) => {
|
| 419 | 419 | tbl.onLocationChange = onLocationChange;
|
| 420 | 420 | tbl.onLocationChange(...args);
|
| 421 | - let displayAddress;
|
|
| 422 | - try {
|
|
| 423 | - const url = new URL(homeURL);
|
|
| 424 | - displayAddress = url.hostname;
|
|
| 425 | - if (!displayAddress) {
|
|
| 426 | - // no host, use full address and truncate if too long
|
|
| 427 | - const MAX_LEN = 32;
|
|
| 428 | - displayAddress = url.href;
|
|
| 429 | - if (displayAddress.length > MAX_LEN) {
|
|
| 430 | - displayAddress = `${displayAddress.substring(0, MAX_LEN)}…`;
|
|
| 431 | - }
|
|
| 432 | - }
|
|
| 433 | - } catch (e) {
|
|
| 421 | + const url = URL.parse(homeURL);
|
|
| 422 | + if (!url) {
|
|
| 434 | 423 | // malformed URL, bail out
|
| 435 | 424 | return;
|
| 436 | 425 | }
|
| 426 | + |
|
| 427 | + let displayAddress = url.hostname;
|
|
| 428 | + if (!displayAddress) {
|
|
| 429 | + // no host, use full address and truncate if too long
|
|
| 430 | + const MAX_LEN = 32;
|
|
| 431 | + displayAddress = url.href;
|
|
| 432 | + if (displayAddress.length > MAX_LEN) {
|
|
| 433 | + displayAddress = `${displayAddress.substring(0, MAX_LEN)}…`;
|
|
| 434 | + }
|
|
| 435 | + }
|
|
| 437 | 436 | const callback = () => {
|
| 438 | 437 | Services.prefs.setStringPref(trustedHomePref, homeURL);
|
| 439 | 438 | win.BrowserHome();
|
| ... | ... | @@ -175,17 +175,15 @@ class Channel { |
| 175 | 175 | );
|
| 176 | 176 | return;
|
| 177 | 177 | }
|
| 178 | - let toHostname;
|
|
| 179 | - try {
|
|
| 180 | - const toUrl = new URL(rule.rule[0].to);
|
|
| 181 | - toHostname = toUrl.hostname;
|
|
| 182 | - } catch (err) {
|
|
| 178 | + const toHostname = URL.parse(rule.rule[0].to)?.hostname;
|
|
| 179 | + if (!toHostname) {
|
|
| 183 | 180 | log.error(
|
| 184 | - "Cannot detect the hostname from the to rule",
|
|
| 185 | - rule.rule[0].to,
|
|
| 186 | - err
|
|
| 181 | + "Unable to parse the URL and the hostname from the to rule",
|
|
| 182 | + rule.rule[0].to
|
|
| 187 | 183 | );
|
| 184 | + return;
|
|
| 188 | 185 | }
|
| 186 | + |
|
| 189 | 187 | let fromRe;
|
| 190 | 188 | try {
|
| 191 | 189 | fromRe = new RegExp(rule.rule[0].from);
|
| ... | ... | @@ -318,6 +316,7 @@ class _OnionAliasStore { |
| 318 | 316 | throw Error("Name cannot be empty");
|
| 319 | 317 | }
|
| 320 | 318 | |
| 319 | + // This will throw if the URL is invalid.
|
|
| 321 | 320 | new URL(chanData.pathPrefix);
|
| 322 | 321 | const scope = new RegExp(chanData.scope);
|
| 323 | 322 | const ch = new Channel(
|
| ... | ... | @@ -25,12 +25,12 @@ export class OnionLocationChild extends JSWindowActorChild { |
| 25 | 25 | let onionLocationURI = doc.onionLocationURI;
|
| 26 | 26 | const refreshURI = docShell.QueryInterface(Ci.nsIRefreshURI);
|
| 27 | 27 | if (onionLocationURI && refreshURI) {
|
| 28 | - const docUrl = new URL(doc.URL);
|
|
| 29 | - let onionUrl = new URL(onionLocationURI.asciiSpec);
|
|
| 28 | + const docUrl = URL.parse(doc.URL);
|
|
| 29 | + let onionUrl = URL.parse(onionLocationURI.asciiSpec);
|
|
| 30 | 30 | // Keep consistent with Location
|
| 31 | - if (!onionUrl.hash && docUrl.hash) {
|
|
| 31 | + if (!onionUrl?.hash && docUrl?.hash) {
|
|
| 32 | 32 | onionUrl.hash = docUrl.hash;
|
| 33 | - onionLocationURI = Services.io.newURI(onionUrl.toString());
|
|
| 33 | + onionLocationURI = Services.io.newURI(onionUrl?.toString() || "");
|
|
| 34 | 34 | }
|
| 35 | 35 | refreshURI.refreshURI(
|
| 36 | 36 | onionLocationURI,
|
| ... | ... | @@ -79,7 +79,14 @@ class RequestObserver { |
| 79 | 79 | }
|
| 80 | 80 | |
| 81 | 81 | isCrossOrigin(url1, url2) {
|
| 82 | - return new URL(url1).origin !== new URL(url2).origin;
|
|
| 82 | + const origin1 = URL.parse(url1)?.origin;
|
|
| 83 | + const origin2 = URL.parse(url2)?.origin;
|
|
| 84 | + |
|
| 85 | + if (!origin1 || !origin2) {
|
|
| 86 | + return true;
|
|
| 87 | + }
|
|
| 88 | + |
|
| 89 | + return origin1 !== origin2;
|
|
| 83 | 90 | }
|
| 84 | 91 | shouldBlindCrossOrigin(uri) {
|
| 85 | 92 | try {
|
| ... | ... | @@ -210,8 +210,8 @@ class EditState { |
| 210 | 210 | |
| 211 | 211 | const pathPrefix = elements.pathPrefixInput.value.trim();
|
| 212 | 212 | try {
|
| 213 | - const url = new URL(pathPrefix);
|
|
| 214 | - if (url.protocol !== "http:" && url.protocol !== "https:") {
|
|
| 213 | + const url = URL.parse(pathPrefix);
|
|
| 214 | + if (url?.protocol !== "http:" && url?.protocol !== "https:") {
|
|
| 215 | 215 | elements.pathPrefixInput.setCustomValidity(
|
| 216 | 216 | await document.l10n.formatValue("rulesets-details-path-input-invalid")
|
| 217 | 217 | );
|
| ... | ... | @@ -30,20 +30,21 @@ export class TorConnectChild extends RemotePageChild { |
| 30 | 30 | this.#redirected = true;
|
| 31 | 31 | |
| 32 | 32 | const redirect = new URLSearchParams(
|
| 33 | - new URL(this.contentWindow.document.location.href).search
|
|
| 33 | + URL.parse(this.contentWindow.document.location.href)?.search
|
|
| 34 | 34 | ).get("redirect");
|
| 35 | 35 | |
| 36 | 36 | // Fallback in error cases:
|
| 37 | 37 | let replaceURI = "about:tor";
|
| 38 | - try {
|
|
| 39 | - const url = new URL(
|
|
| 40 | - redirect
|
|
| 41 | - ? decodeURIComponent(redirect)
|
|
| 42 | - : // NOTE: We expect no redirect when address is entered manually, or
|
|
| 43 | - // about:torconnect is opened from preferences or urlbar.
|
|
| 44 | - // Go to the home page.
|
|
| 45 | - await this.sendQuery("torconnect:home-page")
|
|
| 46 | - );
|
|
| 38 | + const url = URL.parse(
|
|
| 39 | + redirect
|
|
| 40 | + ? decodeURIComponent(redirect)
|
|
| 41 | + : // NOTE: We expect no redirect when address is entered manually, or
|
|
| 42 | + // about:torconnect is opened from preferences or urlbar.
|
|
| 43 | + // Go to the home page.
|
|
| 44 | + await this.sendQuery("torconnect:home-page")
|
|
| 45 | + );
|
|
| 46 | + |
|
| 47 | + if (url) {
|
|
| 47 | 48 | // Do not allow javascript URI. See tor-browser#41766
|
| 48 | 49 | if (
|
| 49 | 50 | ["about:", "file:", "https:", "http:"].includes(url.protocol) ||
|
| ... | ... | @@ -55,8 +56,8 @@ export class TorConnectChild extends RemotePageChild { |
| 55 | 56 | } else {
|
| 56 | 57 | console.error(`Scheme is not allowed "${redirect}"`);
|
| 57 | 58 | }
|
| 58 | - } catch (e) {
|
|
| 59 | - console.error(`Invalid redirect URL "${redirect}"`, e);
|
|
| 59 | + } else {
|
|
| 60 | + console.error(`Invalid redirect URL "${redirect}"`);
|
|
| 60 | 61 | }
|
| 61 | 62 | |
| 62 | 63 | // Replace the destination to prevent "about:torconnect" entering the
|
| ... | ... | @@ -97,11 +97,7 @@ export const DragDropFilter = { |
| 97 | 97 | const links = aDataTransfer.mozGetDataAt(urlType, i);
|
| 98 | 98 | // Skip DNS-safe URLs (no hostname, e.g. RFC 3966 tel:)
|
| 99 | 99 | const mayLeakDNS = links.split("\n").some(link => {
|
| 100 | - try {
|
|
| 101 | - return new URL(link).hostname;
|
|
| 102 | - } catch (e) {
|
|
| 103 | - return false;
|
|
| 104 | - }
|
|
| 100 | + return URL.parse(link)?.hostname ?? false;
|
|
| 105 | 101 | });
|
| 106 | 102 | if (!mayLeakDNS) {
|
| 107 | 103 | continue;
|