From 3dc935e44459934c844bdd079338a08b96acc818 Mon Sep 17 00:00:00 2001 From: Gijs Kruitbosch Date: Tue, 26 Mar 2024 12:38:54 +0000 Subject: [PATCH] Bug 1881800 - chrome/system-privileged XHR should not use credentials, r=peterv,extension-reviewers,application-update-reviewers,decoder,mossop,robwu,releng-reviewers,bytesized,jcristau Differential Revision: https://phabricator.services.mozilla.com/D203334 --- .../components/pocket/content/pktApi.sys.mjs | 2 +- dom/base/test/unit/test_xhr_standalone.js | 5 +++++ dom/tests/unit/test_xhr_init.js | 8 +++++++ dom/webidl/XMLHttpRequest.webidl | 7 ++++-- dom/xhr/XMLHttpRequest.cpp | 22 ++++++++++++++----- dom/xhr/XMLHttpRequestWorker.cpp | 8 ++++--- .../extensions/parent/ext-identity.js | 2 +- .../pdfjs/content/PdfJsNetwork.sys.mjs | 2 +- .../pdfjs/content/PdfStreamConverter.sys.mjs | 2 +- toolkit/components/reader/ReaderMode.sys.mjs | 2 +- toolkit/modules/AsanReporter.sys.mjs | 2 +- 11 files changed, 45 insertions(+), 17 deletions(-) diff --git a/browser/components/pocket/content/pktApi.sys.mjs b/browser/components/pocket/content/pktApi.sys.mjs index 6b4d423eda55..132f9369cee7 100644 --- a/browser/components/pocket/content/pktApi.sys.mjs +++ b/browser/components/pocket/content/pktApi.sys.mjs @@ -308,7 +308,7 @@ export var pktApi = (function () { data.locale_lang = Services.locale.appLocaleAsBCP47; data.consumer_key = oAuthConsumerKey; - var request = new XMLHttpRequest(); + var request = new XMLHttpRequest({ mozAnon: false }); if (!useBFF) { request.open("POST", url, true); diff --git a/dom/base/test/unit/test_xhr_standalone.js b/dom/base/test/unit/test_xhr_standalone.js index 94f2d7d642c1..100027f38ab5 100644 --- a/dom/base/test/unit/test_xhr_standalone.js +++ b/dom/base/test/unit/test_xhr_standalone.js @@ -6,6 +6,10 @@ // in non-window non-Worker context function run_test() { + Services.prefs.setBoolPref( + "network.fetch.systemDefaultsToOmittingCredentials", + false + ); var xhr = new XMLHttpRequest(); xhr.open("GET", "data:,", false); var exceptionThrown = false; @@ -13,6 +17,7 @@ function run_test() { xhr.responseType = ""; xhr.withCredentials = false; } catch (e) { + console.error(e); exceptionThrown = true; } Assert.equal(false, exceptionThrown); diff --git a/dom/tests/unit/test_xhr_init.js b/dom/tests/unit/test_xhr_init.js index a2eaf2b4d727..0f7255806ec8 100644 --- a/dom/tests/unit/test_xhr_init.js +++ b/dom/tests/unit/test_xhr_init.js @@ -7,6 +7,14 @@ function run_test() { Assert.ok(x.mozAnon); Assert.ok(x.mozSystem); + x = new XMLHttpRequest(); + Assert.ok(x.mozAnon); + Assert.ok(x.mozSystem); + + Services.prefs.setBoolPref( + "network.fetch.systemDefaultsToOmittingCredentials", + false + ); x = new XMLHttpRequest(); Assert.ok(!x.mozAnon); Assert.ok(x.mozSystem); diff --git a/dom/webidl/XMLHttpRequest.webidl b/dom/webidl/XMLHttpRequest.webidl index 66cd6cc79de1..b1cc840faae7 100644 --- a/dom/webidl/XMLHttpRequest.webidl +++ b/dom/webidl/XMLHttpRequest.webidl @@ -32,9 +32,12 @@ dictionary MozXMLHttpRequestParameters { /** * If true, the request will be sent without cookie and authentication - * headers. + * headers. Defaults to true for system/privileged/chrome requests, + * and to false otherwise. + * Note that even if set to true, for system/privileged/chrome requests, + * manually-set 'Cookie' headers are not removed. */ - boolean mozAnon = false; + boolean mozAnon; /** * If true, the same origin policy will not be enforced on the request. diff --git a/dom/xhr/XMLHttpRequest.cpp b/dom/xhr/XMLHttpRequest.cpp index be94267d63ec..2994e1af8981 100644 --- a/dom/xhr/XMLHttpRequest.cpp +++ b/dom/xhr/XMLHttpRequest.cpp @@ -8,6 +8,7 @@ #include "XMLHttpRequestMainThread.h" #include "XMLHttpRequestWorker.h" #include "mozilla/Logging.h" +#include "mozilla/StaticPrefs_network.h" #include "mozilla/net/CookieJarSettings.h" mozilla::LazyLogModule gXMLHttpRequestLog("XMLHttpRequest"); @@ -21,15 +22,16 @@ already_AddRefed XMLHttpRequest::Constructor( if (NS_IsMainThread()) { nsCOMPtr global = do_QueryInterface(aGlobal.GetAsSupports()); - nsCOMPtr principal = + nsCOMPtr scriptPrincipal = do_QueryInterface(aGlobal.GetAsSupports()); - if (!global || !principal) { + if (!global || !scriptPrincipal) { aRv.Throw(NS_ERROR_FAILURE); return nullptr; } nsCOMPtr cookieJarSettings; nsCOMPtr window = do_QueryInterface(global); + nsCOMPtr principal = scriptPrincipal->GetPrincipal(); if (window) { Document* document = window->GetExtantDoc(); if (NS_WARN_IF(!document)) { @@ -40,13 +42,21 @@ already_AddRefed XMLHttpRequest::Constructor( cookieJarSettings = document->CookieJarSettings(); } else { // We are here because this is a sandbox. - cookieJarSettings = - net::CookieJarSettings::Create(principal->GetPrincipal()); + cookieJarSettings = net::CookieJarSettings::Create(principal); } RefPtr req = new XMLHttpRequestMainThread(global); - req->Construct(principal->GetPrincipal(), cookieJarSettings, false); - req->InitParameters(aParams.mMozAnon, aParams.mMozSystem); + req->Construct(principal, cookieJarSettings, false); + + bool isAnon = false; + if (aParams.mMozAnon.WasPassed()) { + isAnon = aParams.mMozAnon.Value(); + } else { + isAnon = + StaticPrefs::network_fetch_systemDefaultsToOmittingCredentials() && + (aParams.mMozSystem || principal->IsSystemPrincipal()); + } + req->InitParameters(isAnon, aParams.mMozSystem); return req.forget(); } diff --git a/dom/xhr/XMLHttpRequestWorker.cpp b/dom/xhr/XMLHttpRequestWorker.cpp index 7fdfa8fee943..67cba876dbb3 100644 --- a/dom/xhr/XMLHttpRequestWorker.cpp +++ b/dom/xhr/XMLHttpRequestWorker.cpp @@ -1388,10 +1388,12 @@ already_AddRefed XMLHttpRequestWorker::Construct( new XMLHttpRequestWorker(workerPrivate, global); if (workerPrivate->XHRParamsAllowed()) { - if (aParams.mMozSystem) + if (aParams.mMozSystem) { xhr->mMozAnon = true; - else - xhr->mMozAnon = aParams.mMozAnon; + } else { + xhr->mMozAnon = + aParams.mMozAnon.WasPassed() ? aParams.mMozAnon.Value() : false; + } xhr->mMozSystem = aParams.mMozSystem; } diff --git a/toolkit/components/extensions/parent/ext-identity.js b/toolkit/components/extensions/parent/ext-identity.js index bd53163305ad..f0f63dbf340e 100644 --- a/toolkit/components/extensions/parent/ext-identity.js +++ b/toolkit/components/extensions/parent/ext-identity.js @@ -12,7 +12,7 @@ var { promiseDocumentLoaded } = ExtensionUtils; const checkRedirected = (url, redirectURI) => { return new Promise((resolve, reject) => { - let xhr = new XMLHttpRequest(); + let xhr = new XMLHttpRequest({ mozAnon: false }); xhr.open("GET", url); // We expect this if the user has not authenticated. xhr.onload = () => { diff --git a/toolkit/components/pdfjs/content/PdfJsNetwork.sys.mjs b/toolkit/components/pdfjs/content/PdfJsNetwork.sys.mjs index 2f0d428f1857..a36f889539c9 100644 --- a/toolkit/components/pdfjs/content/PdfJsNetwork.sys.mjs +++ b/toolkit/components/pdfjs/content/PdfJsNetwork.sys.mjs @@ -33,7 +33,7 @@ export class NetworkManager { this.getXhr = args.getXhr || function NetworkManager_getXhr() { - return new XMLHttpRequest(); + return new XMLHttpRequest({ mozAnon: false }); }; this.currXhrId = 0; diff --git a/toolkit/components/pdfjs/content/PdfStreamConverter.sys.mjs b/toolkit/components/pdfjs/content/PdfStreamConverter.sys.mjs index 6df69449c53c..ce9c6898e30e 100644 --- a/toolkit/components/pdfjs/content/PdfStreamConverter.sys.mjs +++ b/toolkit/components/pdfjs/content/PdfStreamConverter.sys.mjs @@ -545,7 +545,7 @@ class RangedChromeActions extends ChromeActions { } }; var getXhr = function getXhr() { - var xhr = new XMLHttpRequest(); + var xhr = new XMLHttpRequest({ mozAnon: false }); xhr.addEventListener("readystatechange", xhr_onreadystatechange); return xhr; }; diff --git a/toolkit/components/reader/ReaderMode.sys.mjs b/toolkit/components/reader/ReaderMode.sys.mjs index 8fcc91cff729..c2561bfb23ae 100644 --- a/toolkit/components/reader/ReaderMode.sys.mjs +++ b/toolkit/components/reader/ReaderMode.sys.mjs @@ -273,7 +273,7 @@ export var ReaderMode = { "READER_MODE_DOWNLOAD_RESULT" ); return new Promise((resolve, reject) => { - let xhr = new XMLHttpRequest(); + let xhr = new XMLHttpRequest({ mozAnon: false }); xhr.open("GET", url, true); xhr.onerror = evt => reject(evt.error); xhr.responseType = docContentType === "text/plain" ? "text" : "document"; diff --git a/toolkit/modules/AsanReporter.sys.mjs b/toolkit/modules/AsanReporter.sys.mjs index 3e24ae8a9695..50929fbad970 100644 --- a/toolkit/modules/AsanReporter.sys.mjs +++ b/toolkit/modules/AsanReporter.sys.mjs @@ -135,7 +135,7 @@ function submitToServer(data) { tool: "asan-nightly-program", }; - var xhr = new XMLHttpRequest(); + var xhr = new XMLHttpRequest({ mozAnon: !auth_token }); xhr.open("POST", api_url, true); xhr.setRequestHeader("Content-Type", "application/json");