зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1509738: CSP snapshot nonce at load start time r=baku
Differential Revision: https://phabricator.services.mozilla.com/D19519 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
4983b7d437
Коммит
6111ccf5fd
|
@ -302,7 +302,8 @@ interface nsIContentSecurityPolicy : nsISerializable
|
|||
in nsISupports aContext,
|
||||
in ACString aMimeTypeGuess,
|
||||
in nsIURI aOriginalURIIfRedirect,
|
||||
in bool aSendViolationReports);
|
||||
in bool aSendViolationReports,
|
||||
in AString aNonce);
|
||||
|
||||
%{ C++
|
||||
// nsIObserver topic to fire when the policy encounters a violation.
|
||||
|
|
|
@ -311,6 +311,16 @@ nsresult ScriptLoader::CheckContentPolicy(Document* aDocument,
|
|||
requestingNode, nsILoadInfo::SEC_ONLY_FOR_EXPLICIT_CONTENTSEC_CHECK,
|
||||
contentPolicyType);
|
||||
|
||||
// snapshot the nonce at load start time for performing CSP checks
|
||||
if (contentPolicyType == nsIContentPolicy::TYPE_INTERNAL_SCRIPT) {
|
||||
nsCOMPtr<Element> element = do_QueryInterface(aContext);
|
||||
if (element && element->IsHTMLElement()) {
|
||||
nsAutoString cspNonce;
|
||||
element->GetAttribute(NS_LITERAL_STRING("nonce"), cspNonce);
|
||||
secCheckLoadInfo->SetCspNonce(cspNonce);
|
||||
}
|
||||
}
|
||||
|
||||
int16_t shouldLoad = nsIContentPolicy::ACCEPT;
|
||||
nsresult rv = NS_CheckContentLoadPolicy(
|
||||
aRequest->mURI, secCheckLoadInfo, NS_LossyConvertUTF16toASCII(aType),
|
||||
|
@ -1252,6 +1262,17 @@ nsresult ScriptLoader::StartLoad(ScriptLoadRequest* aRequest) {
|
|||
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// snapshot the nonce at load start time for performing CSP checks
|
||||
if (contentPolicyType == nsIContentPolicy::TYPE_INTERNAL_SCRIPT) {
|
||||
nsCOMPtr<Element> element = do_QueryInterface(context);
|
||||
if (element && element->IsHTMLElement()) {
|
||||
nsAutoString cspNonce;
|
||||
element->GetAttribute(NS_LITERAL_STRING("nonce"), cspNonce);
|
||||
nsCOMPtr<nsILoadInfo> loadInfo = channel->GetLoadInfo();
|
||||
loadInfo->SetCspNonce(cspNonce);
|
||||
}
|
||||
}
|
||||
|
||||
// To avoid decoding issues, the build-id is part of the JSBytecodeMimeType
|
||||
// constant.
|
||||
aRequest->mCacheInfo = nullptr;
|
||||
|
|
|
@ -121,7 +121,8 @@ nsCSPContext::ShouldLoad(nsContentPolicyType aContentType,
|
|||
nsISupports* aRequestContext,
|
||||
const nsACString& aMimeTypeGuess,
|
||||
nsIURI* aOriginalURIIfRedirect,
|
||||
bool aSendViolationReports, int16_t* outDecision) {
|
||||
bool aSendViolationReports, const nsAString& aNonce,
|
||||
int16_t* outDecision) {
|
||||
if (CSPCONTEXTLOGENABLED()) {
|
||||
CSPCONTEXTLOG(("nsCSPContext::ShouldLoad, aContentLocation: %s",
|
||||
aContentLocation->GetSpecOrDefault().get()));
|
||||
|
@ -155,18 +156,8 @@ nsCSPContext::ShouldLoad(nsContentPolicyType aContentType,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsAutoString nonce;
|
||||
bool parserCreated = false;
|
||||
if (!isPreload) {
|
||||
if (aContentType == nsIContentPolicy::TYPE_SCRIPT ||
|
||||
aContentType == nsIContentPolicy::TYPE_STYLESHEET) {
|
||||
nsCOMPtr<Element> element = do_QueryInterface(aRequestContext);
|
||||
if (element && element->IsHTMLElement()) {
|
||||
// XXXbz What about SVG elements that can have nonce?
|
||||
element->GetAttribute(NS_LITERAL_STRING("nonce"), nonce);
|
||||
}
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIScriptElement> script = do_QueryInterface(aRequestContext);
|
||||
if (script && script->GetParserCreated() != mozilla::dom::NOT_FROM_PARSER) {
|
||||
parserCreated = true;
|
||||
|
@ -177,7 +168,7 @@ nsCSPContext::ShouldLoad(nsContentPolicyType aContentType,
|
|||
permitsInternal(dir,
|
||||
nullptr, // aTriggeringElement
|
||||
aCSPEventListener, aContentLocation,
|
||||
aOriginalURIIfRedirect, nonce, isPreload,
|
||||
aOriginalURIIfRedirect, aNonce, isPreload,
|
||||
false, // allow fallback to default-src
|
||||
aSendViolationReports,
|
||||
true, // send blocked URI in violation reports
|
||||
|
|
|
@ -172,6 +172,10 @@ CSPService::ShouldLoad(nsIURI *aContentLocation, nsILoadInfo *aLoadInfo,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsAutoString cspNonce;
|
||||
rv = aLoadInfo->GetCspNonce(cspNonce);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// 1) Apply speculate CSP for preloads
|
||||
bool isPreload = nsContentUtils::IsPreloadType(contentType);
|
||||
|
||||
|
@ -186,7 +190,7 @@ CSPService::ShouldLoad(nsIURI *aContentLocation, nsILoadInfo *aLoadInfo,
|
|||
contentType, cspEventListener, aContentLocation, requestOrigin,
|
||||
requestContext, aMimeTypeGuess,
|
||||
nullptr, // no redirect, aOriginal URL is null.
|
||||
aLoadInfo->GetSendCSPViolationEvents(), aDecision);
|
||||
aLoadInfo->GetSendCSPViolationEvents(), cspNonce, aDecision);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// if the preload policy already denied the load, then there
|
||||
|
@ -207,7 +211,8 @@ CSPService::ShouldLoad(nsIURI *aContentLocation, nsILoadInfo *aLoadInfo,
|
|||
rv = csp->ShouldLoad(contentType, cspEventListener, aContentLocation,
|
||||
requestOrigin, requestContext, aMimeTypeGuess,
|
||||
nullptr, // no redirect, aOriginal URL is null.
|
||||
aLoadInfo->GetSendCSPViolationEvents(), aDecision);
|
||||
aLoadInfo->GetSendCSPViolationEvents(), cspNonce,
|
||||
aDecision);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
return NS_OK;
|
||||
|
@ -251,17 +256,6 @@ CSPService::AsyncOnChannelRedirect(nsIChannel *oldChannel,
|
|||
nsIAsyncVerifyRedirectCallback *callback) {
|
||||
net::nsAsyncRedirectAutoCallback autoCallback(callback);
|
||||
|
||||
if (XRE_IsE10sParentProcess()) {
|
||||
nsCOMPtr<nsIParentChannel> parentChannel;
|
||||
NS_QueryNotificationCallbacks(oldChannel, parentChannel);
|
||||
if (parentChannel) {
|
||||
// This is an IPC'd channel. Don't check it here, because we won't have
|
||||
// access to the request context; we'll check them in the content
|
||||
// process instead. Bug 1509738 covers fixing this.
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIURI> newUri;
|
||||
nsresult rv = newChannel->GetURI(getter_AddRefs(newUri));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
@ -303,6 +297,10 @@ CSPService::AsyncOnChannelRedirect(nsIChannel *oldChannel,
|
|||
return rv;
|
||||
}
|
||||
|
||||
nsAutoString cspNonce;
|
||||
rv = loadInfo->GetCspNonce(cspNonce);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
bool isPreload = nsContentUtils::IsPreloadType(policyType);
|
||||
|
||||
/* On redirect, if the content policy is a preload type, rejecting the preload
|
||||
|
@ -330,6 +328,7 @@ CSPService::AsyncOnChannelRedirect(nsIChannel *oldChannel,
|
|||
EmptyCString(), // ACString - MIME guess
|
||||
originalUri, // Original nsIURI
|
||||
true, // aSendViolationReports
|
||||
cspNonce, // nonce
|
||||
&aDecision);
|
||||
|
||||
// if the preload policy already denied the load, then there
|
||||
|
@ -356,6 +355,7 @@ CSPService::AsyncOnChannelRedirect(nsIChannel *oldChannel,
|
|||
EmptyCString(), // ACString - MIME guess
|
||||
originalUri, // Original nsIURI
|
||||
true, // aSendViolationReports
|
||||
cspNonce, // nonce
|
||||
&aDecision);
|
||||
}
|
||||
|
||||
|
|
|
@ -153,7 +153,7 @@ function run_test() {
|
|||
csp.shouldLoad(Ci.nsIContentPolicy.TYPE_SCRIPT,
|
||||
null, // nsICSPEventListener
|
||||
NetUtil.newURI("http://blocked.test/foo.js"),
|
||||
null, null, null, null, true);
|
||||
null, null, null, null, true, null);
|
||||
});
|
||||
|
||||
// test that inline script violations cause a report in report-only policy
|
||||
|
@ -206,7 +206,7 @@ function run_test() {
|
|||
csp.shouldLoad(Ci.nsIContentPolicy.TYPE_IMAGE,
|
||||
null, // nsICSPEventListener
|
||||
NetUtil.newURI("data:image/png;base64," + base64data),
|
||||
null, null, null, null, true);
|
||||
null, null, null, null, true, null);
|
||||
});
|
||||
|
||||
// test that only the uri's scheme is reported for globally unique identifiers
|
||||
|
@ -216,7 +216,7 @@ function run_test() {
|
|||
csp.shouldLoad(Ci.nsIContentPolicy.TYPE_SUBDOCUMENT,
|
||||
null, // nsICSPEventListener
|
||||
NetUtil.newURI("intent://mymaps.com/maps?um=1&ie=UTF-8&fb=1&sll"),
|
||||
null, null, null, null, true);
|
||||
null, null, null, null, true, null);
|
||||
});
|
||||
|
||||
// test fragment removal
|
||||
|
@ -227,7 +227,7 @@ function run_test() {
|
|||
csp.shouldLoad(Ci.nsIContentPolicy.TYPE_SCRIPT,
|
||||
null, // nsICSPEventListener
|
||||
NetUtil.newURI(selfSpec + "#bar"),
|
||||
null, null, null, null, true);
|
||||
null, null, null, null, true, null);
|
||||
});
|
||||
|
||||
// test scheme of ftp:
|
||||
|
@ -237,6 +237,6 @@ function run_test() {
|
|||
csp.shouldLoad(Ci.nsIContentPolicy.TYPE_SCRIPT,
|
||||
null, // nsICSPEventListener
|
||||
NetUtil.newURI("ftp://blocked.test/profile.png"),
|
||||
null, null, null, null, true);
|
||||
null, null, null, null, true, null);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -457,6 +457,9 @@ nsresult LoadInfoToLoadInfoArgs(nsILoadInfo* aLoadInfo,
|
|||
ipcController = controller.ref().ToIPC();
|
||||
}
|
||||
|
||||
nsAutoString cspNonce;
|
||||
Unused << NS_WARN_IF(NS_FAILED(aLoadInfo->GetCspNonce(cspNonce)));
|
||||
|
||||
*aOptionalLoadInfoArgs = LoadInfoArgs(
|
||||
loadingPrincipalInfo, triggeringPrincipalInfo, principalToInheritInfo,
|
||||
sandboxedLoadingPrincipalInfo, topLevelPrincipalInfo,
|
||||
|
@ -484,7 +487,7 @@ nsresult LoadInfoToLoadInfoArgs(nsILoadInfo* aLoadInfo,
|
|||
aLoadInfo->GetIsPreflight(), aLoadInfo->GetLoadTriggeredFromExternal(),
|
||||
aLoadInfo->GetServiceWorkerTaintingSynthesized(),
|
||||
aLoadInfo->GetDocumentHasUserInteracted(),
|
||||
aLoadInfo->GetDocumentHasLoaded(),
|
||||
aLoadInfo->GetDocumentHasLoaded(), cspNonce,
|
||||
aLoadInfo->GetIsFromProcessingFrameAttributes());
|
||||
|
||||
return NS_OK;
|
||||
|
@ -640,7 +643,7 @@ nsresult LoadInfoArgsToLoadInfo(
|
|||
loadInfoArgs.isPreflight(), loadInfoArgs.loadTriggeredFromExternal(),
|
||||
loadInfoArgs.serviceWorkerTaintingSynthesized(),
|
||||
loadInfoArgs.documentHasUserInteracted(),
|
||||
loadInfoArgs.documentHasLoaded());
|
||||
loadInfoArgs.documentHasLoaded(), loadInfoArgs.cspNonce());
|
||||
|
||||
if (loadInfoArgs.isFromProcessingFrameAttributes()) {
|
||||
loadInfo->SetIsFromProcessingFrameAttributes();
|
||||
|
|
|
@ -858,6 +858,16 @@ nsresult Loader::CheckContentPolicy(nsIPrincipal* aLoadingPrincipal,
|
|||
aLoadingPrincipal, aTriggeringPrincipal, aRequestingNode,
|
||||
nsILoadInfo::SEC_ONLY_FOR_EXPLICIT_CONTENTSEC_CHECK, contentPolicyType);
|
||||
|
||||
// snapshot the nonce at load start time for performing CSP checks
|
||||
if (contentPolicyType == nsIContentPolicy::TYPE_INTERNAL_STYLESHEET) {
|
||||
nsCOMPtr<Element> element = do_QueryInterface(aRequestingNode);
|
||||
if (element && element->IsHTMLElement()) {
|
||||
nsAutoString cspNonce;
|
||||
element->GetAttribute(NS_LITERAL_STRING("nonce"), cspNonce);
|
||||
secCheckLoadInfo->SetCspNonce(cspNonce);
|
||||
}
|
||||
}
|
||||
|
||||
int16_t shouldLoad = nsIContentPolicy::ACCEPT;
|
||||
nsresult rv = NS_CheckContentLoadPolicy(
|
||||
aTargetURI, secCheckLoadInfo, NS_LITERAL_CSTRING("text/css"), &shouldLoad,
|
||||
|
@ -1310,6 +1320,18 @@ nsresult Loader::LoadSheet(SheetLoadData* aLoadData,
|
|||
return rv;
|
||||
}
|
||||
|
||||
// snapshot the nonce at load start time for performing CSP checks
|
||||
if (contentPolicyType == nsIContentPolicy::TYPE_INTERNAL_STYLESHEET) {
|
||||
nsCOMPtr<Element> element =
|
||||
do_QueryInterface(aLoadData->mRequestingNode);
|
||||
if (element && element->IsHTMLElement()) {
|
||||
nsAutoString cspNonce;
|
||||
element->GetAttribute(NS_LITERAL_STRING("nonce"), cspNonce);
|
||||
nsCOMPtr<nsILoadInfo> loadInfo = channel->GetLoadInfo();
|
||||
loadInfo->SetCspNonce(cspNonce);
|
||||
}
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIInputStream> stream;
|
||||
rv = channel->Open(getter_AddRefs(stream));
|
||||
|
||||
|
@ -1438,6 +1460,17 @@ nsresult Loader::LoadSheet(SheetLoadData* aLoadData,
|
|||
return rv;
|
||||
}
|
||||
|
||||
// snapshot the nonce at load start time for performing CSP checks
|
||||
if (contentPolicyType == nsIContentPolicy::TYPE_INTERNAL_STYLESHEET) {
|
||||
nsCOMPtr<Element> element = do_QueryInterface(aLoadData->mRequestingNode);
|
||||
if (element && element->IsHTMLElement()) {
|
||||
nsAutoString cspNonce;
|
||||
element->GetAttribute(NS_LITERAL_STRING("nonce"), cspNonce);
|
||||
nsCOMPtr<nsILoadInfo> loadInfo = channel->GetLoadInfo();
|
||||
loadInfo->SetCspNonce(cspNonce);
|
||||
}
|
||||
}
|
||||
|
||||
if (!aLoadData->ShouldDefer()) {
|
||||
nsCOMPtr<nsIClassOfService> cos(do_QueryInterface(channel));
|
||||
if (cos) {
|
||||
|
|
|
@ -478,6 +478,7 @@ LoadInfo::LoadInfo(const LoadInfo& rhs)
|
|||
mServiceWorkerTaintingSynthesized(false),
|
||||
mDocumentHasUserInteracted(rhs.mDocumentHasUserInteracted),
|
||||
mDocumentHasLoaded(rhs.mDocumentHasLoaded),
|
||||
mCspNonce(rhs.mCspNonce),
|
||||
mIsFromProcessingFrameAttributes(rhs.mIsFromProcessingFrameAttributes) {}
|
||||
|
||||
LoadInfo::LoadInfo(
|
||||
|
@ -510,7 +511,7 @@ LoadInfo::LoadInfo(
|
|||
const nsTArray<nsCString>& aCorsUnsafeHeaders, bool aForcePreflight,
|
||||
bool aIsPreflight, bool aLoadTriggeredFromExternal,
|
||||
bool aServiceWorkerTaintingSynthesized, bool aDocumentHasUserInteracted,
|
||||
bool aDocumentHasLoaded)
|
||||
bool aDocumentHasLoaded, const nsAString& aCspNonce)
|
||||
: mLoadingPrincipal(aLoadingPrincipal),
|
||||
mTriggeringPrincipal(aTriggeringPrincipal),
|
||||
mPrincipalToInherit(aPrincipalToInherit),
|
||||
|
@ -556,6 +557,7 @@ LoadInfo::LoadInfo(
|
|||
mServiceWorkerTaintingSynthesized(aServiceWorkerTaintingSynthesized),
|
||||
mDocumentHasUserInteracted(aDocumentHasUserInteracted),
|
||||
mDocumentHasLoaded(aDocumentHasLoaded),
|
||||
mCspNonce(aCspNonce),
|
||||
mIsFromProcessingFrameAttributes(false) {
|
||||
// Only top level TYPE_DOCUMENT loads can have a null loadingPrincipal
|
||||
MOZ_ASSERT(mLoadingPrincipal ||
|
||||
|
@ -1254,6 +1256,20 @@ LoadInfo::SetDocumentHasLoaded(bool aDocumentHasLoaded) {
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
LoadInfo::GetCspNonce(nsAString& aCspNonce) {
|
||||
aCspNonce = mCspNonce;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
LoadInfo::SetCspNonce(const nsAString& aCspNonce) {
|
||||
MOZ_ASSERT(!mInitialSecurityCheckDone,
|
||||
"setting the nonce is only allowed before any sec checks");
|
||||
mCspNonce = aCspNonce;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
LoadInfo::GetIsTopLevelLoad(bool* aResult) {
|
||||
*aResult = mFrameOuterWindowID ? mFrameOuterWindowID == mOuterWindowID
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "nsIPrincipal.h"
|
||||
#include "nsIWeakReferenceUtils.h" // for nsWeakPtr
|
||||
#include "nsIURI.h"
|
||||
#include "nsString.h"
|
||||
#include "nsTArray.h"
|
||||
|
||||
#include "mozilla/BasePrincipal.h"
|
||||
|
@ -121,7 +122,8 @@ class LoadInfo final : public nsILoadInfo {
|
|||
const nsTArray<nsCString>& aUnsafeHeaders, bool aForcePreflight,
|
||||
bool aIsPreflight, bool aLoadTriggeredFromExternal,
|
||||
bool aServiceWorkerTaintingSynthesized,
|
||||
bool aDocumentHasUserInteracted, bool aDocumentHasLoaded);
|
||||
bool aDocumentHasUserInteracted, bool aDocumentHasLoaded,
|
||||
const nsAString& aCspNonce);
|
||||
LoadInfo(const LoadInfo& rhs);
|
||||
|
||||
NS_IMETHOD GetRedirects(JSContext* aCx,
|
||||
|
@ -198,6 +200,7 @@ class LoadInfo final : public nsILoadInfo {
|
|||
bool mServiceWorkerTaintingSynthesized;
|
||||
bool mDocumentHasUserInteracted;
|
||||
bool mDocumentHasLoaded;
|
||||
nsString mCspNonce;
|
||||
|
||||
// Is true if this load was triggered by processing the attributes of the
|
||||
// browsing context container.
|
||||
|
|
|
@ -1047,6 +1047,14 @@ interface nsILoadInfo : nsISupports
|
|||
*/
|
||||
[infallible] attribute boolean documentHasLoaded;
|
||||
|
||||
/**
|
||||
* A snapshot of the nonce at load start time which is used for CSP
|
||||
* checks and only set for:
|
||||
* * TYPE_SCRIPT and
|
||||
* * TYPE_STYLESHEET
|
||||
*/
|
||||
attribute AString cspNonce;
|
||||
|
||||
/**
|
||||
* The object in charged to receive CSP violation events. It can be null.
|
||||
* This attribute will be merged into the CSP object eventually.
|
||||
|
|
|
@ -109,6 +109,7 @@ struct LoadInfoArgs
|
|||
bool serviceWorkerTaintingSynthesized;
|
||||
bool documentHasUserInteracted;
|
||||
bool documentHasLoaded;
|
||||
nsString cspNonce;
|
||||
bool isFromProcessingFrameAttributes;
|
||||
};
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче