Bug 1705044 r=freddyb,Gijs,mixedpuppy

Differential Revision: https://phabricator.services.mozilla.com/D154919
This commit is contained in:
Shane Caraveo 2022-11-03 17:00:40 +00:00
parent 66b80c7e7f
commit d3e7b16fa3
5 changed files with 140 additions and 5 deletions

View File

@ -95,6 +95,9 @@ BlockSubresourceFTP=Loading FTP subresource within http(s) page not allowed (Blo
# 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.
# LOCALIZATION NOTE: “%S” is the whole URI of the loaded file.
BlockExtensionScriptWithWrongExt=Loading script from extension URI (“%S”) was blocked because the file extension is not allowed.
RestrictBrowserEvalUsage=eval() and eval-like uses are not allowed in the Parent Process or in System Contexts (Blocked usage in “%1$S”)
# LOCALIZATION NOTE (MixedContentAutoUpgrade):

View File

@ -36,7 +36,9 @@
#include "mozilla/dom/ContentChild.h"
#include "mozilla/dom/ContentParent.h"
#include "mozilla/dom/Document.h"
#include "mozilla/extensions/WebExtensionPolicy.h"
#include "mozilla/Components.h"
#include "mozilla/ExtensionPolicyService.h"
#include "mozilla/Logging.h"
#include "mozilla/Maybe.h"
#include "mozilla/Preferences.h"
@ -1354,6 +1356,74 @@ static nsresult CheckAllowFileProtocolScriptLoad(nsIChannel* aChannel) {
return NS_OK;
}
// We should not allow loading non-JavaScript files as scripts using
// a moz-extension:// URL.
static nsresult CheckAllowExtensionProtocolScriptLoad(nsIChannel* aChannel) {
nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
ExtContentPolicyType type = loadInfo->GetExternalContentPolicyType();
// Only check script loads.
if (type != ExtContentPolicy::TYPE_SCRIPT) {
return NS_OK;
}
nsCOMPtr<nsIURI> uri;
nsresult rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(uri));
NS_ENSURE_SUCCESS(rv, rv);
if (!uri || !uri->SchemeIs("moz-extension")) {
return NS_OK;
}
// We expect this code to never be hit off-the-main-thread (even worker
// scripts are currently hitting only on the main thread, see
// WorkerScriptLoader::DispatchLoadScript calling NS_DispatchToMainThread
// internally), this diagnostic assertion is meant to let us notice if that
// isn't the case anymore.
MOZ_DIAGNOSTIC_ASSERT(NS_IsMainThread(),
"Unexpected off-the-main-thread call to "
"CheckAllowFileProtocolScriptLoad");
nsAutoCString host;
rv = uri->GetHost(host);
NS_ENSURE_SUCCESS(rv, rv);
RefPtr<extensions::WebExtensionPolicyCore> targetPolicy =
ExtensionPolicyService::GetCoreByHost(host);
if (NS_WARN_IF(!targetPolicy) || targetPolicy->ManifestVersion() < 3) {
return NS_OK;
}
nsCOMPtr<nsIMIMEService> mime = do_GetService("@mozilla.org/mime;1", &rv);
NS_ENSURE_SUCCESS(rv, rv);
// GetDefaultTypeFromExtension fails for missing or unknown file-extensions.
nsAutoCString contentType;
rv = mime->GetDefaultTypeFromURI(uri, contentType);
if (NS_FAILED(rv) || !nsContentUtils::IsJavascriptMIMEType(
NS_ConvertUTF8toUTF16(contentType))) {
nsCOMPtr<Document> doc;
if (nsINode* node = loadInfo->LoadingNode()) {
doc = node->OwnerDoc();
}
nsAutoCString spec;
uri->GetSpec(spec);
AutoTArray<nsString, 1> params;
CopyUTF8toUTF16(NS_UnescapeURL(spec), *params.AppendElement());
nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
"EXTENSION_SCRIPT_BLOCKED"_ns, doc,
nsContentUtils::eSECURITY_PROPERTIES,
"BlockExtensionScriptWithWrongExt", params);
return NS_ERROR_CONTENT_BLOCKED;
}
return NS_OK;
}
/*
* Based on the security flags provided in the loadInfo of the channel,
* doContentSecurityCheck() performs the following content security checks
@ -1386,6 +1456,11 @@ nsresult nsContentSecurityManager::doContentSecurityCheck(
rv = CheckAllowLoadInPrivilegedAboutContext(aChannel);
NS_ENSURE_SUCCESS(rv, rv);
// We want to also check redirected requests to ensure
// the target maintains the proper javascript file extensions.
rv = CheckAllowExtensionProtocolScriptLoad(aChannel);
NS_ENSURE_SUCCESS(rv, rv);
rv = CheckChannelHasProtocolSecurityFlag(aChannel);
NS_ENSURE_SUCCESS(rv, rv);

View File

@ -62,6 +62,17 @@ interface nsIMIMEService : nsISupports {
*/
ACString getTypeFromURI(in nsIURI aURI);
/**
* Retrieves a ACString representation of the MIME type
* associated with this file extension. Only the default
* builtin list is examined. Unless you need a restricted
* set use getTypeFromURI.
*
* @param The URI the user wants MIME info on.
* @return The MIME type, if any.
*/
ACString getDefaultTypeFromURI(in nsIURI aURI);
//
ACString getTypeFromFile(in nsIFile aFile);

View File

@ -2963,6 +2963,18 @@ NS_IMETHODIMP nsExternalHelperAppService::GetFromTypeAndExtension(
return NS_OK;
}
bool nsExternalHelperAppService::GetMIMETypeFromDefaultForExtension(
const nsACString& aExtension, nsACString& aMIMEType) {
// First of all, check our default entries
for (auto& entry : defaultMimeEntries) {
if (aExtension.LowerCaseEqualsASCII(entry.mFileExtension)) {
aMIMEType = entry.mMimeType;
return true;
}
}
return false;
}
NS_IMETHODIMP
nsExternalHelperAppService::GetTypeFromExtension(const nsACString& aFileExt,
nsACString& aContentType) {
@ -2982,11 +2994,8 @@ nsExternalHelperAppService::GetTypeFromExtension(const nsACString& aFileExt,
}
// First of all, check our default entries
for (auto& entry : defaultMimeEntries) {
if (aFileExt.LowerCaseEqualsASCII(entry.mFileExtension)) {
aContentType = entry.mMimeType;
return NS_OK;
}
if (GetMIMETypeFromDefaultForExtension(aFileExt, aContentType)) {
return NS_OK;
}
// Ask OS.
@ -3033,6 +3042,35 @@ NS_IMETHODIMP nsExternalHelperAppService::GetPrimaryExtension(
return mi->GetPrimaryExtension(_retval);
}
NS_IMETHODIMP nsExternalHelperAppService::GetDefaultTypeFromURI(
nsIURI* aURI, nsACString& aContentType) {
NS_ENSURE_ARG_POINTER(aURI);
nsresult rv = NS_ERROR_NOT_AVAILABLE;
aContentType.Truncate();
// Now try to get an nsIURL so we don't have to do our own parsing
nsCOMPtr<nsIURL> url = do_QueryInterface(aURI);
if (!url) {
return NS_ERROR_NOT_AVAILABLE;
}
nsAutoCString ext;
rv = url->GetFileExtension(ext);
if (NS_FAILED(rv)) {
return rv;
}
if (!ext.IsEmpty()) {
UnescapeFragment(ext, url, ext);
if (GetMIMETypeFromDefaultForExtension(ext, aContentType)) {
return NS_OK;
}
}
return NS_ERROR_NOT_AVAILABLE;
};
NS_IMETHODIMP nsExternalHelperAppService::GetTypeFromURI(
nsIURI* aURI, nsACString& aContentType) {
NS_ENSURE_ARG_POINTER(aURI);

View File

@ -111,6 +111,14 @@ class nsExternalHelperAppService : public nsIExternalHelperAppService,
NS_IMETHOD OSProtocolHandlerExists(const char* aScheme, bool* aExists) = 0;
/**
* Given an extension, get a MIME type string from the builtin list of
* mime types.
* @return true if we successfully found a mimetype.
*/
virtual bool GetMIMETypeFromDefaultForExtension(const nsACString& aExtension,
nsACString& aMIMEType);
/**
* Given an extension, get a MIME type string. If not overridden by
* the OS-specific nsOSHelperAppService, will call into GetMIMEInfoFromOS