зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1691658 - block http redirects to data: protocol, r=necko-reviewers,ckerschb,valentin
This also adds a network.allow_redirect_to_data pref in case we need to turn this back on for compat reasons. Differential Revision: https://phabricator.services.mozilla.com/D173988
This commit is contained in:
Родитель
c50223779d
Коммит
d0b8081ec4
|
@ -88,7 +88,7 @@ BlockModuleWithWrongMimeType=Loading module from “%1$S” was blocked because
|
|||
|
||||
# LOCALIZATION NOTE: Do not translate "data: URI".
|
||||
BlockTopLevelDataURINavigation=Navigation to toplevel data: URI not allowed (Blocked loading of: “%1$S”)
|
||||
BlockSubresourceRedirectToData=Redirecting to insecure data: URI not allowed (Blocked loading of: “%1$S”)
|
||||
BlockRedirectToDataURI=Redirecting to data: URI not allowed (Blocked loading of: “%1$S”)
|
||||
|
||||
# LOCALIZATION NOTE: Do not translate "file: URI". “%1$S” is the whole URI of the loaded file. “%2$S” is the MIME type e.g. "text/plain".
|
||||
BlockFileScriptWithWrongMimeType=Loading script from file: URI (“%1$S”) was blocked because its MIME type (“%2$S”) is not a valid JavaScript MIME type.
|
||||
|
|
|
@ -131,10 +131,18 @@ bool nsContentSecurityManager::AllowTopLevelNavigationToDataURI(
|
|||
return true;
|
||||
}
|
||||
|
||||
ReportBlockedDataURI(uri, loadInfo);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void nsContentSecurityManager::ReportBlockedDataURI(nsIURI* aURI,
|
||||
nsILoadInfo* aLoadInfo,
|
||||
bool aIsRedirect) {
|
||||
// We're going to block the request, construct the localized error message to
|
||||
// report to the console.
|
||||
nsAutoCString dataSpec;
|
||||
uri->GetSpec(dataSpec);
|
||||
aURI->GetSpec(dataSpec);
|
||||
if (dataSpec.Length() > 50) {
|
||||
dataSpec.Truncate(50);
|
||||
dataSpec.AppendLiteral("...");
|
||||
|
@ -142,18 +150,20 @@ bool nsContentSecurityManager::AllowTopLevelNavigationToDataURI(
|
|||
AutoTArray<nsString, 1> params;
|
||||
CopyUTF8toUTF16(NS_UnescapeURL(dataSpec), *params.AppendElement());
|
||||
nsAutoString errorText;
|
||||
rv = nsContentUtils::FormatLocalizedString(
|
||||
nsContentUtils::eSECURITY_PROPERTIES, "BlockTopLevelDataURINavigation",
|
||||
params, errorText);
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
const char* stringID =
|
||||
aIsRedirect ? "BlockRedirectToDataURI" : "BlockTopLevelDataURINavigation";
|
||||
nsresult rv = nsContentUtils::FormatLocalizedString(
|
||||
nsContentUtils::eSECURITY_PROPERTIES, stringID, params, errorText);
|
||||
if (NS_FAILED(rv)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Report the localized error message to the console for the loading
|
||||
// BrowsingContext's current inner window.
|
||||
RefPtr<BrowsingContext> target = loadInfo->GetBrowsingContext();
|
||||
RefPtr<BrowsingContext> target = aLoadInfo->GetBrowsingContext();
|
||||
nsContentUtils::ReportToConsoleByWindowID(
|
||||
errorText, nsIScriptError::warningFlag, "DATA_URI_BLOCKED"_ns,
|
||||
target ? target->GetCurrentInnerWindowId() : 0);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* static */
|
||||
|
@ -181,23 +191,8 @@ bool nsContentSecurityManager::AllowInsecureRedirectToDataURI(
|
|||
return true;
|
||||
}
|
||||
|
||||
nsAutoCString dataSpec;
|
||||
newURI->GetSpec(dataSpec);
|
||||
if (dataSpec.Length() > 50) {
|
||||
dataSpec.Truncate(50);
|
||||
dataSpec.AppendLiteral("...");
|
||||
}
|
||||
nsCOMPtr<Document> doc;
|
||||
nsINode* node = loadInfo->LoadingNode();
|
||||
if (node) {
|
||||
doc = node->OwnerDoc();
|
||||
}
|
||||
AutoTArray<nsString, 1> params;
|
||||
CopyUTF8toUTF16(NS_UnescapeURL(dataSpec), *params.AppendElement());
|
||||
nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
|
||||
"DATA_URI_BLOCKED"_ns, doc,
|
||||
nsContentUtils::eSECURITY_PROPERTIES,
|
||||
"BlockSubresourceRedirectToData", params);
|
||||
ReportBlockedDataURI(newURI, loadInfo, true);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -39,6 +39,8 @@ class nsContentSecurityManager : public nsIContentSecurityManager,
|
|||
nsIChannel* aChannel, nsCOMPtr<nsIStreamListener>& aInAndOutListener);
|
||||
|
||||
static bool AllowTopLevelNavigationToDataURI(nsIChannel* aChannel);
|
||||
static void ReportBlockedDataURI(nsIURI* aURI, nsILoadInfo* aLoadInfo,
|
||||
bool aIsRedirect = false);
|
||||
static bool AllowInsecureRedirectToDataURI(nsIChannel* aNewChannel);
|
||||
static void MeasureUnexpectedPrivilegedLoads(nsILoadInfo* aLoadInfo,
|
||||
nsIURI* aFinalURI,
|
||||
|
|
|
@ -47,11 +47,25 @@ var origins =
|
|||
//['https://example.com:443'],
|
||||
//['https://sub1.test1.example.com:443'],
|
||||
|
||||
window.addEventListener("message", function(e) {
|
||||
gen.next(e.data);
|
||||
});
|
||||
|
||||
gen = runTest();
|
||||
function initTest() {
|
||||
// Allow all cookies, then do the actual test initialization
|
||||
SpecialPowers.pushPrefEnv({
|
||||
"set": [
|
||||
// Some of this test relies on redirecting to data: URLs from http.
|
||||
["network.allow_redirect_to_data", true],
|
||||
]
|
||||
}).then(initTestCallback);
|
||||
}
|
||||
|
||||
function initTestCallback() {
|
||||
window.addEventListener("message", function(e) {
|
||||
gen.next(e.data);
|
||||
});
|
||||
|
||||
gen = runTest();
|
||||
gen.next();
|
||||
}
|
||||
|
||||
function* runTest() {
|
||||
var loader = document.getElementById('loader');
|
||||
|
@ -158,9 +172,8 @@ function* runTest() {
|
|||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
addLoadEvent(function() {
|
||||
gen.next();
|
||||
});
|
||||
addLoadEvent(initTest);
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
|
|
|
@ -24,7 +24,8 @@ async function expectBlockedToplevelData() {
|
|||
return;
|
||||
}
|
||||
|
||||
if (ChromeUtils.getXPCOMErrorName(status) != "NS_ERROR_DOM_BAD_URI") {
|
||||
if (!["NS_ERROR_DOM_BAD_URI", "NS_ERROR_CORRUPTED_CONTENT"].includes(ChromeUtils.getXPCOMErrorName(status))) {
|
||||
info(ChromeUtils.getXPCOMErrorName(status));
|
||||
isnot(request.URI.scheme, "data");
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -12556,6 +12556,11 @@
|
|||
value: 1
|
||||
mirror: always
|
||||
|
||||
- name: network.allow_redirect_to_data
|
||||
type: RelaxedAtomicBool
|
||||
value: false
|
||||
mirror: always
|
||||
|
||||
- name: network.allow_raw_sockets_in_content_processes
|
||||
type: bool
|
||||
value: false
|
||||
|
|
|
@ -1412,7 +1412,7 @@ nsresult nsHttpChannel::SetupTransaction() {
|
|||
EnsureRequestContext();
|
||||
|
||||
HttpTrafficCategory category = CreateTrafficCategory();
|
||||
std::function<void(TransactionObserverResult &&)> observer;
|
||||
std::function<void(TransactionObserverResult&&)> observer;
|
||||
if (mTransactionObserver) {
|
||||
observer = [transactionObserver{std::move(mTransactionObserver)}](
|
||||
TransactionObserverResult&& aResult) {
|
||||
|
@ -5246,6 +5246,15 @@ nsresult nsHttpChannel::AsyncProcessRedirection(uint32_t redirectType) {
|
|||
return NS_ERROR_CORRUPTED_CONTENT;
|
||||
}
|
||||
|
||||
if (!StaticPrefs::network_allow_redirect_to_data() &&
|
||||
!mLoadInfo->GetAllowInsecureRedirectToDataURI() &&
|
||||
mRedirectURI->SchemeIs("data")) {
|
||||
LOG(("Invalid data URI for redirect!"));
|
||||
nsContentSecurityManager::ReportBlockedDataURI(mRedirectURI, mLoadInfo,
|
||||
true);
|
||||
return NS_ERROR_DOM_BAD_URI;
|
||||
}
|
||||
|
||||
// Perform the URL query string stripping for redirects. We will only strip
|
||||
// the query string if it is redirecting to a third-party URI in the top
|
||||
// level.
|
||||
|
|
|
@ -33,8 +33,11 @@ support-files =
|
|||
# interception, we need to explicitly enable the pref.
|
||||
# Consider enabling it in StaticPrefList.yaml
|
||||
# https://bugzilla.mozilla.org/show_bug.cgi?id=1816325
|
||||
# Several tests rely on redirecting to data: URIs, which was allowed for a long
|
||||
# time but now forbidden. So we enable it just for these tests.
|
||||
prefs =
|
||||
dom.serviceWorkers.enabled=true
|
||||
network.allow_redirect_to_data=true
|
||||
|
||||
[test_trr_nat64.js]
|
||||
run-sequentially = node server exceptions dont replay well
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
[DEFAULT]
|
||||
head = head_channels_clone.js head_trr_clone.js head_http3_clone.js ../unit/head_servers.js
|
||||
skip-if = socketprocess_networking
|
||||
# Several tests rely on redirecting to data: URIs, which was allowed for a long
|
||||
# time but now forbidden. So we enable it just for these tests.
|
||||
prefs =
|
||||
network.allow_redirect_to_data=true
|
||||
support-files =
|
||||
child_channel_id.js
|
||||
!/netwerk/test/unit/test_XHR_redirects.js
|
||||
|
|
|
@ -1,41 +0,0 @@
|
|||
[redirect-to-dataurl.any.worker.html]
|
||||
expected:
|
||||
if (os == "android") and fission: [OK, TIMEOUT]
|
||||
[Testing data URL loading after same-origin redirection (no-cors mode)]
|
||||
expected: FAIL
|
||||
|
||||
[Testing data URL loading after same-origin redirection (same-origin mode)]
|
||||
expected: FAIL
|
||||
|
||||
[Testing data URL loading after cross-origin redirection (no-cors mode)]
|
||||
expected: FAIL
|
||||
|
||||
|
||||
[redirect-to-dataurl.any.html]
|
||||
expected:
|
||||
if (os == "android") and fission: [OK, TIMEOUT]
|
||||
[Testing data URL loading after same-origin redirection (no-cors mode)]
|
||||
expected: FAIL
|
||||
|
||||
[Testing data URL loading after same-origin redirection (same-origin mode)]
|
||||
expected: FAIL
|
||||
|
||||
[Testing data URL loading after cross-origin redirection (no-cors mode)]
|
||||
expected: FAIL
|
||||
|
||||
|
||||
[redirect-to-dataurl.any.serviceworker.html]
|
||||
expected:
|
||||
if (os == "android") and fission: [TIMEOUT, OK]
|
||||
|
||||
[redirect-to-dataurl.any.sharedworker.html]
|
||||
expected:
|
||||
if (os == "android") and fission: [OK, TIMEOUT]
|
||||
[Testing data URL loading after cross-origin redirection (no-cors mode)]
|
||||
expected: FAIL
|
||||
|
||||
[Testing data URL loading after same-origin redirection (same-origin mode)]
|
||||
expected: FAIL
|
||||
|
||||
[Testing data URL loading after same-origin redirection (no-cors mode)]
|
||||
expected: FAIL
|
|
@ -1,4 +0,0 @@
|
|||
[data.window.html]
|
||||
[<img> fetch that redirects to data: URL]
|
||||
expected: FAIL
|
||||
|
|
@ -1,6 +1,16 @@
|
|||
[redirect-to-data.html]
|
||||
# This test relies on iframe.onload, which doesn't work:
|
||||
# https://bugzilla.mozilla.org/show_bug.cgi?id=1194350
|
||||
expected: TIMEOUT
|
||||
|
||||
[Loading an iframe with src=redirecting URL]
|
||||
expected: FAIL
|
||||
expected: TIMEOUT
|
||||
|
||||
[Navigating an iframe to a redirecting URL]
|
||||
expected: FAIL
|
||||
expected: NOTRUN
|
||||
|
||||
[Loading a popup directly to the redirecting URL]
|
||||
expected: NOTRUN
|
||||
|
||||
[Loading a popup that eventually goes to the redirecting URL]
|
||||
expected: NOTRUN
|
||||
|
|
Загрузка…
Ссылка в новой задаче