Skip to content
This repository was archived by the owner on Jul 9, 2025. It is now read-only.

Commit 04a47c0

Browse files
committed
Bug 1275612 - Don't allow any origins to send objects over WebChannel. r=Gijs
The last actual Firefox user of this less-safe feature was removed in 2022. Thunderbird's sync server still needs it, but apparently that is a prototype that isn't really working, so they said it was okay to remove this. Differential Revision: https://phabricator.services.mozilla.com/D220646
1 parent c6217b8 commit 04a47c0

File tree

6 files changed

+8
-124
lines changed

6 files changed

+8
-124
lines changed

browser/app/profile/firefox.js

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2528,10 +2528,6 @@ pref("signon.showAutoCompleteFooter", true);
25282528
pref("signon.showAutoCompleteImport", "import");
25292529
pref("signon.suggestImportCount", 3);
25302530

2531-
// Space separated list of URLS that are allowed to send objects (instead of
2532-
// only strings) through webchannels. Bug 1275612 tracks removing this pref and capability.
2533-
pref("webchannel.allowObject.urlWhitelist", "https://content.cdn.mozilla.net https://install.mozilla.org");
2534-
25352531
// Whether or not the browser should scan for unsubmitted
25362532
// crash reports, and then show a notification for submitting
25372533
// those reports.

browser/base/content/test/general/browser_remoteTroubleshoot.js

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,6 @@ const TEST_URL_TAIL =
1313
"example.com/browser/browser/base/content/test/general/test_remoteTroubleshoot.html";
1414
const TEST_URI_GOOD = Services.io.newURI("https://" + TEST_URL_TAIL);
1515
const TEST_URI_BAD = Services.io.newURI("http://" + TEST_URL_TAIL);
16-
const TEST_URI_GOOD_OBJECT = Services.io.newURI(
17-
"https://" + TEST_URL_TAIL + "?object"
18-
);
1916

2017
// Creates a one-shot web-channel for the test data to be sent back from the test page.
2118
function promiseChannelResponse(channelID, originOrPermission) {
@@ -116,15 +113,4 @@ add_task(async function () {
116113
got.message.errno === 2,
117114
"should have failed with errno 2, no such channel"
118115
);
119-
120-
// Check that the page can send an object as well if it's in the whitelist
121-
let webchannelWhitelistPref = "webchannel.allowObject.urlWhitelist";
122-
let origWhitelist = Services.prefs.getCharPref(webchannelWhitelistPref);
123-
let newWhitelist = origWhitelist + " https://example.com";
124-
Services.prefs.setCharPref(webchannelWhitelistPref, newWhitelist);
125-
registerCleanupFunction(() => {
126-
Services.prefs.clearUserPref(webchannelWhitelistPref);
127-
});
128-
got = await promiseNewChannelResponse(TEST_URI_GOOD_OBJECT);
129-
Assert.ok(got.message, "should have gotten some data back");
130116
});

browser/base/content/test/general/test_remoteTroubleshoot.html

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,12 @@
11
<!DOCTYPE HTML>
22
<html>
33
<script>
4-
// This test is run multiple times, once with only strings allowed through the
5-
// WebChannel, and once with objects allowed. This function allows us to handle
6-
// both cases without too much pain.
7-
function makeDetails(object) {
8-
if (window.location.search.includes("object")) {
9-
return object;
10-
}
11-
return JSON.stringify(object);
12-
}
134
// Add a listener for responses to our remote requests.
145
window.addEventListener("WebChannelMessageToContent", function(event) {
156
if (event.detail.id == "remote-troubleshooting") {
167
// Send what we got back to the test.
178
var backEvent = new window.CustomEvent("WebChannelMessageToChrome", {
18-
detail: makeDetails({
9+
detail: JSON.stringify({
1910
id: "test-remote-troubleshooting-backchannel",
2011
message: {
2112
message: event.detail.message,
@@ -32,7 +23,7 @@
3223
// Make a request for the troubleshooting data as we load.
3324
window.onload = function() {
3425
var event = new window.CustomEvent("WebChannelMessageToChrome", {
35-
detail: makeDetails({
26+
detail: JSON.stringify({
3627
id: "remote-troubleshooting",
3728
message: {
3829
command: "request",

toolkit/actors/WebChannelChild.sys.mjs

Lines changed: 2 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -3,27 +3,8 @@
33
* License, v. 2.0. If a copy of the MPL was not distributed with this
44
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
55

6-
import { XPCOMUtils } from "resource://gre/modules/XPCOMUtils.sys.mjs";
7-
86
import { ContentDOMReference } from "resource://gre/modules/ContentDOMReference.sys.mjs";
97

10-
// Preference containing the list (space separated) of origins that are
11-
// allowed to send non-string values through a WebChannel, mainly for
12-
// backwards compatability. See bug 1238128 for more information.
13-
const URL_WHITELIST_PREF = "webchannel.allowObject.urlWhitelist";
14-
15-
let _cachedWhitelist = null;
16-
17-
const CACHED_PREFS = {};
18-
XPCOMUtils.defineLazyPreferenceGetter(
19-
CACHED_PREFS,
20-
"URL_WHITELIST",
21-
URL_WHITELIST_PREF,
22-
"",
23-
// Null this out so we update it.
24-
() => (_cachedWhitelist = null)
25-
);
26-
278
export class WebChannelChild extends JSWindowActorChild {
289
handleEvent(event) {
2910
if (event.type === "WebChannelMessageToChrome") {
@@ -39,16 +20,6 @@ export class WebChannelChild extends JSWindowActorChild {
3920
return undefined;
4021
}
4122

42-
_getWhitelistedPrincipals() {
43-
if (!_cachedWhitelist) {
44-
let urls = CACHED_PREFS.URL_WHITELIST.split(/\s+/);
45-
_cachedWhitelist = urls.map(origin =>
46-
Services.scriptSecurityManager.createContentPrincipalFromOrigin(origin)
47-
);
48-
}
49-
return _cachedWhitelist;
50-
}
51-
5223
_onMessageToChrome(e) {
5324
// If target is window then we want the document principal, otherwise fallback to target itself.
5425
let principal = e.target.nodePrincipal
@@ -57,19 +28,8 @@ export class WebChannelChild extends JSWindowActorChild {
5728

5829
if (e.detail) {
5930
if (typeof e.detail != "string") {
60-
// Check if the principal is one of the ones that's allowed to send
61-
// non-string values for e.detail. They're whitelisted by site origin,
62-
// so we compare on originNoSuffix in order to avoid other origin attributes
63-
// that are not relevant here, such as containers or private browsing.
64-
let objectsAllowed = this._getWhitelistedPrincipals().some(
65-
whitelisted => principal.originNoSuffix == whitelisted.originNoSuffix
66-
);
67-
if (!objectsAllowed) {
68-
console.error(
69-
"WebChannelMessageToChrome sent with an object from a non-whitelisted principal"
70-
);
71-
return;
72-
}
31+
console.error("WebChannelMessageToChrome must only send strings");
32+
return;
7333
}
7434

7535
let eventTarget =

toolkit/modules/tests/browser/browser_web_channel.js

Lines changed: 4 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -425,14 +425,13 @@ var gTests = [
425425
},
426426
},
427427
{
428-
desc: "WebChannel disallows non-string message from non-whitelisted origin",
428+
desc: "WebChannel disallows non-string messages",
429429
async run() {
430430
/**
431431
* This test ensures that non-string messages can't be sent via WebChannels.
432-
* We create a page (on a non-whitelisted origin) which should send us two
433-
* messages immediately. The first message has an object for it's detail,
434-
* and the second has a string. We check that we only get the second
435-
* message.
432+
* We create a page which should send us two messages immediately. The first
433+
* message has an object for its detail, and the second has a string. We
434+
* check that we only get the second message.
436435
*/
437436
let channel = new WebChannel("objects", Services.io.newURI(HTTP_PATH));
438437
let testDonePromise = new Promise(resolve => {
@@ -454,51 +453,6 @@ var gTests = [
454453
);
455454
},
456455
},
457-
{
458-
desc: "WebChannel allows both string and non-string message from whitelisted origin",
459-
async run() {
460-
/**
461-
* Same process as above, but we whitelist the origin before loading the page,
462-
* and expect to get *both* messages back (each exactly once).
463-
*/
464-
let channel = new WebChannel("objects", Services.io.newURI(HTTP_PATH));
465-
466-
let testDonePromise = new Promise((resolve, reject) => {
467-
let sawObject = false;
468-
let sawString = false;
469-
channel.listen((id, message) => {
470-
is(id, "objects");
471-
if (message.type === "object") {
472-
ok(!sawObject);
473-
sawObject = true;
474-
} else if (message.type === "string") {
475-
ok(!sawString);
476-
sawString = true;
477-
} else {
478-
reject(new Error(`Unknown message type: ${message.type}`));
479-
}
480-
if (sawObject && sawString) {
481-
resolve();
482-
}
483-
});
484-
});
485-
const webchannelWhitelistPref = "webchannel.allowObject.urlWhitelist";
486-
let origWhitelist = Services.prefs.getCharPref(webchannelWhitelistPref);
487-
let newWhitelist = origWhitelist + " " + HTTP_PATH;
488-
Services.prefs.setCharPref(webchannelWhitelistPref, newWhitelist);
489-
await BrowserTestUtils.withNewTab(
490-
{
491-
gBrowser,
492-
url: HTTP_PATH + HTTP_ENDPOINT + "?object",
493-
},
494-
async function () {
495-
await testDonePromise;
496-
Services.prefs.setCharPref(webchannelWhitelistPref, origWhitelist);
497-
channel.stopListening();
498-
}
499-
);
500-
},
501-
},
502456
{
503457
desc: "WebChannel errors handling the message are delivered back to content",
504458
async run() {

tools/lint/rejected-words.yml

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ avoid-blacklist-and-whitelist:
3535
- browser/app/winlauncher/LauncherProcessWin.cpp
3636
- browser/base/content/browser.js
3737
- browser/base/content/contentTheme.js
38-
- browser/base/content/test/general/browser_remoteTroubleshoot.js
3938
- browser/base/content/test/general/browser_tab_drag_drop_perwindow.js
4039
- browser/base/content/test/performance/browser_preferences_usage.js
4140
- browser/base/content/test/protectionsUI/browser_protectionsUI_cryptominers.js
@@ -233,7 +232,6 @@ avoid-blacklist-and-whitelist:
233232
- testing/raptor/browsertime/browsertime_scenario.js
234233
- testing/web-platform/tests/tools/manifest/tests/test_manifest.py
235234
- toolkit/actors/RemotePageChild.sys.mjs
236-
- toolkit/actors/WebChannelChild.sys.mjs
237235
- toolkit/components/antitracking/docs/tracking-lists/index.md
238236
- toolkit/components/antitracking/test/browser/browser_socialtracking_save_image.js
239237
- toolkit/components/reputationservice/ApplicationReputation.cpp
@@ -269,7 +267,6 @@ avoid-blacklist-and-whitelist:
269267
- toolkit/content/tests/browser/browser_delay_autoplay_webAudio.js
270268
- toolkit/modules/PermissionsUtils.sys.mjs
271269
- toolkit/modules/tests/browser/browser_AsyncPrefs.js
272-
- toolkit/modules/tests/browser/browser_web_channel.js
273270
- toolkit/modules/tests/xpcshell/test_PermissionsUtils.js
274271
- toolkit/modules/third_party/jsesc/jsesc.mjs
275272
- toolkit/modules/Troubleshoot.sys.mjs

0 commit comments

Comments
 (0)