diff --git a/dom/fetch/FetchDriver.cpp b/dom/fetch/FetchDriver.cpp index 10c6454277c9..7485b441428b 100644 --- a/dom/fetch/FetchDriver.cpp +++ b/dom/fetch/FetchDriver.cpp @@ -1356,7 +1356,7 @@ FetchDriver::OnStartRequest(nsIRequest* aRequest) { SRICheck::IntegrityMetadata(mRequest->GetIntegrity(), sourceUri, reporter, &mSRIMetadata); mSRIDataVerifier = - MakeUnique(mSRIMetadata, sourceUri, reporter); + MakeUnique(mSRIMetadata, channel, reporter); // Do not retarget off main thread when using SRI API. return NS_OK; @@ -1583,14 +1583,7 @@ FetchDriver::OnStopRequest(nsIRequest* aRequest, nsresult aStatusCode) { reporter = mObserver->GetReporter(); } - nsAutoCString sourceUri; - if (mDocument && mDocument->GetDocumentURI()) { - mDocument->GetDocumentURI()->GetAsciiSpec(sourceUri); - } else if (!mWorkerScript.IsEmpty()) { - sourceUri.Assign(mWorkerScript); - } - nsresult rv = - mSRIDataVerifier->Verify(mSRIMetadata, channel, sourceUri, reporter); + nsresult rv = mSRIDataVerifier->Verify(mSRIMetadata, channel, reporter); if (NS_FAILED(rv)) { if (altDataListener) { altDataListener->Cancel(); diff --git a/dom/script/ScriptLoader.cpp b/dom/script/ScriptLoader.cpp index 47bd1277f9c8..6276dcdb031a 100644 --- a/dom/script/ScriptLoader.cpp +++ b/dom/script/ScriptLoader.cpp @@ -931,12 +931,8 @@ nsresult ScriptLoader::PrepareIncrementalStreamLoader( ScriptLoadRequest* aRequest) { UniquePtr sriDataVerifier; if (!aRequest->mIntegrity.IsEmpty()) { - nsAutoCString sourceUri; - if (mDocument->GetDocumentURI()) { - mDocument->GetDocumentURI()->GetAsciiSpec(sourceUri); - } sriDataVerifier = MakeUnique(aRequest->mIntegrity, - sourceUri, mReporter); + aChannel, mReporter); } RefPtr handler = @@ -3837,13 +3833,7 @@ nsresult ScriptLoader::VerifySRI(ScriptLoadRequest* aRequest, if (!aRequest->mIntegrity.IsEmpty() && NS_SUCCEEDED((rv = aSRIStatus))) { MOZ_ASSERT(aSRIDataVerifier); MOZ_ASSERT(mReporter); - - nsAutoCString sourceUri; - if (mDocument && mDocument->GetDocumentURI()) { - mDocument->GetDocumentURI()->GetAsciiSpec(sourceUri); - } - rv = aSRIDataVerifier->Verify(aRequest->mIntegrity, channel, sourceUri, - mReporter); + rv = aSRIDataVerifier->Verify(aRequest->mIntegrity, channel, mReporter); if (channelRequest) { mReporter->FlushReportsToConsole( nsContentUtils::GetInnerWindowID(channelRequest)); diff --git a/dom/security/SRICheck.cpp b/dom/security/SRICheck.cpp index 73f27759ddf2..4ffb858eb0ad 100644 --- a/dom/security/SRICheck.cpp +++ b/dom/security/SRICheck.cpp @@ -9,13 +9,12 @@ #include "mozilla/Base64.h" #include "mozilla/LoadTainting.h" #include "mozilla/Logging.h" -#include "mozilla/Preferences.h" #include "mozilla/dom/SRILogHelper.h" #include "mozilla/dom/SRIMetadata.h" -#include "nsComponentManagerUtils.h" #include "nsContentUtils.h" #include "nsIChannel.h" #include "nsIConsoleReportCollector.h" +#include "nsIHttpChannel.h" #include "nsIScriptError.h" #include "nsIURI.h" #include "nsNetUtil.h" @@ -30,6 +29,30 @@ namespace mozilla::dom { +static void GetChannelRequestURI(nsIChannel* aChannel, nsACString& aSourceUri) { + nsCOMPtr originalURI; + aChannel->GetOriginalURI(getter_AddRefs(originalURI)); + if (originalURI) { + originalURI->GetAsciiSpec(aSourceUri); + } +} + +static void GetReferrerSpec(nsIChannel* aChannel, nsACString& aReferrer) { + nsCOMPtr httpChan = do_QueryInterface(aChannel); + if (!httpChan) { + return; + } + nsCOMPtr referrer = httpChan->GetReferrerInfo(); + if (!referrer) { + return; + } + nsCOMPtr original = referrer->GetOriginalReferrer(); + if (!original) { + return; + } + original->GetSpec(aReferrer); +} + /** * Returns whether or not the sub-resource about to be loaded is eligible * for integrity checks. If it's not, the checks will be skipped and the @@ -37,7 +60,6 @@ namespace mozilla::dom { */ static nsresult IsEligible(nsIChannel* aChannel, mozilla::LoadTainting aTainting, - const nsACString& aSourceFileURI, nsIConsoleReportCollector* aReporter) { NS_ENSURE_ARG_POINTER(aReporter); @@ -52,17 +74,6 @@ static nsresult IsEligible(nsIChannel* aChannel, return NS_OK; } - nsCOMPtr originalURI; - nsresult rv = aChannel->GetOriginalURI(getter_AddRefs(originalURI)); - NS_ENSURE_SUCCESS(rv, rv); - nsAutoCString requestSpec; - rv = originalURI->GetSpec(requestSpec); - NS_ENSURE_SUCCESS(rv, rv); - - if (MOZ_LOG_TEST(SRILogHelper::GetSriLog(), mozilla::LogLevel::Debug)) { - SRILOG(("SRICheck::IsEligible, requestURI=%s", requestSpec.get())); - } - // Is the sub-resource same-origin? if (aTainting == LoadTainting::Basic) { SRILOG(("SRICheck::IsEligible, same-origin")); @@ -70,13 +81,14 @@ static nsresult IsEligible(nsIChannel* aChannel, } SRILOG(("SRICheck::IsEligible, NOT same-origin")); - NS_ConvertUTF8toUTF16 requestSpecUTF16(requestSpec); - nsTArray params; - params.AppendElement(requestSpecUTF16); + nsAutoCString requestSpec; + GetChannelRequestURI(aChannel, requestSpec); + nsAutoCString referrer; + GetReferrerSpec(aChannel, referrer); aReporter->AddConsoleReport( nsIScriptError::errorFlag, "Sub-resource Integrity"_ns, - nsContentUtils::eSECURITY_PROPERTIES, aSourceFileURI, 0, 0, - "IneligibleResource"_ns, const_cast&>(params)); + nsContentUtils::eSECURITY_PROPERTIES, referrer, 0, 0, + "IneligibleResource"_ns, {NS_ConvertUTF8toUTF16(requestSpec)}); return NS_ERROR_SRI_NOT_ELIGIBLE; } @@ -102,25 +114,17 @@ nsresult SRICheck::IntegrityMetadata(const nsAString& aMetadataList, SRIMetadata metadata(token); if (metadata.IsMalformed()) { - NS_ConvertUTF8toUTF16 tokenUTF16(token); - nsTArray params; - params.AppendElement(tokenUTF16); aReporter->AddConsoleReport( nsIScriptError::warningFlag, "Sub-resource Integrity"_ns, nsContentUtils::eSECURITY_PROPERTIES, aSourceFileURI, 0, 0, - "MalformedIntegrityHash"_ns, - const_cast&>(params)); + "MalformedIntegrityHash"_ns, {NS_ConvertUTF8toUTF16(token)}); } else if (!metadata.IsAlgorithmSupported()) { nsAutoCString alg; metadata.GetAlgorithm(&alg); - NS_ConvertUTF8toUTF16 algUTF16(alg); - nsTArray params; - params.AppendElement(algUTF16); aReporter->AddConsoleReport( nsIScriptError::warningFlag, "Sub-resource Integrity"_ns, nsContentUtils::eSECURITY_PROPERTIES, aSourceFileURI, 0, 0, - "UnsupportedHashAlg"_ns, - const_cast&>(params)); + "UnsupportedHashAlg"_ns, {NS_ConvertUTF8toUTF16(alg)}); } nsAutoCString alg1, alg2; @@ -159,7 +163,7 @@ nsresult SRICheck::IntegrityMetadata(const nsAString& aMetadataList, // ////////////////////////////////////////////////////////////// SRICheckDataVerifier::SRICheckDataVerifier(const SRIMetadata& aMetadata, - const nsACString& aSourceFileURI, + nsIChannel* aChannel, nsIConsoleReportCollector* aReporter) : mCryptoHash(nullptr), mBytesHashed(0), @@ -171,11 +175,12 @@ SRICheckDataVerifier::SRICheckDataVerifier(const SRIMetadata& aMetadata, MOZ_ASSERT(aReporter); if (!aMetadata.IsValid()) { - nsTArray params; - aReporter->AddConsoleReport( - nsIScriptError::warningFlag, "Sub-resource Integrity"_ns, - nsContentUtils::eSECURITY_PROPERTIES, aSourceFileURI, 0, 0, - "NoValidMetadata"_ns, const_cast&>(params)); + nsAutoCString referrer; + GetReferrerSpec(aChannel, referrer); + aReporter->AddConsoleReport(nsIScriptError::warningFlag, + "Sub-resource Integrity"_ns, + nsContentUtils::eSECURITY_PROPERTIES, referrer, + 0, 0, "NoValidMetadata"_ns, {}); mInvalidMetadata = true; return; // ignore invalid metadata for forward-compatibility } @@ -234,8 +239,8 @@ nsresult SRICheckDataVerifier::Finish() { } nsresult SRICheckDataVerifier::VerifyHash( - const SRIMetadata& aMetadata, uint32_t aHashIndex, - const nsACString& aSourceFileURI, nsIConsoleReportCollector* aReporter) { + nsIChannel* aChannel, const SRIMetadata& aMetadata, uint32_t aHashIndex, + nsIConsoleReportCollector* aReporter) { NS_ENSURE_ARG_POINTER(aReporter); nsAutoCString base64Hash; @@ -259,13 +264,13 @@ nsresult SRICheckDataVerifier::VerifyHash( SRILOG( ("SRICheckDataVerifier::VerifyHash, base64url decoding failed too. " "Bailing out.")); + nsAutoCString referrer; + GetReferrerSpec(aChannel, referrer); // if neither succeeded, we can bail out and warn - nsTArray params; aReporter->AddConsoleReport( nsIScriptError::errorFlag, "Sub-resource Integrity"_ns, - nsContentUtils::eSECURITY_PROPERTIES, aSourceFileURI, 0, 0, - "InvalidIntegrityBase64"_ns, - const_cast&>(params)); + nsContentUtils::eSECURITY_PROPERTIES, referrer, 0, 0, + "InvalidIntegrityBase64"_ns, {}); return NS_ERROR_SRI_CORRUPT; } binaryHash.Assign(reinterpret_cast(decoded.Elements()), @@ -286,12 +291,12 @@ nsresult SRICheckDataVerifier::VerifyHash( SRILOG( ("SRICheckDataVerifier::VerifyHash, supplied base64(url) hash was " "incorrect length after decoding.")); - nsTArray params; - aReporter->AddConsoleReport( - nsIScriptError::errorFlag, "Sub-resource Integrity"_ns, - nsContentUtils::eSECURITY_PROPERTIES, aSourceFileURI, 0, 0, - "InvalidIntegrityLength"_ns, - const_cast&>(params)); + nsAutoCString referrer; + GetReferrerSpec(aChannel, referrer); + aReporter->AddConsoleReport(nsIScriptError::errorFlag, + "Sub-resource Integrity"_ns, + nsContentUtils::eSECURITY_PROPERTIES, referrer, + 0, 0, "InvalidIntegrityLength"_ns, {}); return NS_ERROR_SRI_CORRUPT; } @@ -309,18 +314,15 @@ nsresult SRICheckDataVerifier::VerifyHash( nsresult SRICheckDataVerifier::Verify(const SRIMetadata& aMetadata, nsIChannel* aChannel, - const nsACString& aSourceFileURI, nsIConsoleReportCollector* aReporter) { MOZ_ASSERT(aChannel); nsCOMPtr loadInfo = aChannel->LoadInfo(); - return Verify(aMetadata, aChannel, loadInfo->GetTainting(), aSourceFileURI, - aReporter); + return Verify(aMetadata, aChannel, loadInfo->GetTainting(), aReporter); } nsresult SRICheckDataVerifier::Verify(const SRIMetadata& aMetadata, nsIChannel* aChannel, LoadTainting aLoadTainting, - const nsACString& aSourceFileURI, nsIConsoleReportCollector* aReporter) { NS_ENSURE_ARG_POINTER(aReporter); @@ -334,8 +336,7 @@ nsresult SRICheckDataVerifier::Verify(const SRIMetadata& aMetadata, nsresult rv = Finish(); NS_ENSURE_SUCCESS(rv, rv); - if (NS_FAILED( - IsEligible(aChannel, aLoadTainting, aSourceFileURI, aReporter))) { + if (NS_FAILED(IsEligible(aChannel, aLoadTainting, aReporter))) { return NS_ERROR_SRI_NOT_ELIGIBLE; } @@ -344,7 +345,7 @@ nsresult SRICheckDataVerifier::Verify(const SRIMetadata& aMetadata, } for (uint32_t i = 0; i < aMetadata.HashCount(); i++) { - if (NS_SUCCEEDED(VerifyHash(aMetadata, i, aSourceFileURI, aReporter))) { + if (NS_SUCCEEDED(VerifyHash(aChannel, aMetadata, i, aReporter))) { return NS_OK; // stop at the first valid hash } } @@ -363,14 +364,15 @@ nsresult SRICheckDataVerifier::Verify(const SRIMetadata& aMetadata, rv = Base64Encode(mComputedHash, encodedHash); NS_ENSURE_SUCCESS(rv, rv); - nsTArray params; - params.AppendElement(NS_ConvertUTF8toUTF16(alg)); - params.AppendElement(NS_ConvertUTF8toUTF16(requestSpec)); - params.AppendElement(NS_ConvertUTF8toUTF16(encodedHash)); + nsAutoCString referrer; + GetReferrerSpec(aChannel, referrer); + aReporter->AddConsoleReport( nsIScriptError::errorFlag, "Sub-resource Integrity"_ns, - nsContentUtils::eSECURITY_PROPERTIES, aSourceFileURI, 0, 0, - "IntegrityMismatch3"_ns, const_cast&>(params)); + nsContentUtils::eSECURITY_PROPERTIES, referrer, 0, 0, + "IntegrityMismatch3"_ns, + {NS_ConvertUTF8toUTF16(alg), NS_ConvertUTF8toUTF16(requestSpec), + NS_ConvertUTF8toUTF16(encodedHash)}); return NS_ERROR_SRI_CORRUPT; } diff --git a/dom/security/SRICheck.h b/dom/security/SRICheck.h index 7c046f4a273e..2d932c43f9a8 100644 --- a/dom/security/SRICheck.h +++ b/dom/security/SRICheck.h @@ -48,8 +48,7 @@ class SRICheck final { // metadata. class SRICheckDataVerifier final { public: - SRICheckDataVerifier(const SRIMetadata& aMetadata, - const nsACString& aSourceFileURI, + SRICheckDataVerifier(const SRIMetadata& aMetadata, nsIChannel* aChannel, nsIConsoleReportCollector* aReporter); // Append the following bytes to the content used to compute the hash. Once @@ -59,13 +58,12 @@ class SRICheckDataVerifier final { // Verify that the computed hash corresponds to the metadata. nsresult Verify(const SRIMetadata& aMetadata, nsIChannel* aChannel, - LoadTainting aLoadTainting, const nsACString& aSourceFileURI, + LoadTainting aLoadTainting, nsIConsoleReportCollector* aReporter); // Like Verify(), but takes the load tainting from the channel's load info // (which is main-thread only). nsresult Verify(const SRIMetadata& aMetadata, nsIChannel* aChannel, - const nsACString& aSourceFileURI, nsIConsoleReportCollector* aReporter); bool IsComplete() const { return mComplete; } @@ -100,8 +98,8 @@ class SRICheckDataVerifier final { nsresult EnsureCryptoHash(); nsresult Finish(); - nsresult VerifyHash(const SRIMetadata& aMetadata, uint32_t aHashIndex, - const nsACString& aSourceFileURI, + nsresult VerifyHash(nsIChannel* aChannel, const SRIMetadata& aMetadata, + uint32_t aHashIndex, nsIConsoleReportCollector* aReporter); }; diff --git a/dom/security/test/sri/mochitest.toml b/dom/security/test/sri/mochitest.toml index e40ffa6cbc3c..46925c7bbb2a 100644 --- a/dom/security/test/sri/mochitest.toml +++ b/dom/security/test/sri/mochitest.toml @@ -39,6 +39,8 @@ support-files = [ ["test_bug_1364262.html"] +["test_console_messages.html"] + ["test_script_crossdomain.html"] skip-if = [ "http3", diff --git a/dom/security/test/sri/test_console_messages.html b/dom/security/test/sri/test_console_messages.html new file mode 100644 index 000000000000..1dcd7c9922da --- /dev/null +++ b/dom/security/test/sri/test_console_messages.html @@ -0,0 +1,52 @@ + +Test for SRI console messages + + diff --git a/layout/style/Loader.cpp b/layout/style/Loader.cpp index 8d94cbf4b5aa..38aadab68cad 100644 --- a/layout/style/Loader.cpp +++ b/layout/style/Loader.cpp @@ -626,19 +626,20 @@ NotNull SheetLoadData::DetermineNonBOMEncoding( return mGuessedEncoding; } -static nsresult VerifySheetIntegrity( - const SRIMetadata& aMetadata, nsIChannel* aChannel, LoadTainting aTainting, - const nsACString& aFirst, const nsACString& aSecond, - const nsACString& aSourceFileURI, nsIConsoleReportCollector* aReporter) { +static nsresult VerifySheetIntegrity(const SRIMetadata& aMetadata, + nsIChannel* aChannel, + LoadTainting aTainting, + const nsACString& aFirst, + const nsACString& aSecond, + nsIConsoleReportCollector* aReporter) { NS_ENSURE_ARG_POINTER(aReporter); MOZ_LOG(SRILogHelper::GetSriLog(), LogLevel::Debug, ("VerifySheetIntegrity (unichar stream)")); - SRICheckDataVerifier verifier(aMetadata, aSourceFileURI, aReporter); + SRICheckDataVerifier verifier(aMetadata, aChannel, aReporter); MOZ_TRY(verifier.Update(aFirst)); MOZ_TRY(verifier.Update(aSecond)); - return verifier.Verify(aMetadata, aChannel, aTainting, aSourceFileURI, - aReporter); + return verifier.Verify(aMetadata, aChannel, aTainting, aReporter); } static bool AllLoadsCanceled(const SheetLoadData& aData) { @@ -780,13 +781,8 @@ nsresult SheetLoadData::VerifySheetReadyToParse(nsresult aStatus, SRIMetadata sriMetadata; mSheet->GetIntegrity(sriMetadata); if (!sriMetadata.IsEmpty()) { - nsAutoCString sourceUri; - if (nsCOMPtr uri = mReferrerInfo->GetOriginalReferrer()) { - uri->GetAsciiSpec(sourceUri); - } - nsresult rv = - VerifySheetIntegrity(sriMetadata, aChannel, mTainting, aBytes1, aBytes2, - sourceUri, mLoader->mReporter); + nsresult rv = VerifySheetIntegrity(sriMetadata, aChannel, mTainting, + aBytes1, aBytes2, mLoader->mReporter); if (NS_FAILED(rv)) { LOG((" Load was blocked by SRI")); MOZ_LOG(gSriPRLog, LogLevel::Debug,