From 20040f196d70afa0d9c32f2b326a18e26b8d414b Mon Sep 17 00:00:00 2001 From: Christoph Kerschbaumer Date: Mon, 20 May 2019 15:59:28 +0000 Subject: [PATCH] Bug 1551379: Allow non linkable about: pages to skip CORS when loading local module scripts. r=smaug Differential Revision: https://phabricator.services.mozilla.com/D31514 --HG-- extra : moz-landing-system : lando --- dom/script/ScriptLoader.cpp | 64 +++++++++++++++++++++++++++++++++---- dom/script/ScriptLoader.h | 9 ++++++ 2 files changed, 66 insertions(+), 7 deletions(-) diff --git a/dom/script/ScriptLoader.cpp b/dom/script/ScriptLoader.cpp index fec704fc673e..1ce18cb0b2f0 100644 --- a/dom/script/ScriptLoader.cpp +++ b/dom/script/ScriptLoader.cpp @@ -30,6 +30,7 @@ #include "mozilla/dom/SRILogHelper.h" #include "mozilla/net/UrlClassifierFeatureFactory.h" #include "mozilla/StaticPrefs.h" +#include "nsAboutProtocolUtils.h" #include "nsGkAtoms.h" #include "nsNetUtil.h" #include "nsGlobalWindowInner.h" @@ -338,6 +339,50 @@ nsresult ScriptLoader::CheckContentPolicy(Document* aDocument, return NS_OK; } +/* static */ +bool ScriptLoader::IsAboutPageLoadingChromeURI(ScriptLoadRequest* aRequest) { + // if we are not dealing with a codebasePrincipal it can not be a + // Principal with a scheme of about: and there is nothing left to do + if (!aRequest->TriggeringPrincipal()->GetIsCodebasePrincipal()) { + return false; + } + + // if the triggering uri is not of scheme about:, there is nothing to do + nsCOMPtr triggeringURI; + nsresult rv = + aRequest->TriggeringPrincipal()->GetURI(getter_AddRefs(triggeringURI)); + NS_ENSURE_SUCCESS(rv, false); + + bool isAbout = + (NS_SUCCEEDED(triggeringURI->SchemeIs("about", &isAbout)) && isAbout); + if (!isAbout) { + return false; + } + + // if the about: page is linkable from content, there is nothing to do + nsCOMPtr aboutMod; + rv = NS_GetAboutModule(triggeringURI, getter_AddRefs(aboutMod)); + NS_ENSURE_SUCCESS(rv, false); + + uint32_t aboutModuleFlags = 0; + rv = aboutMod->GetURIFlags(triggeringURI, &aboutModuleFlags); + NS_ENSURE_SUCCESS(rv, false); + + if (aboutModuleFlags & nsIAboutModule::MAKE_LINKABLE) { + return false; + } + + // if the uri to be loaded is not of scheme chrome:, there is nothing to do. + bool isChrome = + (NS_SUCCEEDED(aRequest->mURI->SchemeIs("chrome", &isChrome)) && isChrome); + if (!isChrome) { + return false; + } + + // seems like an about page wants to load a chrome URI. + return true; +} + bool ScriptLoader::ModuleMapContainsURL(nsIURI* aURL) const { // Returns whether we have fetched, or are currently fetching, a module script // for a URL. @@ -1240,14 +1285,19 @@ nsresult ScriptLoader::StartLoad(ScriptLoadRequest* aRequest) { nsSecurityFlags securityFlags; if (aRequest->IsModuleRequest()) { // According to the spec, module scripts have different behaviour to classic - // scripts and always use CORS. - securityFlags = nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS; - if (aRequest->CORSMode() == CORS_NONE || - aRequest->CORSMode() == CORS_ANONYMOUS) { - securityFlags |= nsILoadInfo::SEC_COOKIES_SAME_ORIGIN; + // scripts and always use CORS. Only exception: Non linkable about: pages + // which load local module scripts. + if (IsAboutPageLoadingChromeURI(aRequest)) { + securityFlags = nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL; } else { - MOZ_ASSERT(aRequest->CORSMode() == CORS_USE_CREDENTIALS); - securityFlags |= nsILoadInfo::SEC_COOKIES_INCLUDE; + securityFlags = nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS; + if (aRequest->CORSMode() == CORS_NONE || + aRequest->CORSMode() == CORS_ANONYMOUS) { + securityFlags |= nsILoadInfo::SEC_COOKIES_SAME_ORIGIN; + } else { + MOZ_ASSERT(aRequest->CORSMode() == CORS_USE_CREDENTIALS); + securityFlags |= nsILoadInfo::SEC_COOKIES_INCLUDE; + } } } else { securityFlags = aRequest->CORSMode() == CORS_NONE diff --git a/dom/script/ScriptLoader.h b/dom/script/ScriptLoader.h index 0609a56fb0dc..8743e50233a7 100644 --- a/dom/script/ScriptLoader.h +++ b/dom/script/ScriptLoader.h @@ -387,6 +387,15 @@ class ScriptLoader final : public nsISupports { const nsAString& aType, ScriptLoadRequest* aRequest); + /** + * Helper function to determine whether an about: page loads a chrome: URI. + * Please note that this function only returns true if: + * * the about: page uses a CodeBasePrincipal with scheme about: + * * the about: page is not linkable from content + * (e.g. the function will return false for about:blank or about:srcdoc) + */ + static bool IsAboutPageLoadingChromeURI(ScriptLoadRequest* aRequest); + /** * Start a load for aRequest's URI. */