Bug 1608970 - Record the addon name, id, and filepath of javascript files loaded into the parent process r=mixedpuppy,ckerschb

Differential Revision: https://phabricator.services.mozilla.com/D60186

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Tom Ritter 2020-02-26 18:01:28 +00:00
parent 7229e0ca1f
commit 265c831dd7
3 changed files with 157 additions and 29 deletions

View File

@ -19,6 +19,7 @@
#endif
#include "js/Array.h" // JS::GetArrayLength
#include "mozilla/ExtensionPolicyService.h"
#include "mozilla/Logging.h"
#include "mozilla/dom/Document.h"
#include "mozilla/StaticPrefs_extensions.h"
@ -150,7 +151,7 @@ nsString OptimizeFileName(const nsAString& aFileName) {
/* static */
FilenameTypeAndDetails nsContentSecurityUtils::FilenameToFilenameType(
const nsString& fileName) {
const nsString& fileName, bool collectAdditionalExtensionData) {
// These are strings because the Telemetry Events API only accepts strings
static NS_NAMED_LITERAL_CSTRING(kChromeURI, "chromeuri");
static NS_NAMED_LITERAL_CSTRING(kResourceURI, "resourceuri");
@ -249,6 +250,40 @@ FilenameTypeAndDetails nsContentSecurityUtils::FilenameToFilenameType(
if (sanitizedPathAndScheme == NS_LITERAL_STRING("file")) {
sanitizedPathAndScheme.Append(NS_LITERAL_STRING("://.../"));
sanitizedPathAndScheme.Append(strSanitizedPath);
} else if (sanitizedPathAndScheme == NS_LITERAL_STRING("moz-extension") &&
collectAdditionalExtensionData) {
sanitizedPathAndScheme.Append(NS_LITERAL_STRING("://["));
nsCOMPtr<nsIURI> uri;
nsresult rv = NS_NewURI(getter_AddRefs(uri), fileName);
if (NS_FAILED(rv)) {
// Return after adding ://[ so we know we failed here.
return FilenameTypeAndDetails(kSanitizedWindowsURL,
Some(sanitizedPathAndScheme));
}
mozilla::extensions::URLInfo url(uri);
if (NS_IsMainThread()) {
// EPS is only usable on main thread
auto* policy =
ExtensionPolicyService::GetSingleton().GetByHost(url.Host());
if (policy) {
nsString addOnId;
policy->GetId(addOnId);
sanitizedPathAndScheme.Append(addOnId);
sanitizedPathAndScheme.Append(NS_LITERAL_STRING(": "));
sanitizedPathAndScheme.Append(policy->Name());
} else {
sanitizedPathAndScheme.Append(
NS_LITERAL_STRING("failed finding addon by host"));
}
} else {
sanitizedPathAndScheme.Append(
NS_LITERAL_STRING("can't get addon off main thread"));
}
sanitizedPathAndScheme.Append(NS_LITERAL_STRING("]"));
sanitizedPathAndScheme.Append(url.FilePath());
}
return FilenameTypeAndDetails(kSanitizedWindowsURL,
Some(sanitizedPathAndScheme));
@ -488,7 +523,7 @@ void nsContentSecurityUtils::NotifyEvalUsage(bool aIsSystemPrincipal,
: Telemetry::EventID::Security_Evalusage_Parentprocess;
FilenameTypeAndDetails fileNameTypeAndDetails =
FilenameToFilenameType(aFileNameA);
FilenameToFilenameType(aFileNameA, false);
mozilla::Maybe<nsTArray<EventExtraEntry>> extra;
if (fileNameTypeAndDetails.second().isSome()) {
extra = Some<nsTArray<EventExtraEntry>>({EventExtraEntry{
@ -792,7 +827,7 @@ bool nsContentSecurityUtils::ValidateScriptFilename(const char* aFilename,
// Send Telemetry
FilenameTypeAndDetails fileNameTypeAndDetails =
FilenameToFilenameType(filenameU);
FilenameToFilenameType(filenameU, true);
Telemetry::EventID eventType =
Telemetry::EventID::Security_Javascriptload_Parentprocess;

View File

@ -24,7 +24,7 @@ typedef mozilla::Pair<nsCString, mozilla::Maybe<nsString>>
class nsContentSecurityUtils {
public:
static FilenameTypeAndDetails FilenameToFilenameType(
const nsString& fileName);
const nsString& fileName, bool collectAdditionalExtensionData);
static bool IsEvalAllowed(JSContext* cx, bool aIsSystemPrincipal,
const nsAString& aScript);
static void NotifyEvalUsage(bool aIsSystemPrincipal,

View File

@ -12,6 +12,11 @@
#include "nsContentSecurityUtils.h"
#include "nsStringFwd.h"
#include "mozilla/ExtensionPolicyService.h"
#include "mozilla/dom/ScriptSettings.h"
#include "mozilla/dom/SimpleGlobalObject.h"
#include "mozilla/extensions/WebExtensionPolicy.h"
static NS_NAMED_LITERAL_CSTRING(kChromeURI, "chromeuri");
static NS_NAMED_LITERAL_CSTRING(kResourceURI, "resourceuri");
static NS_NAMED_LITERAL_CSTRING(kBlobUri, "bloburi");
@ -29,20 +34,21 @@ static NS_NAMED_LITERAL_CSTRING(kOther, "other");
fprintf(stderr, "First: %s\n", first.get()); \
fprintf(stderr, "Second: %s\n", NS_ConvertUTF16toUTF8(second).get()); \
ASSERT_TRUE((condition));
// Usage: ASSERT_AND_PRINT(ret.first(), ret.second().value(), ...
TEST(FilenameEvalParser, ResourceChrome)
{
{
NS_NAMED_LITERAL_STRING(str, "chrome://firegestures/content/browser.js");
FilenameTypeAndDetails ret =
nsContentSecurityUtils::FilenameToFilenameType(str);
nsContentSecurityUtils::FilenameToFilenameType(str, false);
ASSERT_TRUE(ret.first() == kChromeURI && ret.second().isSome() &&
ret.second().value() == str);
}
{
NS_NAMED_LITERAL_STRING(str, "resource://firegestures/content/browser.js");
FilenameTypeAndDetails ret =
nsContentSecurityUtils::FilenameToFilenameType(str);
nsContentSecurityUtils::FilenameToFilenameType(str, false);
ASSERT_TRUE(ret.first() == kResourceURI && ret.second().isSome() &&
ret.second().value() == str);
}
@ -53,25 +59,25 @@ TEST(FilenameEvalParser, BlobData)
{
NS_NAMED_LITERAL_STRING(str, "blob://000-000");
FilenameTypeAndDetails ret =
nsContentSecurityUtils::FilenameToFilenameType(str);
nsContentSecurityUtils::FilenameToFilenameType(str, false);
ASSERT_TRUE(ret.first() == kBlobUri && !ret.second().isSome());
}
{
NS_NAMED_LITERAL_STRING(str, "blob:000-000");
FilenameTypeAndDetails ret =
nsContentSecurityUtils::FilenameToFilenameType(str);
nsContentSecurityUtils::FilenameToFilenameType(str, false);
ASSERT_TRUE(ret.first() == kBlobUri && !ret.second().isSome());
}
{
NS_NAMED_LITERAL_STRING(str, "data://blahblahblah");
FilenameTypeAndDetails ret =
nsContentSecurityUtils::FilenameToFilenameType(str);
nsContentSecurityUtils::FilenameToFilenameType(str, false);
ASSERT_TRUE(ret.first() == kDataUri && !ret.second().isSome());
}
{
NS_NAMED_LITERAL_STRING(str, "data:blahblahblah");
FilenameTypeAndDetails ret =
nsContentSecurityUtils::FilenameToFilenameType(str);
nsContentSecurityUtils::FilenameToFilenameType(str, false);
ASSERT_TRUE(ret.first() == kDataUri && !ret.second().isSome());
}
}
@ -85,7 +91,7 @@ TEST(FilenameEvalParser, MozExtension)
"extensions/federated-learning@shield.mozilla.org.xpi!/experiments/"
"study/api.js");
FilenameTypeAndDetails ret =
nsContentSecurityUtils::FilenameToFilenameType(str);
nsContentSecurityUtils::FilenameToFilenameType(str, false);
ASSERT_TRUE(ret.first() == kMozillaExtension &&
ret.second().value() ==
NS_LITERAL_STRING(
@ -98,7 +104,7 @@ TEST(FilenameEvalParser, MozExtension)
"extensions/federated-learning@shigeld.mozilla.org.xpi!/experiments/"
"study/api.js");
FilenameTypeAndDetails ret =
nsContentSecurityUtils::FilenameToFilenameType(str);
nsContentSecurityUtils::FilenameToFilenameType(str, false);
ASSERT_TRUE(
ret.first() == kMozillaExtension &&
ret.second().value() ==
@ -112,7 +118,7 @@ TEST(FilenameEvalParser, MozExtension)
"extensions/federated-learning@shigeld.mozilla.org.xpi!/experiments/"
"study/apiiiiiiiiiiiiiiiiiiiiiiiiiiiiii.js");
FilenameTypeAndDetails ret =
nsContentSecurityUtils::FilenameToFilenameType(str);
nsContentSecurityUtils::FilenameToFilenameType(str, false);
ASSERT_TRUE(
ret.first() == kMozillaExtension &&
ret.second().value() ==
@ -126,14 +132,14 @@ TEST(FilenameEvalParser, UserChromeJS)
{
NS_NAMED_LITERAL_STRING(str, "firegestures/content/browser.uc.js");
FilenameTypeAndDetails ret =
nsContentSecurityUtils::FilenameToFilenameType(str);
nsContentSecurityUtils::FilenameToFilenameType(str, false);
ASSERT_TRUE(ret.first() == kSuspectedUserChromeJS &&
!ret.second().isSome());
}
{
NS_NAMED_LITERAL_STRING(str, "firegestures/content/browser.uc.js?");
FilenameTypeAndDetails ret =
nsContentSecurityUtils::FilenameToFilenameType(str);
nsContentSecurityUtils::FilenameToFilenameType(str, false);
ASSERT_TRUE(ret.first() == kSuspectedUserChromeJS &&
!ret.second().isSome());
}
@ -141,7 +147,7 @@ TEST(FilenameEvalParser, UserChromeJS)
nsLiteralString str =
NS_LITERAL_STRING("firegestures/content/browser.uc.js?243244224");
FilenameTypeAndDetails ret =
nsContentSecurityUtils::FilenameToFilenameType(str);
nsContentSecurityUtils::FilenameToFilenameType(str, false);
ASSERT_TRUE(ret.first() == kSuspectedUserChromeJS &&
!ret.second().isSome());
}
@ -151,7 +157,7 @@ TEST(FilenameEvalParser, UserChromeJS)
"file:///b:/fxprofiles/mark/chrome/"
"addbookmarkherewithmiddleclick.uc.js?1558444389291");
FilenameTypeAndDetails ret =
nsContentSecurityUtils::FilenameToFilenameType(str);
nsContentSecurityUtils::FilenameToFilenameType(str, false);
ASSERT_TRUE(ret.first() == kSuspectedUserChromeJS &&
!ret.second().isSome());
}
@ -162,14 +168,14 @@ TEST(FilenameEvalParser, SingleFile)
{
NS_NAMED_LITERAL_STRING(str, "browser.uc.js?2456");
FilenameTypeAndDetails ret =
nsContentSecurityUtils::FilenameToFilenameType(str);
nsContentSecurityUtils::FilenameToFilenameType(str, false);
ASSERT_TRUE(ret.first() == kSingleString && ret.second().isSome() &&
ret.second().value() == str);
}
{
NS_NAMED_LITERAL_STRING(str, "debugger");
FilenameTypeAndDetails ret =
nsContentSecurityUtils::FilenameToFilenameType(str);
nsContentSecurityUtils::FilenameToFilenameType(str, false);
ASSERT_TRUE(ret.first() == kSingleString && ret.second().isSome() &&
ret.second().value() == str);
}
@ -180,13 +186,13 @@ TEST(FilenameEvalParser, Other)
{
NS_NAMED_LITERAL_STRING(str, "firegestures--content");
FilenameTypeAndDetails ret =
nsContentSecurityUtils::FilenameToFilenameType(str);
nsContentSecurityUtils::FilenameToFilenameType(str, false);
ASSERT_TRUE(ret.first() == kOther && !ret.second().isSome());
}
{
NS_NAMED_LITERAL_STRING(str, "gallop://thing/fire");
FilenameTypeAndDetails ret =
nsContentSecurityUtils::FilenameToFilenameType(str);
nsContentSecurityUtils::FilenameToFilenameType(str, false);
#if defined(XP_WIN)
ASSERT_TRUE(ret.first() == kSanitizedWindowsURL &&
ret.second().value() == NS_LITERAL_STRING("gallop"));
@ -197,7 +203,7 @@ TEST(FilenameEvalParser, Other)
{
NS_NAMED_LITERAL_STRING(str, "gallop://fire");
FilenameTypeAndDetails ret =
nsContentSecurityUtils::FilenameToFilenameType(str);
nsContentSecurityUtils::FilenameToFilenameType(str, false);
#if defined(XP_WIN)
ASSERT_TRUE(ret.first() == kSanitizedWindowsURL &&
ret.second().value() == NS_LITERAL_STRING("gallop"));
@ -208,7 +214,7 @@ TEST(FilenameEvalParser, Other)
{
NS_NAMED_LITERAL_STRING(str, "firegestures/content");
FilenameTypeAndDetails ret =
nsContentSecurityUtils::FilenameToFilenameType(str);
nsContentSecurityUtils::FilenameToFilenameType(str, false);
#if defined(XP_WIN)
ASSERT_TRUE(ret.first() == kSanitizedWindowsPath &&
ret.second().value() == NS_LITERAL_STRING("content"));
@ -219,7 +225,7 @@ TEST(FilenameEvalParser, Other)
{
NS_NAMED_LITERAL_STRING(str, "firegestures\\content");
FilenameTypeAndDetails ret =
nsContentSecurityUtils::FilenameToFilenameType(str);
nsContentSecurityUtils::FilenameToFilenameType(str, false);
#if defined(XP_WIN)
ASSERT_TRUE(ret.first() == kSanitizedWindowsPath &&
ret.second().value() == NS_LITERAL_STRING("content"));
@ -230,7 +236,7 @@ TEST(FilenameEvalParser, Other)
{
NS_NAMED_LITERAL_STRING(str, "/home/tom/files/thing");
FilenameTypeAndDetails ret =
nsContentSecurityUtils::FilenameToFilenameType(str);
nsContentSecurityUtils::FilenameToFilenameType(str, false);
#if defined(XP_WIN)
ASSERT_TRUE(ret.first() == kSanitizedWindowsPath &&
ret.second().value() == NS_LITERAL_STRING("thing"));
@ -241,7 +247,7 @@ TEST(FilenameEvalParser, Other)
{
NS_NAMED_LITERAL_STRING(str, "file://c/uers/tom/file.txt");
FilenameTypeAndDetails ret =
nsContentSecurityUtils::FilenameToFilenameType(str);
nsContentSecurityUtils::FilenameToFilenameType(str, false);
#if defined(XP_WIN)
ASSERT_TRUE(ret.first() == kSanitizedWindowsURL &&
ret.second().value() ==
@ -253,7 +259,7 @@ TEST(FilenameEvalParser, Other)
{
NS_NAMED_LITERAL_STRING(str, "c:/uers/tom/file.txt");
FilenameTypeAndDetails ret =
nsContentSecurityUtils::FilenameToFilenameType(str);
nsContentSecurityUtils::FilenameToFilenameType(str, false);
#if defined(XP_WIN)
ASSERT_TRUE(ret.first() == kSanitizedWindowsPath &&
ret.second().value() == NS_LITERAL_STRING("file.txt"));
@ -264,7 +270,7 @@ TEST(FilenameEvalParser, Other)
{
NS_NAMED_LITERAL_STRING(str, "http://example.com/");
FilenameTypeAndDetails ret =
nsContentSecurityUtils::FilenameToFilenameType(str);
nsContentSecurityUtils::FilenameToFilenameType(str, false);
#if defined(XP_WIN)
ASSERT_TRUE(ret.first() == kSanitizedWindowsURL &&
ret.second().value() == NS_LITERAL_STRING("http"));
@ -275,7 +281,7 @@ TEST(FilenameEvalParser, Other)
{
NS_NAMED_LITERAL_STRING(str, "http://example.com/thing.html");
FilenameTypeAndDetails ret =
nsContentSecurityUtils::FilenameToFilenameType(str);
nsContentSecurityUtils::FilenameToFilenameType(str, false);
#if defined(XP_WIN)
ASSERT_TRUE(ret.first() == kSanitizedWindowsURL &&
ret.second().value() == NS_LITERAL_STRING("http"));
@ -284,3 +290,90 @@ TEST(FilenameEvalParser, Other)
#endif
}
}
#if defined(XP_WIN)
TEST(FilenameEvalParser, WebExtensionPathParser)
{
{
// Set up an Extension and register it so we can test against it.
mozilla::dom::AutoJSAPI jsAPI;
ASSERT_TRUE(jsAPI.Init(xpc::PrivilegedJunkScope()));
JSContext* cx = jsAPI.cx();
mozilla::dom::GlobalObject go(cx, xpc::PrivilegedJunkScope());
auto wEI = new mozilla::extensions::WebExtensionInit();
JS::Rooted<JSObject*> func(
cx, (JSObject*)JS_NewFunction(cx, (JSNative)1, 0, 0, "customMethodA"));
JS::Rooted<JSObject*> tempGlobalRoot(cx, JS::CurrentGlobalOrNull(cx));
wEI->mLocalizeCallback = new mozilla::dom::WebExtensionLocalizeCallback(
cx, func, tempGlobalRoot, NULL);
wEI->mAllowedOrigins =
mozilla::dom::OwningMatchPatternSetOrStringSequence();
nsString* slotPtr =
wEI->mAllowedOrigins.SetAsStringSequence().AppendElement(
mozilla::fallible);
nsString& slot = *slotPtr;
slot.Truncate();
slot = NS_LITERAL_STRING("http://example.com");
wEI->mName = NS_LITERAL_STRING("gtest Test Extension");
wEI->mId = NS_LITERAL_STRING("gtesttestextension@mozilla.org");
wEI->mBaseURL = NS_LITERAL_STRING("file://foo");
wEI->mMozExtensionHostname =
NS_LITERAL_CSTRING("e37c3c08-beac-a04b-8032-c4f699a1a856");
mozilla::ErrorResult eR;
RefPtr<mozilla::WebExtensionPolicy> w =
mozilla::extensions::WebExtensionPolicy::Constructor(go, *wEI, eR);
w->SetActive(true, eR);
NS_NAMED_LITERAL_STRING(
str,
"moz-extension://e37c3c08-beac-a04b-8032-c4f699a1a856/path/to/file.js");
FilenameTypeAndDetails ret =
nsContentSecurityUtils::FilenameToFilenameType(str, true);
ASSERT_TRUE(ret.first() == kSanitizedWindowsURL &&
ret.second().value() ==
NS_LITERAL_STRING(
"moz-extension://[gtesttestextension@mozilla.org: "
"gtest Test Extension]/path/to/file.js"));
w->SetActive(false, eR);
}
{
NS_NAMED_LITERAL_STRING(
str,
"moz-extension://e37c3c08-beac-a04b-8032-c4f699a1a856/path/to/file.js");
FilenameTypeAndDetails ret =
nsContentSecurityUtils::FilenameToFilenameType(str, false);
ASSERT_TRUE(ret.first() == kSanitizedWindowsURL &&
ret.second().value() == NS_LITERAL_STRING("moz-extension"));
}
{
NS_NAMED_LITERAL_STRING(
str, "moz-extension://e37c3c08-beac-a04b-8032-c4f699a1a856/file.js");
FilenameTypeAndDetails ret =
nsContentSecurityUtils::FilenameToFilenameType(str, true);
ASSERT_TRUE(
ret.first() == kSanitizedWindowsURL &&
ret.second().value() ==
NS_LITERAL_STRING(
"moz-extension://[failed finding addon by host]/file.js"));
}
{
NS_NAMED_LITERAL_STRING(
str,
"moz-extension://e37c3c08-beac-a04b-8032-c4f699a1a856/path/to/"
"file.js?querystringx=6");
FilenameTypeAndDetails ret =
nsContentSecurityUtils::FilenameToFilenameType(str, true);
ASSERT_TRUE(ret.first() == kSanitizedWindowsURL &&
ret.second().value() ==
NS_LITERAL_STRING("moz-extension://[failed finding addon "
"by host]/path/to/file.js"));
}
}
#endif