summaryrefslogtreecommitdiffstats
path: root/dom/security/test/gtest/TestUnexpectedPrivilegedLoads.cpp
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 14:29:10 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 14:29:10 +0000
commit2aa4a82499d4becd2284cdb482213d541b8804dd (patch)
treeb80bf8bf13c3766139fbacc530efd0dd9d54394c /dom/security/test/gtest/TestUnexpectedPrivilegedLoads.cpp
parentInitial commit. (diff)
downloadfirefox-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.cpp197
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";
+ }
+}