зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1578231: Hardcode whitelist of about: pages where we can not apply a CSP. r=jkt
Differential Revision: https://phabricator.services.mozilla.com/D44617 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
4bf8a96317
Коммит
4e4f4a0bf6
|
@ -18,8 +18,6 @@
|
|||
void nsContentSecurityUtils::AssertAboutPageHasCSP(Document* aDocument) {
|
||||
// We want to get to a point where all about: pages ship with a CSP. This
|
||||
// assertion ensures that we can not deploy new about: pages without a CSP.
|
||||
// Initially we will whitelist legacy about: pages which not yet have a CSP
|
||||
// attached, but ultimately that whitelist should disappear.
|
||||
// Please note that any about: page should not use inline JS or inline CSS,
|
||||
// and instead should load JS and CSS from an external file (*.js, *.css)
|
||||
// which allows us to apply a strong CSP omitting 'unsafe-inline'. Ideally,
|
||||
|
@ -27,43 +25,15 @@ void nsContentSecurityUtils::AssertAboutPageHasCSP(Document* aDocument) {
|
|||
// should at least be as strong as:
|
||||
// <meta http-equiv="Content-Security-Policy" content="default-src chrome:"/>
|
||||
|
||||
// Check if we are loading an about: URI at all
|
||||
nsCOMPtr<nsIURI> documentURI = aDocument->GetDocumentURI();
|
||||
if (!documentURI->SchemeIs("about") ||
|
||||
Preferences::GetBool("csp.skip_about_page_has_csp_assert")) {
|
||||
// Check if we should skip the assertion
|
||||
if (Preferences::GetBool("csp.skip_about_page_has_csp_assert")) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Potentially init the legacy whitelist of about URIs without a CSP.
|
||||
static StaticAutoPtr<nsTArray<nsCString>> sLegacyAboutPagesWithNoCSP;
|
||||
if (!sLegacyAboutPagesWithNoCSP ||
|
||||
Preferences::GetBool("csp.overrule_about_uris_without_csp_whitelist")) {
|
||||
sLegacyAboutPagesWithNoCSP = new nsTArray<nsCString>();
|
||||
nsAutoCString legacyAboutPages;
|
||||
Preferences::GetCString("csp.about_uris_without_csp", legacyAboutPages);
|
||||
for (const nsACString& hostString : legacyAboutPages.Split(',')) {
|
||||
// please note that for the actual whitelist we only store the path of
|
||||
// about: URI. Let's reassemble the full about URI here so we don't
|
||||
// have to remove query arguments later.
|
||||
nsCString aboutURI;
|
||||
aboutURI.AppendLiteral("about:");
|
||||
aboutURI.Append(hostString);
|
||||
sLegacyAboutPagesWithNoCSP->AppendElement(aboutURI);
|
||||
}
|
||||
ClearOnShutdown(&sLegacyAboutPagesWithNoCSP);
|
||||
}
|
||||
|
||||
// Check if the about URI is whitelisted
|
||||
nsAutoCString aboutSpec;
|
||||
documentURI->GetSpec(aboutSpec);
|
||||
ToLowerCase(aboutSpec);
|
||||
for (auto& legacyPageEntry : *sLegacyAboutPagesWithNoCSP) {
|
||||
// please note that we perform a substring match here on purpose,
|
||||
// so we don't have to deal and parse out all the query arguments
|
||||
// the various about pages rely on.
|
||||
if (aboutSpec.Find(legacyPageEntry) == 0) {
|
||||
return;
|
||||
}
|
||||
// Check if we are loading an about: URI at all
|
||||
nsCOMPtr<nsIURI> documentURI = aDocument->GetDocumentURI();
|
||||
if (!documentURI->SchemeIs("about")) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIContentSecurityPolicy> csp = aDocument->GetCsp();
|
||||
|
@ -80,10 +50,44 @@ void nsContentSecurityUtils::AssertAboutPageHasCSP(Document* aDocument) {
|
|||
}
|
||||
}
|
||||
}
|
||||
if (Preferences::GetBool("csp.overrule_about_uris_without_csp_whitelist")) {
|
||||
|
||||
// Check if we should skip the allowlist and assert right away. Please note
|
||||
// that this pref can and should only be set for automated testing.
|
||||
if (Preferences::GetBool("csp.skip_about_page_csp_allowlist_and_assert")) {
|
||||
NS_ASSERTION(foundDefaultSrc, "about: page must have a CSP");
|
||||
return;
|
||||
}
|
||||
|
||||
nsAutoCString aboutSpec;
|
||||
documentURI->GetSpec(aboutSpec);
|
||||
ToLowerCase(aboutSpec);
|
||||
|
||||
// This allowlist contains about: pages that are permanently allowed to
|
||||
// render without a CSP applied.
|
||||
static nsLiteralCString sAllowedAboutPagesWithNoCSP[] = {
|
||||
// about:blank is a special about page -> no CSP
|
||||
NS_LITERAL_CSTRING("about:blank"),
|
||||
// about:srcdoc is a special about page -> no CSP
|
||||
NS_LITERAL_CSTRING("about:srcdoc"),
|
||||
// about:sync-log displays plain text only -> no CSP
|
||||
NS_LITERAL_CSTRING("about:sync-log"),
|
||||
// about:printpreview displays plain text only -> no CSP
|
||||
NS_LITERAL_CSTRING("about:printpreview"),
|
||||
// Bug 1497200: Apply Meta CSP to about:downloads
|
||||
NS_LITERAL_CSTRING("about:downloads"),
|
||||
// Bug 1497584: Apply Meta CSP to about:preferences
|
||||
NS_LITERAL_CSTRING("about:preferences"),
|
||||
};
|
||||
|
||||
for (const nsLiteralCString& allowlistEntry : sAllowedAboutPagesWithNoCSP) {
|
||||
// please note that we perform a substring match here on purpose,
|
||||
// so we don't have to deal and parse out all the query arguments
|
||||
// the various about pages rely on.
|
||||
if (StringBeginsWith(aboutSpec, allowlistEntry)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
MOZ_ASSERT(foundDefaultSrc,
|
||||
"about: page must contain a CSP including default-src");
|
||||
}
|
||||
|
|
|
@ -9,31 +9,20 @@
|
|||
<iframe id="testframe"></iframe>
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
// Test Setup: The test overrules the allowlist of about: pages that are allowed to load
|
||||
// without a CSP and makes sure to hit the assertion within AssertAboutPageHasCSP().
|
||||
|
||||
SpecialPowers.setBoolPref("csp.skip_about_page_csp_allowlist_and_assert", true);
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SimpleTest.expectAssertions(0, 1);
|
||||
|
||||
// Test Setup:
|
||||
// The test overrules the whitelist of about: pages that are allowed to load without a CSP
|
||||
// and makes sure to hit the assertion within AssertAboutPageHasCSP().
|
||||
// However, due to the caching mechanism within AssertAboutPageHasCSP this
|
||||
// test loads a second dummy data: URI to reset the old cache and finally resets the pref
|
||||
// used for testing purposes.
|
||||
|
||||
let origWhiteList = SpecialPowers.getCharPref("csp.about_uris_without_csp");
|
||||
|
||||
SpecialPowers.setCharPref("csp.about_uris_without_csp", "");
|
||||
SpecialPowers.setBoolPref("csp.overrule_about_uris_without_csp_whitelist", true);
|
||||
|
||||
ok(true, "sanity: prefs flipped and test runs");
|
||||
let myFrame = document.getElementById("testframe");
|
||||
myFrame.src = "about:blank";
|
||||
// booom :-)
|
||||
|
||||
SpecialPowers.setCharPref("csp.about_uris_without_csp", origWhiteList);
|
||||
myFrame.src = "data:text/html,<body>just a dumy data: URI</body>";
|
||||
|
||||
SpecialPowers.setBoolPref("csp.overrule_about_uris_without_csp_whitelist", false);
|
||||
|
||||
SpecialPowers.setBoolPref("csp.skip_about_page_csp_allowlist_and_assert", false);
|
||||
SimpleTest.finish();
|
||||
</script>
|
||||
</pre>
|
||||
|
|
|
@ -2254,10 +2254,13 @@ pref("security.dialog_enable_delay", 1000);
|
|||
pref("security.notification_enable_delay", 500);
|
||||
|
||||
#if defined(DEBUG) && !defined(ANDROID)
|
||||
pref("csp.about_uris_without_csp", "blank,printpreview,srcdoc,downloads,preferences,sync-log");
|
||||
// the following prefs are for testing purposes only.
|
||||
pref("csp.overrule_about_uris_without_csp_whitelist", false);
|
||||
// For testing purposes only: Flipping this pref to true allows
|
||||
// to skip the assertion that every about page ships with a CSP.
|
||||
pref("csp.skip_about_page_has_csp_assert", false);
|
||||
// For testing purposes only: Flipping this pref to true allows
|
||||
// to skip the allowlist for about: pages and do not ship with a
|
||||
// CSP and NS_ASSERT right away.
|
||||
pref("csp.skip_about_page_csp_allowlist_and_assert", false);
|
||||
#endif
|
||||
|
||||
#ifdef EARLY_BETA_OR_EARLIER
|
||||
|
|
Загрузка…
Ссылка в новой задаче