diff --git a/devtools/shared/layout/utils.js b/devtools/shared/layout/utils.js index ebd2353414d1..804290654a2c 100644 --- a/devtools/shared/layout/utils.js +++ b/devtools/shared/layout/utils.js @@ -915,10 +915,11 @@ function isFrameBlockedByCSP(node) { const res = node.ownerDocument.csp.shouldLoad( Ci.nsIContentPolicy.TYPE_SUBDOCUMENT, null, // nsICSPEventListener - null, // nsILoadInfo uri, null, // aOriginalURIIfRedirect - false // aSendViolationReports + false, // aSendViolationReports + null, // aNonce + false // aParserCreated ); return res !== Ci.nsIContentPolicy.ACCEPT; diff --git a/dom/interfaces/security/nsIContentSecurityPolicy.idl b/dom/interfaces/security/nsIContentSecurityPolicy.idl index 827849b77b77..bf691ed215c6 100644 --- a/dom/interfaces/security/nsIContentSecurityPolicy.idl +++ b/dom/interfaces/security/nsIContentSecurityPolicy.idl @@ -344,10 +344,11 @@ interface nsIContentSecurityPolicy : nsISerializable */ short shouldLoad(in nsContentPolicyType aContentType, in nsICSPEventListener aCSPEventListener, - in nsILoadInfo aLoadInfo, in nsIURI aContentLocation, in nsIURI aOriginalURIIfRedirect, - in bool aSendViolationReports); + in bool aSendViolationReports, + in AString aNonce, + in boolean aParserCreated); %{ C++ // nsIObserver topic to fire when the policy encounters a violation. diff --git a/dom/script/ScriptLoader.cpp b/dom/script/ScriptLoader.cpp index 47d9575b15ee..c1702e453ddb 100644 --- a/dom/script/ScriptLoader.cpp +++ b/dom/script/ScriptLoader.cpp @@ -407,9 +407,6 @@ nsresult ScriptLoader::CheckContentPolicy(Document* aDocument, requestingNode, nsILoadInfo::SEC_ONLY_FOR_EXPLICIT_CONTENTSEC_CHECK, contentPolicyType); - secCheckLoadInfo->SetIntegrityMetadata( - aRequest->mIntegrity.GetIntegrityString()); - // snapshot the nonce at load start time for performing CSP checks if (contentPolicyType == nsIContentPolicy::TYPE_INTERNAL_SCRIPT || contentPolicyType == nsIContentPolicy::TYPE_INTERNAL_MODULE) { @@ -626,9 +623,6 @@ nsresult ScriptLoader::StartLoadInternal( NS_ENSURE_SUCCESS(rv, rv); } - nsCOMPtr loadInfo = channel->LoadInfo(); - loadInfo->SetIntegrityMetadata(aRequest->mIntegrity.GetIntegrityString()); - // snapshot the nonce at load start time for performing CSP checks if (contentPolicyType == nsIContentPolicy::TYPE_INTERNAL_SCRIPT || contentPolicyType == nsIContentPolicy::TYPE_INTERNAL_MODULE) { @@ -636,6 +630,7 @@ nsresult ScriptLoader::StartLoadInternal( nsString* cspNonce = static_cast(context->GetProperty(nsGkAtoms::nonce)); if (cspNonce) { + nsCOMPtr loadInfo = channel->LoadInfo(); loadInfo->SetCspNonce(*cspNonce); } } diff --git a/dom/security/nsCSPContext.cpp b/dom/security/nsCSPContext.cpp index d624083ab246..8bed4cbad0f3 100644 --- a/dom/security/nsCSPContext.cpp +++ b/dom/security/nsCSPContext.cpp @@ -130,9 +130,10 @@ static void BlockedContentSourceToString( NS_IMETHODIMP nsCSPContext::ShouldLoad(nsContentPolicyType aContentType, nsICSPEventListener* aCSPEventListener, - nsILoadInfo* aLoadInfo, nsIURI* aContentLocation, + nsIURI* aContentLocation, nsIURI* aOriginalURIIfRedirect, - bool aSendViolationReports, int16_t* outDecision) { + bool aSendViolationReports, const nsAString& aNonce, + bool aParserCreated, int16_t* outDecision) { if (CSPCONTEXTLOGENABLED()) { CSPCONTEXTLOG(("nsCSPContext::ShouldLoad, aContentLocation: %s", aContentLocation->GetSpecOrDefault().get())); @@ -161,10 +162,11 @@ nsCSPContext::ShouldLoad(nsContentPolicyType aContentType, bool permitted = permitsInternal( dir, nullptr, // aTriggeringElement - aCSPEventListener, aLoadInfo, aContentLocation, aOriginalURIIfRedirect, + aCSPEventListener, aContentLocation, aOriginalURIIfRedirect, aNonce, false, // allow fallback to default-src aSendViolationReports, - true); // send blocked URI in violation reports + true, // send blocked URI in violation reports + aParserCreated); *outDecision = permitted ? nsIContentPolicy::ACCEPT : nsIContentPolicy::REJECT_SERVER; @@ -181,17 +183,18 @@ nsCSPContext::ShouldLoad(nsContentPolicyType aContentType, bool nsCSPContext::permitsInternal( CSPDirective aDir, Element* aTriggeringElement, - nsICSPEventListener* aCSPEventListener, nsILoadInfo* aLoadInfo, - nsIURI* aContentLocation, nsIURI* aOriginalURIIfRedirect, bool aSpecific, - bool aSendViolationReports, bool aSendContentLocationInViolationReports) { + nsICSPEventListener* aCSPEventListener, nsIURI* aContentLocation, + nsIURI* aOriginalURIIfRedirect, const nsAString& aNonce, bool aSpecific, + bool aSendViolationReports, bool aSendContentLocationInViolationReports, + bool aParserCreated) { EnsureIPCPoliciesRead(); bool permits = true; nsAutoString violatedDirective; for (uint32_t p = 0; p < mPolicies.Length(); p++) { - if (!mPolicies[p]->permits(aDir, aLoadInfo, aContentLocation, + if (!mPolicies[p]->permits(aDir, aContentLocation, aNonce, !!aOriginalURIIfRedirect, aSpecific, - violatedDirective)) { + aParserCreated, violatedDirective)) { // If the policy is violated and not report-only, reject the load and // report to the console if (!mPolicies[p]->getReportOnlyFlag()) { @@ -1687,12 +1690,13 @@ nsCSPContext::PermitsAncestry(nsILoadInfo* aLoadInfo, permitsInternal(nsIContentSecurityPolicy::FRAME_ANCESTORS_DIRECTIVE, nullptr, // triggering element nullptr, // nsICSPEventListener - nullptr, // nsILoadInfo ancestorsArray[a], nullptr, // no redirect here. + u""_ns, // no nonce true, // specific, do not use default-src true, // send violation reports - okToSendAncestor); + okToSendAncestor, + false); // not parser created if (!permits) { *outPermitsAncestry = false; } @@ -1722,12 +1726,13 @@ nsCSPContext::Permits(Element* aTriggeringElement, } } - *outPermits = permitsInternal(aDir, aTriggeringElement, aCSPEventListener, - nullptr, // no nsILoadInfo - aURI, - nullptr, // no original (pre-redirect) URI - aSpecific, aSendViolationReports, - true); // send blocked URI in violation reports + *outPermits = + permitsInternal(aDir, aTriggeringElement, aCSPEventListener, aURI, + nullptr, // no original (pre-redirect) URI + u""_ns, // no nonce + aSpecific, aSendViolationReports, + true, // send blocked URI in violation reports + false); // not parser created if (CSPCONTEXTLOGENABLED()) { CSPCONTEXTLOG(("nsCSPContext::Permits, aUri: %s, aDir: %s, isAllowed: %s", diff --git a/dom/security/nsCSPContext.h b/dom/security/nsCSPContext.h index 97c01385d66f..85d286f90165 100644 --- a/dom/security/nsCSPContext.h +++ b/dom/security/nsCSPContext.h @@ -154,10 +154,11 @@ class nsCSPContext : public nsIContentSecurityPolicy { bool permitsInternal(CSPDirective aDir, mozilla::dom::Element* aTriggeringElement, nsICSPEventListener* aCSPEventListener, - nsILoadInfo* aLoadInfo, nsIURI* aContentLocation, - nsIURI* aOriginalURIIfRedirect, bool aSpecific, + nsIURI* aContentLocation, nsIURI* aOriginalURIIfRedirect, + const nsAString& aNonce, bool aSpecific, bool aSendViolationReports, - bool aSendContentLocationInViolationReports); + bool aSendContentLocationInViolationReports, + bool aParserCreated); // helper to report inline script/style violations void reportInlineViolation(CSPDirective aDirective, diff --git a/dom/security/nsCSPService.cpp b/dom/security/nsCSPService.cpp index c7c58a37dc01..c5c65ad4d200 100644 --- a/dom/security/nsCSPService.cpp +++ b/dom/security/nsCSPService.cpp @@ -111,6 +111,7 @@ bool subjectToCSP(nsIURI* aURI, nsContentPolicyType aContentType) { } nsContentPolicyType contentType = aLoadInfo->InternalContentPolicyType(); + bool parserCreatedScript = aLoadInfo->GetParserCreatedScript(); nsCOMPtr cspEventListener; nsresult rv = @@ -135,6 +136,10 @@ bool subjectToCSP(nsIURI* aURI, nsContentPolicyType aContentType) { 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); @@ -143,9 +148,9 @@ bool subjectToCSP(nsIURI* aURI, nsContentPolicyType aContentType) { if (preloadCsp) { // obtain the enforcement decision rv = preloadCsp->ShouldLoad( - contentType, cspEventListener, aLoadInfo, aContentLocation, + contentType, cspEventListener, aContentLocation, nullptr, // no redirect, aOriginal URL is null. - false, aDecision); + false, cspNonce, parserCreatedScript, aDecision); NS_ENSURE_SUCCESS(rv, rv); // if the preload policy already denied the load, then there @@ -187,9 +192,10 @@ bool subjectToCSP(nsIURI* aURI, nsContentPolicyType aContentType) { // obtain the enforcement decision rv = csp->ShouldLoad( - contentType, cspEventListener, aLoadInfo, aContentLocation, + contentType, cspEventListener, aContentLocation, originalURI, // no redirect, unless it's a frame navigation. - !isPreload && aLoadInfo->GetSendCSPViolationEvents(), aDecision); + !isPreload && aLoadInfo->GetSendCSPViolationEvents(), cspNonce, + parserCreatedScript, aDecision); if (NS_CP_REJECTED(*aDecision)) { NS_SetRequestBlockingReason( @@ -344,6 +350,10 @@ nsresult CSPService::ConsultCSPForRedirect(nsIURI* aOriginalURI, aLoadInfo->GetCspEventListener(getter_AddRefs(cspEventListener)); MOZ_ALWAYS_SUCCEEDS(rv); + nsAutoString cspNonce; + rv = aLoadInfo->GetCspNonce(cspNonce); + MOZ_ALWAYS_SUCCEEDS(rv); + bool isPreload = nsContentUtils::IsPreloadType(policyType); /* On redirect, if the content policy is a preload type, rejecting the @@ -352,6 +362,7 @@ nsresult CSPService::ConsultCSPForRedirect(nsIURI* aOriginalURI, */ int16_t decision = nsIContentPolicy::ACCEPT; + bool parserCreatedScript = aLoadInfo->GetParserCreatedScript(); // 1) Apply speculative CSP for preloads if (isPreload) { @@ -360,11 +371,12 @@ nsresult CSPService::ConsultCSPForRedirect(nsIURI* aOriginalURI, // Pass originalURI to indicate the redirect preloadCsp->ShouldLoad( policyType, // load type per nsIContentPolicy (uint32_t) - cspEventListener, aLoadInfo, + cspEventListener, aNewURI, // nsIURI aOriginalURI, // Original nsIURI true, // aSendViolationReports - &decision); + cspNonce, // nonce + parserCreatedScript, &decision); // if the preload policy already denied the load, then there // is no point in checking the real policy @@ -380,11 +392,12 @@ nsresult CSPService::ConsultCSPForRedirect(nsIURI* aOriginalURI, if (csp) { // Pass originalURI to indicate the redirect csp->ShouldLoad(policyType, // load type per nsIContentPolicy (uint32_t) - cspEventListener, aLoadInfo, + cspEventListener, aNewURI, // nsIURI aOriginalURI, // Original nsIURI true, // aSendViolationReports - &decision); + cspNonce, // nonce + parserCreatedScript, &decision); if (NS_CP_REJECTED(decision)) { aCancelCode = Some(NS_ERROR_DOM_BAD_URI); return NS_BINDING_FAILED; diff --git a/dom/security/nsCSPUtils.cpp b/dom/security/nsCSPUtils.cpp index 90d6e00254f3..e52802d367e2 100644 --- a/dom/security/nsCSPUtils.cpp +++ b/dom/security/nsCSPUtils.cpp @@ -21,16 +21,12 @@ #include "nsReadableUtils.h" #include "nsSandboxFlags.h" #include "nsServiceManagerUtils.h" -#include "nsWhitespaceTokenizer.h" #include "mozilla/Components.h" #include "mozilla/dom/CSPDictionariesBinding.h" #include "mozilla/dom/Document.h" -#include "mozilla/dom/SRIMetadata.h" #include "mozilla/StaticPrefs_security.h" -using mozilla::dom::SRIMetadata; - #define DEFAULT_PORT -1 static mozilla::LogModule* GetCspUtilsLog() { @@ -1080,151 +1076,14 @@ nsCSPDirective::~nsCSPDirective() { } } -// This check only considers types "script-like" -// (https://fetch.spec.whatwg.org/#request-destination-script-like) that can -// also have integrity metadata. -static bool IsScriptLikeWithIntegrity(nsContentPolicyType aType) { - switch (aType) { - case nsIContentPolicy::TYPE_SCRIPT: - case nsIContentPolicy::TYPE_INTERNAL_SCRIPT: - case nsIContentPolicy::TYPE_INTERNAL_SCRIPT_PRELOAD: - case nsIContentPolicy::TYPE_INTERNAL_MODULE: - case nsIContentPolicy::TYPE_INTERNAL_MODULE_PRELOAD: - return true; - default: - return false; - } -} - -// https://www.w3.org/TR/SRI/#parse-metadata -// This function is similar to SRICheck::IntegrityMetadata, but also keeps -// SRI metadata with weaker hashes. -// CSP treats "no metadata" and empty results the same way. -static nsTArray ParseSRIMetadata(const nsAString& aMetadata) { - // Step 1. Let result be the empty set. - // Step 2. Let empty be equal to true. - nsTArray result; - - NS_ConvertUTF16toUTF8 metadataList(aMetadata); - nsAutoCString token; - - // Step 3. For each token returned by splitting metadata on spaces: - nsCWhitespaceTokenizer tokenizer(metadataList); - while (tokenizer.hasMoreTokens()) { - token = tokenizer.nextToken(); - // Step 3.1. Set empty to false. - // Step 3.3. Parse token per the grammar in integrity metadata. - SRIMetadata metadata(token); - // Step 3.2. If token is not a valid metadata, skip the remaining steps, and - // proceed to the next token. - if (metadata.IsMalformed()) { - continue; - } - - // Step 3.4. Let algorithm be the alg component of token. - // Step 3.5. If algorithm is a hash function recognized by the user agent, - // add the - // parsed token to result. - if (metadata.IsAlgorithmSupported()) { - result.AppendElement(metadata); - } - } - - // Step 4. Return no metadata if empty is true, otherwise return result. - return result; -} - -bool nsCSPDirective::permits(CSPDirective aDirective, nsILoadInfo* aLoadInfo, - nsIURI* aUri, const nsAString& aNonce, +bool nsCSPDirective::permits(nsIURI* aUri, const nsAString& aNonce, bool aWasRedirected, bool aReportOnly, bool aUpgradeInsecure, bool aParserCreated) const { - MOZ_ASSERT(equals(aDirective) || isDefaultDirective()); - if (CSPUTILSLOGENABLED()) { CSPUTILSLOG( ("nsCSPDirective::permits, aUri: %s", aUri->GetSpecOrDefault().get())); } - // https://w3c.github.io/webappsec-csp/#script-pre-request - if (aLoadInfo) { - // Step 1. If request’s destination is script-like: - if (IsScriptLikeWithIntegrity(aLoadInfo->InternalContentPolicyType())) { - MOZ_ASSERT(aDirective == CSPDirective::SCRIPT_SRC_ELEM_DIRECTIVE); - - // Step 1.2. Let integrity expressions be the set of source expressions in - // directive’s value that match the hash-source grammar. - nsTArray integrityExpressions; - for (uint32_t i = 0; i < mSrcs.Length(); i++) { - if (mSrcs[i]->isHash()) { - integrityExpressions.AppendElement( - static_cast(mSrcs[i])); - } - } - - // Step 1.3. If integrity expressions is not empty: - if (!integrityExpressions.IsEmpty()) { - // Step 1.3.1. Let integrity sources be the result of executing the - // algorithm defined in [SRI 3.3.3 Parse metadata] on request’s - // integrity metadata. - nsAutoString integrityMetadata; - aLoadInfo->GetIntegrityMetadata(integrityMetadata); - nsTArray integritySources = - ParseSRIMetadata(integrityMetadata); - - // Step 1.3.2. If integrity sources is "no metadata" or an empty set, - // skip the remaining substeps. - if (!integritySources.IsEmpty()) { - // Step 1.3.3. Let bypass due to integrity match be true. - bool bypass = true; - - nsAutoCString sourceAlgorithmUTF8; - nsAutoCString sourceHashUTF8; - nsAutoString sourceAlgorithm; - nsAutoString sourceHash; - nsAutoString algorithm; - nsAutoString hash; - - // Step 1.3.4. For each source of integrity sources: - for (const SRIMetadata& source : integritySources) { - source.GetAlgorithm(&sourceAlgorithmUTF8); - sourceAlgorithm = NS_ConvertUTF8toUTF16(sourceAlgorithmUTF8); - source.GetHash(0, &sourceHashUTF8); - sourceHash = NS_ConvertUTF8toUTF16(sourceHashUTF8); - - // Step 1.3.4.1 If directive’s value does not contain a source - // expression whose hash-algorithm is an ASCII case-insensitive - // match for source’s hash-algorithm, and whose base64-value is - // identical to source’s base64-value, then set bypass due to - // integrity match to false. - bool found = false; - for (const nsCSPHashSrc* hashSrc : integrityExpressions) { - hashSrc->getAlgorithm(algorithm); - hashSrc->getHash(hash); - - // The nsCSPHashSrc constructor lowercases algorithm, so this - // is case-insensitive. - if (sourceAlgorithm == algorithm && sourceHash == hash) { - found = true; - break; - } - } - - if (!found) { - bypass = false; - break; - } - } - - // Step 1.3.5. If bypass due to integrity match is true, return - // "Allowed". - if (bypass) { - return true; - } - } - } - } - } - for (uint32_t i = 0; i < mSrcs.Length(); i++) { if (mSrcs[i]->permits(aUri, aNonce, aWasRedirected, aReportOnly, aUpgradeInsecure, aParserCreated)) { @@ -1540,8 +1399,9 @@ nsCSPPolicy::~nsCSPPolicy() { } } -bool nsCSPPolicy::permits(CSPDirective aDir, nsILoadInfo* aLoadInfo, - nsIURI* aUri, bool aWasRedirected, bool aSpecific, +bool nsCSPPolicy::permits(CSPDirective aDir, nsIURI* aUri, + const nsAString& aNonce, bool aWasRedirected, + bool aSpecific, bool aParserCreated, nsAString& outViolatedDirective) const { if (CSPUTILSLOGENABLED()) { CSPUTILSLOG(("nsCSPPolicy::permits, aUri: %s, aDir: %d, aSpecific: %s", @@ -1552,13 +1412,6 @@ bool nsCSPPolicy::permits(CSPDirective aDir, nsILoadInfo* aLoadInfo, NS_ASSERTION(aUri, "permits needs an uri to perform the check!"); outViolatedDirective.Truncate(); - bool parserCreated = false; - nsAutoString nonce; - if (aLoadInfo) { - parserCreated = aLoadInfo->GetParserCreatedScript(); - MOZ_ALWAYS_SUCCEEDS(aLoadInfo->GetCspNonce(nonce)); - } - nsCSPDirective* defaultDir = nullptr; // Try to find a relevant directive @@ -1566,9 +1419,8 @@ bool nsCSPPolicy::permits(CSPDirective aDir, nsILoadInfo* aLoadInfo, // hashtable. for (uint32_t i = 0; i < mDirectives.Length(); i++) { if (mDirectives[i]->equals(aDir)) { - if (!mDirectives[i]->permits(aDir, aLoadInfo, aUri, nonce, aWasRedirected, - mReportOnly, mUpgradeInsecDir, - parserCreated)) { + if (!mDirectives[i]->permits(aUri, aNonce, aWasRedirected, mReportOnly, + mUpgradeInsecDir, aParserCreated)) { mDirectives[i]->getDirName(outViolatedDirective); return false; } @@ -1582,8 +1434,8 @@ bool nsCSPPolicy::permits(CSPDirective aDir, nsILoadInfo* aLoadInfo, // If the above loop runs through, we haven't found a matching directive. // Avoid relooping, just store the result of default-src while looping. if (!aSpecific && defaultDir) { - if (!defaultDir->permits(aDir, aLoadInfo, aUri, nonce, aWasRedirected, - mReportOnly, mUpgradeInsecDir, parserCreated)) { + if (!defaultDir->permits(aUri, aNonce, aWasRedirected, mReportOnly, + mUpgradeInsecDir, aParserCreated)) { defaultDir->getDirName(outViolatedDirective); return false; } @@ -1670,9 +1522,8 @@ bool nsCSPPolicy::allowsNavigateTo(nsIURI* aURI, bool aWasRedirected, return true; } // Otherwise, check against the allowlist. - if (!mDirectives[i]->permits( - nsIContentSecurityPolicy::NAVIGATE_TO_DIRECTIVE, nullptr, aURI, - u""_ns, aWasRedirected, false, false, false)) { + if (!mDirectives[i]->permits(aURI, u""_ns, aWasRedirected, false, false, + false)) { allowsNavigateTo = false; } } diff --git a/dom/security/nsCSPUtils.h b/dom/security/nsCSPUtils.h index 064476855793..dd3ea9a1c493 100644 --- a/dom/security/nsCSPUtils.h +++ b/dom/security/nsCSPUtils.h @@ -9,7 +9,6 @@ #include "nsCOMPtr.h" #include "nsIContentSecurityPolicy.h" -#include "nsILoadInfo.h" #include "nsIURI.h" #include "nsLiteralString.h" #include "nsString.h" @@ -237,8 +236,6 @@ class nsCSPBaseSrc { virtual bool isReportSample() const { return false; } - virtual bool isHash() const { return false; } - protected: // invalidate srcs if 'script-dynamic' is present or also invalidate // unsafe-inline' if nonce- or hash-source specified @@ -391,8 +388,6 @@ class nsCSPHashSrc : public nsCSPBaseSrc { // not invalidate hashes. } - bool isHash() const final { return true; } - private: nsString mAlgorithm; nsString mHash; @@ -452,8 +447,7 @@ class nsCSPDirective { explicit nsCSPDirective(CSPDirective aDirective); virtual ~nsCSPDirective(); - virtual bool permits(CSPDirective aDirective, nsILoadInfo* aLoadInfo, - nsIURI* aUri, const nsAString& aNonce, + virtual bool permits(nsIURI* aUri, const nsAString& aNonce, bool aWasRedirected, bool aReportOnly, bool aUpgradeInsecure, bool aParserCreated) const; virtual bool allows(enum CSPKeyword aKeyword, const nsAString& aHashOrNonce, @@ -560,9 +554,9 @@ class nsBlockAllMixedContentDirective : public nsCSPDirective { explicit nsBlockAllMixedContentDirective(CSPDirective aDirective); ~nsBlockAllMixedContentDirective(); - bool permits(CSPDirective aDirective, nsILoadInfo* aLoadInfo, nsIURI* aUri, - const nsAString& aNonce, bool aWasRedirected, bool aReportOnly, - bool aUpgradeInsecure, bool aParserCreated) const override { + bool permits(nsIURI* aUri, const nsAString& aNonce, bool aWasRedirected, + bool aReportOnly, bool aUpgradeInsecure, + bool aParserCreated) const override { return false; } @@ -618,9 +612,9 @@ class nsUpgradeInsecureDirective : public nsCSPDirective { explicit nsUpgradeInsecureDirective(CSPDirective aDirective); ~nsUpgradeInsecureDirective(); - bool permits(CSPDirective aDirective, nsILoadInfo* aLoadInfo, nsIURI* aUri, - const nsAString& aNonce, bool aWasRedirected, bool aReportOnly, - bool aUpgradeInsecure, bool aParserCreated) const override { + bool permits(nsIURI* aUri, const nsAString& aNonce, bool aWasRedirected, + bool aReportOnly, bool aUpgradeInsecure, + bool aParserCreated) const override { return false; } @@ -647,8 +641,8 @@ class nsCSPPolicy { nsCSPPolicy(); virtual ~nsCSPPolicy(); - bool permits(CSPDirective aDirective, nsILoadInfo* aLoadInfo, nsIURI* aUri, - bool aWasRedirected, bool aSpecific, + bool permits(CSPDirective aDirective, nsIURI* aUri, const nsAString& aNonce, + bool aWasRedirected, bool aSpecific, bool aParserCreated, nsAString& outViolatedDirective) const; bool allows(CSPDirective aDirective, enum CSPKeyword aKeyword, const nsAString& aHashOrNonce, bool aParserCreated) const; diff --git a/dom/security/test/unit/test_csp_reports.js b/dom/security/test/unit/test_csp_reports.js index 49cece5d7907..7248f1b4117a 100644 --- a/dom/security/test/unit/test_csp_reports.js +++ b/dom/security/test/unit/test_csp_reports.js @@ -194,10 +194,11 @@ function run_test() { csp.shouldLoad( Ci.nsIContentPolicy.TYPE_SCRIPT, null, // nsICSPEventListener - null, // aLoadInfo NetUtil.newURI("http://blocked.test/foo.js"), null, - true + true, + null, + false ); } ); @@ -260,10 +261,11 @@ function run_test() { csp.shouldLoad( Ci.nsIContentPolicy.TYPE_IMAGE, null, // nsICSPEventListener - null, // nsILoadInfo NetUtil.newURI("data:image/png;base64," + base64data), null, - true + true, + null, + false ); }); @@ -273,10 +275,11 @@ function run_test() { csp.shouldLoad( Ci.nsIContentPolicy.TYPE_SUBDOCUMENT, null, // nsICSPEventListener - null, // nsILoadInfo NetUtil.newURI("intent://mymaps.com/maps?um=1&ie=UTF-8&fb=1&sll"), null, - true + true, + null, + false ); }); @@ -288,10 +291,11 @@ function run_test() { csp.shouldLoad( Ci.nsIContentPolicy.TYPE_SCRIPT, null, // nsICSPEventListener - null, // nsILoadInfo NetUtil.newURI(selfSpec + "#bar"), null, - true + true, + null, + false ); }); } diff --git a/ipc/glue/BackgroundUtils.cpp b/ipc/glue/BackgroundUtils.cpp index 198729bcc9a9..f3071bb62713 100644 --- a/ipc/glue/BackgroundUtils.cpp +++ b/ipc/glue/BackgroundUtils.cpp @@ -486,10 +486,6 @@ nsresult LoadInfoToLoadInfoArgs(nsILoadInfo* aLoadInfo, nsAutoString cspNonce; Unused << NS_WARN_IF(NS_FAILED(aLoadInfo->GetCspNonce(cspNonce))); - nsAutoString integrityMetadata; - Unused << NS_WARN_IF( - NS_FAILED(aLoadInfo->GetIntegrityMetadata(integrityMetadata))); - nsCOMPtr cookieJarSettings; rv = aLoadInfo->GetCookieJarSettings(getter_AddRefs(cookieJarSettings)); NS_ENSURE_SUCCESS(rv, rv); @@ -572,9 +568,8 @@ nsresult LoadInfoToLoadInfoArgs(nsILoadInfo* aLoadInfo, aLoadInfo->GetDocumentHasUserInteracted(), aLoadInfo->GetAllowListFutureDocumentsCreatedFromThisRedirectChain(), aLoadInfo->GetNeedForCheckingAntiTrackingHeuristic(), cspNonce, - integrityMetadata, aLoadInfo->GetSkipContentSniffing(), - aLoadInfo->GetHttpsOnlyStatus(), aLoadInfo->GetHstsStatus(), - aLoadInfo->GetHasValidUserGestureActivation(), + aLoadInfo->GetSkipContentSniffing(), aLoadInfo->GetHttpsOnlyStatus(), + aLoadInfo->GetHstsStatus(), aLoadInfo->GetHasValidUserGestureActivation(), aLoadInfo->GetAllowDeprecatedSystemRequests(), aLoadInfo->GetIsInDevToolsContext(), aLoadInfo->GetParserCreatedScript(), aLoadInfo->GetIsFromProcessingFrameAttributes(), @@ -862,9 +857,9 @@ nsresult LoadInfoArgsToLoadInfo( loadInfoArgs.documentHasUserInteracted(), loadInfoArgs.allowListFutureDocumentsCreatedFromThisRedirectChain(), loadInfoArgs.needForCheckingAntiTrackingHeuristic(), - loadInfoArgs.cspNonce(), loadInfoArgs.integrityMetadata(), - loadInfoArgs.skipContentSniffing(), loadInfoArgs.httpsOnlyStatus(), - loadInfoArgs.hstsStatus(), loadInfoArgs.hasValidUserGestureActivation(), + loadInfoArgs.cspNonce(), loadInfoArgs.skipContentSniffing(), + loadInfoArgs.httpsOnlyStatus(), loadInfoArgs.hstsStatus(), + loadInfoArgs.hasValidUserGestureActivation(), loadInfoArgs.allowDeprecatedSystemRequests(), loadInfoArgs.isInDevToolsContext(), loadInfoArgs.parserCreatedScript(), loadInfoArgs.storagePermission(), loadInfoArgs.isMetaRefresh(), diff --git a/netwerk/base/LoadInfo.cpp b/netwerk/base/LoadInfo.cpp index e7f1addae035..ad390f81cebf 100644 --- a/netwerk/base/LoadInfo.cpp +++ b/netwerk/base/LoadInfo.cpp @@ -611,7 +611,6 @@ LoadInfo::LoadInfo(const LoadInfo& rhs) mNeedForCheckingAntiTrackingHeuristic( rhs.mNeedForCheckingAntiTrackingHeuristic), mCspNonce(rhs.mCspNonce), - mIntegrityMetadata(rhs.mIntegrityMetadata), mSkipContentSniffing(rhs.mSkipContentSniffing), mHttpsOnlyStatus(rhs.mHttpsOnlyStatus), mHstsStatus(rhs.mHstsStatus), @@ -665,8 +664,7 @@ LoadInfo::LoadInfo( bool aServiceWorkerTaintingSynthesized, bool aDocumentHasUserInteracted, bool aAllowListFutureDocumentsCreatedFromThisRedirectChain, bool aNeedForCheckingAntiTrackingHeuristic, const nsAString& aCspNonce, - const nsAString& aIntegrityMetadata, bool aSkipContentSniffing, - uint32_t aHttpsOnlyStatus, bool aHstsStatus, + bool aSkipContentSniffing, uint32_t aHttpsOnlyStatus, bool aHstsStatus, bool aHasValidUserGestureActivation, bool aAllowDeprecatedSystemRequests, bool aIsInDevToolsContext, bool aParserCreatedScript, nsILoadInfo::StoragePermissionState aStoragePermission, bool aIsMetaRefresh, @@ -732,7 +730,6 @@ LoadInfo::LoadInfo( mNeedForCheckingAntiTrackingHeuristic( aNeedForCheckingAntiTrackingHeuristic), mCspNonce(aCspNonce), - mIntegrityMetadata(aIntegrityMetadata), mSkipContentSniffing(aSkipContentSniffing), mHttpsOnlyStatus(aHttpsOnlyStatus), mHstsStatus(aHstsStatus), @@ -1806,20 +1803,6 @@ LoadInfo::SetCspNonce(const nsAString& aCspNonce) { return NS_OK; } -NS_IMETHODIMP -LoadInfo::GetIntegrityMetadata(nsAString& aIntegrityMetadata) { - aIntegrityMetadata = mIntegrityMetadata; - return NS_OK; -} - -NS_IMETHODIMP -LoadInfo::SetIntegrityMetadata(const nsAString& aIntegrityMetadata) { - MOZ_ASSERT(!mInitialSecurityCheckDone, - "setting the nonce is only allowed before any sec checks"); - mIntegrityMetadata = aIntegrityMetadata; - return NS_OK; -} - NS_IMETHODIMP LoadInfo::GetSkipContentSniffing(bool* aSkipContentSniffing) { *aSkipContentSniffing = mSkipContentSniffing; diff --git a/netwerk/base/LoadInfo.h b/netwerk/base/LoadInfo.h index dace62e98dff..ae6f16d596ed 100644 --- a/netwerk/base/LoadInfo.h +++ b/netwerk/base/LoadInfo.h @@ -234,8 +234,7 @@ class LoadInfo final : public nsILoadInfo { bool aServiceWorkerTaintingSynthesized, bool aDocumentHasUserInteracted, bool aAllowListFutureDocumentsCreatedFromThisRedirectChain, bool aNeedForCheckingAntiTrackingHeuristic, const nsAString& aCspNonce, - const nsAString& aIntegrityMetadata, bool aSkipContentSniffing, - uint32_t aHttpsOnlyStatus, bool aHstsStatus, + bool aSkipContentSniffing, uint32_t aHttpsOnlyStatus, bool aHstsStatus, bool aHasValidUserGestureActivation, bool aAllowDeprecatedSystemRequests, bool aIsInDevToolsContext, bool aParserCreatedScript, nsILoadInfo::StoragePermissionState aStoragePermission, @@ -343,7 +342,6 @@ class LoadInfo final : public nsILoadInfo { bool mAllowListFutureDocumentsCreatedFromThisRedirectChain = false; bool mNeedForCheckingAntiTrackingHeuristic = false; nsString mCspNonce; - nsString mIntegrityMetadata; bool mSkipContentSniffing = false; uint32_t mHttpsOnlyStatus = nsILoadInfo::HTTPS_ONLY_UNINITIALIZED; bool mHstsStatus = false; diff --git a/netwerk/base/TRRLoadInfo.cpp b/netwerk/base/TRRLoadInfo.cpp index 2b9360cd23f1..e5cbe5e21370 100644 --- a/netwerk/base/TRRLoadInfo.cpp +++ b/netwerk/base/TRRLoadInfo.cpp @@ -539,16 +539,6 @@ TRRLoadInfo::SetCspNonce(const nsAString& aCspNonce) { return NS_ERROR_NOT_IMPLEMENTED; } -NS_IMETHODIMP -TRRLoadInfo::GetIntegrityMetadata(nsAString& aIntegrityMetadata) { - return NS_ERROR_NOT_IMPLEMENTED; -} - -NS_IMETHODIMP -TRRLoadInfo::SetIntegrityMetadata(const nsAString& aIntegrityMetadata) { - return NS_ERROR_NOT_IMPLEMENTED; -} - NS_IMETHODIMP TRRLoadInfo::GetSkipContentSniffing(bool* aSkipContentSniffing) { return NS_ERROR_NOT_IMPLEMENTED; diff --git a/netwerk/base/nsILoadInfo.idl b/netwerk/base/nsILoadInfo.idl index f3f8304a1b88..79fdcc5e4da3 100644 --- a/netwerk/base/nsILoadInfo.idl +++ b/netwerk/base/nsILoadInfo.idl @@ -1336,9 +1336,6 @@ interface nsILoadInfo : nsISupports */ attribute AString cspNonce; - // Subresource Integrity (SRI) metadata. - attribute AString integrityMetadata; - /** * List of possible reasons the request associated with this load info * may have been blocked, set by various content blocking checkers. diff --git a/netwerk/ipc/NeckoChannelParams.ipdlh b/netwerk/ipc/NeckoChannelParams.ipdlh index f44ad8be1589..0aaacd2bd021 100644 --- a/netwerk/ipc/NeckoChannelParams.ipdlh +++ b/netwerk/ipc/NeckoChannelParams.ipdlh @@ -164,7 +164,6 @@ struct LoadInfoArgs bool allowListFutureDocumentsCreatedFromThisRedirectChain; bool needForCheckingAntiTrackingHeuristic; nsString cspNonce; - nsString integrityMetadata; bool skipContentSniffing; uint32_t httpsOnlyStatus; bool hstsStatus; diff --git a/testing/web-platform/meta/content-security-policy/script-src/script-src-report-only-policy-works-with-external-hash-policy.html.ini b/testing/web-platform/meta/content-security-policy/script-src/script-src-report-only-policy-works-with-external-hash-policy.html.ini new file mode 100644 index 000000000000..833dfeeddb0e --- /dev/null +++ b/testing/web-platform/meta/content-security-policy/script-src/script-src-report-only-policy-works-with-external-hash-policy.html.ini @@ -0,0 +1,8 @@ +implementation-status: backlog +[script-src-report-only-policy-works-with-external-hash-policy.html] + [External script in a script tag with matching SRI hash should run.] + expected: FAIL + + [Should fire securitypolicyviolation event] + expected: FAIL + diff --git a/testing/web-platform/meta/content-security-policy/script-src/script-src-sri_hash.sub.html.ini b/testing/web-platform/meta/content-security-policy/script-src/script-src-sri_hash.sub.html.ini new file mode 100644 index 000000000000..46422119adc1 --- /dev/null +++ b/testing/web-platform/meta/content-security-policy/script-src/script-src-sri_hash.sub.html.ini @@ -0,0 +1,14 @@ +[script-src-sri_hash.sub.html] + expected: + if (os == "android") and fission: [OK, TIMEOUT] + [matching integrity] + expected: FAIL + + [multiple matching integrity] + expected: FAIL + + [matching plus unsupported integrity] + expected: FAIL + + [External script in a script tag with matching SRI hash should run.] + expected: FAIL diff --git a/testing/web-platform/tests/content-security-policy/default-src/default-src-sri_hash.sub.html b/testing/web-platform/tests/content-security-policy/default-src/default-src-sri_hash.sub.html deleted file mode 100644 index 87fce5961fd1..000000000000 --- a/testing/web-platform/tests/content-security-policy/default-src/default-src-sri_hash.sub.html +++ /dev/null @@ -1,109 +0,0 @@ - - - - - External scripts with matching SRI hash (in default-src) should be allowed. - - - - - - - - -

External scripts with matching SRI hash (in default-src) should be allowed.

-
- - - - - - - - - - diff --git a/testing/web-platform/tests/content-security-policy/default-src/default-src-sri_hash.sub.html.sub.headers b/testing/web-platform/tests/content-security-policy/default-src/default-src-sri_hash.sub.html.sub.headers deleted file mode 100644 index 6f2066063873..000000000000 --- a/testing/web-platform/tests/content-security-policy/default-src/default-src-sri_hash.sub.html.sub.headers +++ /dev/null @@ -1,5 +0,0 @@ -Expires: Mon, 26 Jul 1997 05:00:00 GMT -Cache-Control: no-store, no-cache, must-revalidate -Cache-Control: post-check=0, pre-check=0, false -Pragma: no-cache -Content-Security-Policy: default-src {{domains[www]}}:* 'nonce-dummy' 'sha256-wIc3KtqOuTFEu6t17sIBuOswgkV406VJvhSk79Gw6U0=' 'ShA256-L7/UQ9VWpyG7C9RDEC4ctS5hI3Zcw+ta+haPGlByG9c=' 'sha512-rYCVMxWV5nq8IsMo+UZNObWtEiWGok/vDN8BMoEQi41s0znSes6E1Q2aag3Lw3u2J1w2rqH7uF2ws6FpQhfSOA=='; style-src 'unsafe-inline' diff --git a/testing/web-platform/tests/content-security-policy/default-src/externalScript.js b/testing/web-platform/tests/content-security-policy/default-src/externalScript.js deleted file mode 100644 index 2920b03c9bc9..000000000000 --- a/testing/web-platform/tests/content-security-policy/default-src/externalScript.js +++ /dev/null @@ -1 +0,0 @@ -externalRan = true; \ No newline at end of file diff --git a/testing/web-platform/tests/content-security-policy/default-src/simpleSourcedScript.js b/testing/web-platform/tests/content-security-policy/default-src/simpleSourcedScript.js deleted file mode 100644 index deca86508fff..000000000000 --- a/testing/web-platform/tests/content-security-policy/default-src/simpleSourcedScript.js +++ /dev/null @@ -1 +0,0 @@ -window.postMessage(document.currentScript.id, "*"); diff --git a/testing/web-platform/tests/content-security-policy/script-src/script-src-sri_hash.sub.html b/testing/web-platform/tests/content-security-policy/script-src/script-src-sri_hash.sub.html index 9216e2b0d497..b59206824dc8 100644 --- a/testing/web-platform/tests/content-security-policy/script-src/script-src-sri_hash.sub.html +++ b/testing/web-platform/tests/content-security-policy/script-src/script-src-sri_hash.sub.html @@ -6,8 +6,7 @@ - - + @@ -26,13 +25,9 @@ './simpleSourcedScript.js', 'sha256-L7/UQ9VWpyG7C9RDEC4ctS5hI3Zcw+ta+haPGlByG9c=', true ], - [ 'matching integrity (case-insensitive algorithm)', - './simpleSourcedScript.js', - 'sha256-L7/UQ9VWpyG7C9RDEC4ctS5hI3Zcw+ta+haPGlByG9c=', - true ], [ 'multiple matching integrity', './simpleSourcedScript.js', - 'sha256-L7/UQ9VWpyG7C9RDEC4ctS5hI3Zcw+ta+haPGlByG9c= sha512-rYCVMxWV5nq8IsMo+UZNObWtEiWGok/vDN8BMoEQi41s0znSes6E1Q2aag3Lw3u2J1w2rqH7uF2ws6FpQhfSOA==', + 'sha256-L7/UQ9VWpyG7C9RDEC4ctS5hI3Zcw+ta+haPGlByG9c= sha512-rYCVMxWV5nq8IsMo+UZNObWtEiWGok/vDN8BMoEQi41s0znSes6E1Q2aag3Lw3u2J1w2rqH7uF2ws6FpQhfSOA=', true ], [ 'no integrity', './simpleSourcedScript.js', diff --git a/testing/web-platform/tests/content-security-policy/script-src/script-src-sri_hash.sub.html.sub.headers b/testing/web-platform/tests/content-security-policy/script-src/script-src-sri_hash.sub.html.sub.headers index 971525ff762b..25cd6541acac 100644 --- a/testing/web-platform/tests/content-security-policy/script-src/script-src-sri_hash.sub.html.sub.headers +++ b/testing/web-platform/tests/content-security-policy/script-src/script-src-sri_hash.sub.html.sub.headers @@ -2,4 +2,4 @@ Expires: Mon, 26 Jul 1997 05:00:00 GMT Cache-Control: no-store, no-cache, must-revalidate Cache-Control: post-check=0, pre-check=0, false Pragma: no-cache -Content-Security-Policy: script-src {{domains[www]}}:* 'nonce-dummy' 'sha256-wIc3KtqOuTFEu6t17sIBuOswgkV406VJvhSk79Gw6U0=' 'ShA256-L7/UQ9VWpyG7C9RDEC4ctS5hI3Zcw+ta+haPGlByG9c=' 'sha512-rYCVMxWV5nq8IsMo+UZNObWtEiWGok/vDN8BMoEQi41s0znSes6E1Q2aag3Lw3u2J1w2rqH7uF2ws6FpQhfSOA==' +Content-Security-Policy: script-src {{domains[www]}}:* 'nonce-dummy' 'sha256-wIc3KtqOuTFEu6t17sIBuOswgkV406VJvhSk79Gw6U0=' 'sha256-L7/UQ9VWpyG7C9RDEC4ctS5hI3Zcw+ta+haPGlByG9c=' 'sha512-rYCVMxWV5nq8IsMo+UZNObWtEiWGok/vDN8BMoEQi41s0znSes6E1Q2aag3Lw3u2J1w2rqH7uF2ws6FpQhfSOA='