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:
Changes:
browser/base/content/pageinfo/security.js
| ... |
... |
@@ -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: "",
|
browser/components/abouttor/content/aboutTor.js
| ... |
... |
@@ -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
|
});
|
browser/components/newidentity/content/newidentity.js
| ... |
... |
@@ -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();
|
browser/components/onionservices/OnionAliasStore.sys.mjs
| ... |
... |
@@ -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(
|
browser/components/onionservices/OnionLocationChild.sys.mjs
| ... |
... |
@@ -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,
|
browser/components/onionservices/TorRequestWatch.sys.mjs
| ... |
... |
@@ -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 {
|
browser/components/rulesets/content/aboutRulesets.js
| ... |
... |
@@ -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
|
);
|
toolkit/components/torconnect/TorConnectChild.sys.mjs
| ... |
... |
@@ -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
|
toolkit/modules/DragDropFilter.sys.mjs
| ... |
... |
@@ -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;
|
|