diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 14:29:10 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 14:29:10 +0000 |
commit | 2aa4a82499d4becd2284cdb482213d541b8804dd (patch) | |
tree | b80bf8bf13c3766139fbacc530efd0dd9d54394c /dom/security/test/gtest/TestUnexpectedPrivilegedLoads.cpp | |
parent | Initial commit. (diff) | |
download | firefox-upstream.tar.xz firefox-upstream.zip |
Adding upstream version 86.0.1.upstream/86.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'dom/security/test/gtest/TestUnexpectedPrivilegedLoads.cpp')
-rw-r--r-- | dom/security/test/gtest/TestUnexpectedPrivilegedLoads.cpp | 197 |
1 files changed, 197 insertions, 0 deletions
diff --git a/dom/security/test/gtest/TestUnexpectedPrivilegedLoads.cpp b/dom/security/test/gtest/TestUnexpectedPrivilegedLoads.cpp new file mode 100644 index 0000000000..3bfaa29a59 --- /dev/null +++ b/dom/security/test/gtest/TestUnexpectedPrivilegedLoads.cpp @@ -0,0 +1,197 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "core/TelemetryEvent.h" +#include "gtest/gtest.h" +#include "js/Array.h" // JS::GetArrayLength +#include "mozilla/Maybe.h" +#include "mozilla/Telemetry.h" +#include "mozilla/Unused.h" +#include "TelemetryFixture.h" +#include "TelemetryTestHelpers.h" + +#include <string.h> +#include <stdlib.h> +#include "nsContentSecurityManager.h" +#include "nsContentSecurityUtils.h" +#include "nsNetUtil.h" +#include "nsStringFwd.h" + +using namespace mozilla; +using namespace TelemetryTestHelpers; + +TEST_F(TelemetryTestFixture, UnexpectedPrivilegedLoadsTelemetryTest) { + struct testResults { + nsCString fileinfo; + nsCString extraValueContenttype; + nsCString extraValueRemotetype; + nsCString extraValueFiledetails; + }; + + struct testCasesAndResults { + nsCString urlstring; + ExtContentPolicyType contentType; + nsCString remoteType; + testResults expected; + }; + + AutoJSContextWithGlobal cx(mCleanGlobal); + // Make sure we don't look at events from other tests. + Unused << mTelemetry->ClearEvents(); + + // required for telemetry lookups + constexpr auto category = "security"_ns; + constexpr auto method = "unexpectedload"_ns; + constexpr auto object = "systemprincipal"_ns; + constexpr auto extraKeyContenttype = "contenttype"_ns; + constexpr auto extraKeyRemotetype = "remotetype"_ns; + constexpr auto extraKeyFiledetails = "filedetails"_ns; + + // some cases from TestFilenameEvalParser + // no need to replicate all scenarios?! + testCasesAndResults myTestCases[] = { + {"chrome://firegestures/content/browser.js"_ns, + ExtContentPolicy::TYPE_SCRIPT, + "web"_ns, + {"chromeuri"_ns, "TYPE_SCRIPT"_ns, "web"_ns, + "chrome://firegestures/content/browser.js"_ns}}, + {"resource://firegestures/content/browser.js"_ns, + ExtContentPolicy::TYPE_SCRIPT, + "web"_ns, + {"resourceuri"_ns, "TYPE_SCRIPT"_ns, "web"_ns, + "resource://firegestures/content/browser.js"_ns}}, + {// test that we don't report blob details + // ..and test that we strip of URLs from remoteTypes + "blob://000-000"_ns, + ExtContentPolicy::TYPE_SCRIPT, + "webIsolated=https://blob.example/"_ns, + {"bloburi"_ns, "TYPE_SCRIPT"_ns, "webIsolated"_ns, "unknown"_ns}}, + {// test for cases where finalURI is null, due to a broken nested URI + // .. like malformed moz-icon URLs + "moz-icon:blahblah"_ns, + ExtContentPolicy::TYPE_IMAGE, + "web"_ns, + {"other"_ns, "TYPE_IMAGE"_ns, "web"_ns, "unknown"_ns}}, + {// we dont report data urls + // ..and test that we strip of URLs from remoteTypes + "data://blahblahblah"_ns, + ExtContentPolicy::TYPE_DOCUMENT, + "webCOOP+COEP=https://data.example"_ns, + {"dataurl"_ns, "TYPE_DOCUMENT"_ns, "webCOOP+COEP"_ns, "unknown"_ns}}, + {// we only report file URLs on windows, where we can easily sanitize + "file://c/users/tom/file.txt"_ns, + ExtContentPolicy::TYPE_SCRIPT, + "web"_ns, + { +#if defined(XP_WIN) + "sanitizedWindowsURL"_ns, "TYPE_SCRIPT"_ns, "web"_ns, + "file://.../file.txt"_ns + +#else + "other"_ns, "TYPE_SCRIPT"_ns, "web"_ns, "unknown"_ns +#endif + }}, + {// test for cases where finalURI is empty + ""_ns, + ExtContentPolicy::TYPE_IMAGE, + "web"_ns, + {"other"_ns, "TYPE_IMAGE"_ns, "web"_ns, "unknown"_ns}}, + {// test for cases where finalURI is null, due to the struct layout, we'll + // override the URL with nullptr in loop below. + "URLWillResultInNullPtr"_ns, + ExtContentPolicy::TYPE_FONT, + "web"_ns, + {"other"_ns, "TYPE_FONT"_ns, "web"_ns, "unknown"_ns}}, + }; + + int i = 0; + for (auto const& currentTest : myTestCases) { + nsCOMPtr<nsIURI> uri; + + // special-casing for a case where the uri is null + if (!currentTest.urlstring.Equals("URLWillResultInNullPtr")) { + NS_NewURI(getter_AddRefs(uri), currentTest.urlstring); + } + // this will record the event + nsContentSecurityManager::MeasureUnexpectedPrivilegedLoads( + uri, currentTest.contentType, currentTest.remoteType); + + // let's inspect the recorded events + + JS::RootedValue eventsSnapshot(cx.GetJSContext()); + GetEventSnapshot(cx.GetJSContext(), &eventsSnapshot); + + ASSERT_TRUE(EventPresent(cx.GetJSContext(), eventsSnapshot, category, + method, object)) + << "Test event with value and extra must be present."; + + // Convert eventsSnapshot into array/object + JSContext* aCx = cx.GetJSContext(); + JS::RootedObject arrayObj(aCx, &eventsSnapshot.toObject()); + + JS::Rooted<JS::Value> eventRecord(aCx); + ASSERT_TRUE(JS_GetElement(aCx, arrayObj, i++, &eventRecord)) + << "Must be able to get record."; // record is already undefined :-/ + + ASSERT_TRUE(!eventRecord.isUndefined()) + << "eventRecord should not be undefined"; + + JS::RootedObject recordArray(aCx, &eventRecord.toObject()); + uint32_t recordLength; + ASSERT_TRUE(JS::GetArrayLength(aCx, recordArray, &recordLength)) + << "Event record array must have length."; + ASSERT_TRUE(recordLength == 6) + << "Event record must have 6 elements."; + + JS::Rooted<JS::Value> str(aCx); + nsAutoJSString jsStr; + // The fileinfo string is at index 4 + ASSERT_TRUE(JS_GetElement(aCx, recordArray, 4, &str)) + << "Must be able to get value."; + ASSERT_TRUE(jsStr.init(aCx, str)) + << "Value must be able to be init'd to a jsstring."; + + ASSERT_STREQ(NS_ConvertUTF16toUTF8(jsStr).get(), + currentTest.expected.fileinfo.get()) + << "Reported fileinfo equals supplied value"; + + // Extra is at index 5 + JS::Rooted<JS::Value> obj(aCx); + ASSERT_TRUE(JS_GetElement(aCx, recordArray, 5, &obj)) + << "Must be able to get extra."; + JS::RootedObject extraObj(aCx, &obj.toObject()); + // looking at remotetype extra for content type + JS::Rooted<JS::Value> extraValC(aCx); + ASSERT_TRUE( + JS_GetProperty(aCx, extraObj, extraKeyContenttype.get(), &extraValC)) + << "Must be able to get the extra key's value for contenttype"; + ASSERT_TRUE(jsStr.init(aCx, extraValC)) + << "Extra value contenttype must be able to be init'd to a jsstring."; + ASSERT_STREQ(NS_ConvertUTF16toUTF8(jsStr).get(), + currentTest.expected.extraValueContenttype.get()) + << "Reported value for extra contenttype should equals supplied value"; + // and again for remote type + JS::Rooted<JS::Value> extraValP(aCx); + ASSERT_TRUE( + JS_GetProperty(aCx, extraObj, extraKeyRemotetype.get(), &extraValP)) + << "Must be able to get the extra key's value for remotetype"; + ASSERT_TRUE(jsStr.init(aCx, extraValP)) + << "Extra value remotetype must be able to be init'd to a jsstring."; + ASSERT_STREQ(NS_ConvertUTF16toUTF8(jsStr).get(), + currentTest.expected.extraValueRemotetype.get()) + << "Reported value for extra remotetype should equals supplied value"; + // repeating the same for filedetails extra + JS::Rooted<JS::Value> extraValF(aCx); + ASSERT_TRUE( + JS_GetProperty(aCx, extraObj, extraKeyFiledetails.get(), &extraValF)) + << "Must be able to get the extra key's value for filedetails"; + ASSERT_TRUE(jsStr.init(aCx, extraValF)) + << "Extra value filedetails must be able to be init'd to a jsstring."; + ASSERT_STREQ(NS_ConvertUTF16toUTF8(jsStr).get(), + currentTest.expected.extraValueFiledetails.get()) + << "Reported value for extra filedetails should equals supplied value"; + } +} |