Bug 1407258: Dowgrade document loads with expanded principals to their last sub-principal. r?bz
There are currently some corner cases where channels that are eventually
loaded into documents (mainly <img src="data:image/svg+xml,") can inherit
expanded principals from a caller. Since documents aren't allowed to have
expanded principals, this causes crashes.
This patch is a short term workaround for the issue, until we have a longer
term solution that prevents the channels from inheriting the expanded
principals to begin with.
MozReview-Commit-ID: JwqqtVynLjj
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -106,16 +106,17 @@
#include "nsNetUtil.h" // for NS_NewURI
#include "nsIInputStreamChannel.h"
#include "nsIAuthPrompt.h"
#include "nsIAuthPrompt2.h"
#include "nsIScriptSecurityManager.h"
#include "nsIPermissionManager.h"
#include "nsIPrincipal.h"
+#include "ExpandedPrincipal.h"
#include "NullPrincipal.h"
#include "nsIDOMWindow.h"
#include "nsPIDOMWindow.h"
#include "nsIDOMElement.h"
#include "nsFocusManager.h"
// for radio group stuff
@@ -2481,16 +2482,30 @@ nsDocument::ResetToURI(nsIURI *aURI, nsI
already_AddRefed<nsIPrincipal>
nsDocument::MaybeDowngradePrincipal(nsIPrincipal* aPrincipal)
{
if (!aPrincipal) {
return nullptr;
}
+ // We can't load a document with an expanded principal. If we're given one,
+ // automatically downgrade it to the last principal it subsumes (which is the
+ // extension principal, in the case of extension content scripts).
+ auto* basePrin = BasePrincipal::Cast(aPrincipal);
+ if (basePrin->Is<ExpandedPrincipal>()) {
+ auto* expanded = basePrin->As<ExpandedPrincipal>();
+
+ nsTArray<nsCOMPtr<nsIPrincipal>>* whitelist;
+ MOZ_ALWAYS_SUCCEEDS(expanded->GetWhiteList(&whitelist));
+ MOZ_ASSERT(whitelist->Length() > 0);
+
+ return do_AddRef(whitelist->LastElement().get());
+ }
+
if (!sChromeInContentPrefCached) {
sChromeInContentPrefCached = true;
Preferences::AddBoolVarCache(&sChromeInContentAllowed,
kChromeInContentPref, false);
}
if (!sChromeInContentAllowed &&
nsContentUtils::IsSystemPrincipal(aPrincipal)) {
// We basically want the parent document here, but because this is very
--- a/toolkit/components/extensions/test/xpcshell/test_ext_contentscript_triggeringPrincipal.js
+++ b/toolkit/components/extensions/test/xpcshell/test_ext_contentscript_triggeringPrincipal.js
@@ -253,16 +253,22 @@ function toHTML(test, opts) {
* A list of test objects, as understood by {@see getElementData}.
* @param {ElementTestOptions} baseOpts
* A base options object, as understood by {@see getElementData},
* which represents the default values for injections under this
* context.
*/
function injectElements(tests, baseOpts) {
window.addEventListener("load", () => {
+ // Basic smoke test to check that SVG images do not try to create a document
+ // with an expanded principal, which would cause a crash.
+ let img = document.createElement("img");
+ img.src = "data:image/svg+xml,%3Csvg%2F%3E";
+ document.body.appendChild(img);
+
let overrideOpts = opts => Object.assign({}, baseOpts, opts);
let opts = baseOpts;
// Build the full element with setAttr, then inject.
for (let test of tests) {
let {elem, srcElem, src} = createElement(test, opts);
srcElem.setAttribute(test.srcAttr, src);
document.body.appendChild(elem);