Issue #2736 - Part 1: Provide more consistent principals to CSP.

We're currently fairly vague and inconsistent about the values we provide to
content policy implementations for requestOrigin and requestPrincipal. In some
cases they're the triggering principal, sometimes the loading principal,
sometimes the channel principal.

Our existing content policy implementations which require or expect a
loading principal currently retrieve it from the context node.
Since no current callers require the principal to be the loading
principal, and some already expect it to be the triggering principal
(which there's currently no other way to retrieve), a choice was made
to pass the triggering principal whenever possible, but use the loading
principal to determine the origin URL.
This commit is contained in:
Moonchild 2025-04-26 20:07:16 +02:00 committed by roytam1
commit 9ad680cfc4
18 changed files with 109 additions and 61 deletions

View file

@ -9951,6 +9951,9 @@ nsDocShell::InternalLoad(nsIURI* aURI,
int16_t shouldLoad = nsIContentPolicy::ACCEPT;
rv = NS_CheckContentLoadPolicy(contentType,
aURI,
// This is a top-level load, so the loading
// principal is null.
nullptr,
aTriggeringPrincipal,
requestingContext,
EmptyCString(), // mime guess

View file

@ -1556,7 +1556,8 @@ WebSocketImpl::Init(JSContext* aCx,
int16_t shouldLoad = nsIContentPolicy::ACCEPT;
aRv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_WEBSOCKET,
uri,
aPrincipal,
aPrincipal, // loading principal
aPrincipal, // triggering principal
originDoc,
EmptyCString(),
nullptr,

View file

@ -152,7 +152,7 @@ NS_CP_ContentTypeName(uint32_t contentType)
return NS_ERROR_FAILURE; \
\
return policy-> action (contentType, contentLocation, requestOrigin, \
context, mimeType, extra, originPrincipal, \
context, mimeType, extra, triggeringPrincipal, \
decision); \
PR_END_MACRO
@ -160,7 +160,7 @@ NS_CP_ContentTypeName(uint32_t contentType)
#define CHECK_CONTENT_POLICY_WITH_SERVICE(action, _policy) \
PR_BEGIN_MACRO \
return _policy-> action (contentType, contentLocation, requestOrigin, \
context, mimeType, extra, originPrincipal, \
context, mimeType, extra, triggeringPrincipal, \
decision); \
PR_END_MACRO
@ -173,14 +173,18 @@ NS_CP_ContentTypeName(uint32_t contentType)
#define CHECK_PRINCIPAL_AND_DATA(action) \
nsCOMPtr<nsIURI> requestOrigin; \
PR_BEGIN_MACRO \
if (originPrincipal) { \
if (loadingPrincipal) { \
nsCOMPtr<nsIScriptSecurityManager> secMan = aSecMan; \
if (!secMan) { \
secMan = do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID); \
} \
if (secMan) { \
bool isSystem; \
nsresult rv = secMan->IsSystemPrincipal(originPrincipal, \
/* We exempt most loads into any document with the system principal \
* from content policy checks, mostly as an optimization. Which means \
* that we need to apply this check to the loading principal, not the \
* principal that triggered the load. */ \
nsresult rv = secMan->IsSystemPrincipal(loadingPrincipal, \
&isSystem); \
NS_ENSURE_SUCCESS(rv, rv); \
if (isSystem && contentType != nsIContentPolicy::TYPE_DOCUMENT) { \
@ -203,31 +207,33 @@ NS_CP_ContentTypeName(uint32_t contentType)
dataPolicy-> action (externalType, contentLocation, \
requestOrigin, context, \
mimeType, extra, \
originPrincipal, decision); \
triggeringPrincipal, decision);\
} \
} \
} \
return NS_OK; \
} \
} \
nsresult rv = originPrincipal->GetURI(getter_AddRefs(requestOrigin)); \
nsresult rv = loadingPrincipal->GetURI(getter_AddRefs(requestOrigin)); \
NS_ENSURE_SUCCESS(rv, rv); \
} \
PR_END_MACRO
/**
* Alias for calling ShouldLoad on the content policy service. Parameters are
* the same as nsIContentPolicy::shouldLoad, except for the originPrincipal
* parameter, which should be non-null if possible, and the last two
* parameters, which can be used to pass in pointer to some useful services if
* the caller already has them. The origin URI to pass to shouldLoad will be
* the URI of originPrincipal, unless originPrincipal is null (in which case a
* null origin URI will be passed).
* the same as nsIContentPolicy::shouldLoad, except for the loadingPrincipal
* and triggeringPrincipal parameters (which should be non-null if possible,
* and have the same semantics as in LoadInfo), and the last two parameters,
* which can be used to pass in pointer to some useful services if the caller
* already has them. The origin URI to pass to shouldLoad will be the URI of
* loadingPrincipal, unless loadingPrincipal is null (in which case a null
* origin URI will be passed).
*/
inline nsresult
NS_CheckContentLoadPolicy(uint32_t contentType,
nsIURI *contentLocation,
nsIPrincipal *originPrincipal,
nsIPrincipal *loadingPrincipal,
nsIPrincipal *triggeringPrincipal,
nsISupports *context,
const nsACString &mimeType,
nsISupports *extra,
@ -244,17 +250,19 @@ NS_CheckContentLoadPolicy(uint32_t contentType,
/**
* Alias for calling ShouldProcess on the content policy service. Parameters
* are the same as nsIContentPolicy::shouldLoad, except for the originPrincipal
* parameter, which should be non-null if possible, and the last two
* parameters, which can be used to pass in pointer to some useful services if
* the caller already has them. The origin URI to pass to shouldLoad will be
* the URI of originPrincipal, unless originPrincipal is null (in which case a
* null origin URI will be passed).
* are the same as nsIContentPolicy::shouldLoad, except for the and
* triggeringPrincipal parameters (which should be non-null if possible, and
* have the same semantics as in nsLoadInfo), and the last parameter, which
* can be used to pass in a pointer to a useful service if the caller already
* has it. The origin URI to pass to shouldLoad will be the URI of
* loadingPrincipal, unless loadingPrincipal is null (in which case a null
* origin URI will be passed).
*/
inline nsresult
NS_CheckContentProcessPolicy(uint32_t contentType,
nsIURI *contentLocation,
nsIPrincipal *originPrincipal,
nsIPrincipal *loadingPrincipal,
nsIPrincipal *triggeringPrincipal,
nsISupports *context,
const nsACString &mimeType,
nsISupports *extra,

View file

@ -3289,6 +3289,7 @@ nsContentUtils::CanLoadImage(nsIURI* aURI, nsISupports* aContext,
rv = NS_CheckContentLoadPolicy(aContentType,
aURI,
aLoadingPrincipal,
aLoadingPrincipal, // triggering principal
aContext,
EmptyCString(), //mime guess
nullptr, //extra

View file

@ -34,8 +34,11 @@ interface nsIContentPolicy : nsIContentPolicyBase
* not be null
*
* @param aRequestOrigin OPTIONAL. the location of the resource that
* initiated this load request; can be null if
* inapplicable
* that is loading the request. This will generally
* be the URI of the loading principal for the
* resulting request (as determined by its
* LoadInfo), but may vary depending on the
* caller. Can be null if inapplicable.
*
* @param aContext OPTIONAL. the nsIDOMNode or nsIDOMWindow that
* initiated the request, or something that can QI
@ -55,8 +58,12 @@ interface nsIContentPolicy : nsIContentPolicyBase
* @param aRequestPrincipal an OPTIONAL argument, defines the principal that
* caused the load. This is optional only for
* non-gecko code: all gecko code should set this
* argument. For navigation events, this is
* the principal of the page that caused this load.
* argument. This should generally be the same as
* the triggering principal for the resulting
* request (as determined by its LoadInfo), but may
* vary depending on the caller. Sometimes it will
* be the loading principal or final channel
* principal instead.
*
* @return ACCEPT or REJECT_*
*

View file

@ -1633,7 +1633,8 @@ nsObjectLoadingContent::CheckLoadPolicy(int16_t *aContentPolicy)
*aContentPolicy = nsIContentPolicy::ACCEPT;
nsresult rv = NS_CheckContentLoadPolicy(contentPolicyType,
mURI,
doc->NodePrincipal(),
doc->NodePrincipal(), // loading principal
doc->NodePrincipal(), // triggering principal
thisContent,
mContentType,
nullptr, //extra
@ -1684,7 +1685,8 @@ nsObjectLoadingContent::CheckProcessPolicy(int16_t *aContentPolicy)
nsresult rv =
NS_CheckContentProcessPolicy(objectType,
mURI ? mURI : mBaseURI,
doc->NodePrincipal(),
doc->NodePrincipal(), // loading principal
doc->NodePrincipal(), // triggering principal
static_cast<nsIImageLoadingContent*>(this),
mContentType,
nullptr, //extra

View file

@ -97,11 +97,14 @@ ImageListener::OnStartRequest(nsIRequest* request, nsISupports *ctxt)
if (secMan) {
secMan->GetChannelResultPrincipal(channel, getter_AddRefs(channelPrincipal));
}
nsCOMPtr<nsILoadInfo> loadInfo = channel->GetLoadInfo();
int16_t decision = nsIContentPolicy::ACCEPT;
nsresult rv = NS_CheckContentProcessPolicy(nsIContentPolicy::TYPE_INTERNAL_IMAGE,
channelURI,
channelPrincipal,
loadInfo ? loadInfo->TriggeringPrincipal() : nullptr,
domWindow->GetFrameElementInternal(),
mimeType,
nullptr,

View file

@ -505,7 +505,8 @@ nsPluginStreamListenerPeer::OnStartRequest(nsIRequest *request,
int16_t shouldLoad = nsIContentPolicy::ACCEPT;
rv = NS_CheckContentProcessPolicy(nsIContentPolicy::TYPE_OBJECT_SUBREQUEST,
mURL,
principal,
principal, // loading principal
principal, // triggering principal
element,
contentType,
nullptr,

View file

@ -448,7 +448,8 @@ ScriptLoader::CheckContentPolicy(nsIDocument* aDocument,
int16_t shouldLoad = nsIContentPolicy::ACCEPT;
nsresult rv = NS_CheckContentLoadPolicy(contentPolicyType,
aURI,
aDocument->NodePrincipal(),
aDocument->NodePrincipal(), // loading principal
aDocument->NodePrincipal(), // triggering principal
aContext,
NS_LossyConvertUTF16toASCII(aType),
nullptr, //extra

View file

@ -573,18 +573,11 @@ DoContentSecurityChecks(nsIChannel* aChannel, nsILoadInfo* aLoadInfo)
MOZ_ASSERT(false, "can not perform security check without a valid contentType");
}
// For document loads we use the triggeringPrincipal as the originPrincipal.
// Note the the loadingPrincipal for loads of TYPE_DOCUMENT is a nullptr.
nsCOMPtr<nsIPrincipal> principal =
(contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT ||
contentPolicyType == nsIContentPolicy::TYPE_SUBDOCUMENT)
? aLoadInfo->TriggeringPrincipal()
: aLoadInfo->LoadingPrincipal();
int16_t shouldLoad = nsIContentPolicy::ACCEPT;
rv = NS_CheckContentLoadPolicy(internalContentPolicyType,
uri,
principal,
aLoadInfo->LoadingPrincipal(),
aLoadInfo->TriggeringPrincipal(),
requestingContext,
mimeTypeGuess,
nullptr, //extra,

View file

@ -261,10 +261,14 @@ public:
rv = NS_NewURI(getter_AddRefs(uri), url, nullptr, nullptr);
NS_ENSURE_SUCCESS(rv, false);
int16_t decision = nsIContentPolicy::ACCEPT;
rv = NS_CheckContentLoadPolicy(aLoadInfo->InternalContentPolicyType(), uri,
rv = NS_CheckContentLoadPolicy(aLoadInfo->InternalContentPolicyType(),
uri,
aLoadInfo->LoadingPrincipal(),
aLoadInfo->LoadingNode(), EmptyCString(),
nullptr, &decision);
aLoadInfo->TriggeringPrincipal(),
aLoadInfo->LoadingNode(),
EmptyCString(),
nullptr,
&decision);
NS_ENSURE_SUCCESS(rv, false);
return decision == nsIContentPolicy::ACCEPT;
}

View file

@ -592,7 +592,8 @@ ServiceWorkerManager::Register(mozIDOMWindow* aWindow,
int16_t decision = nsIContentPolicy::ACCEPT;
rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_INTERNAL_SERVICE_WORKER,
aScriptURI,
documentPrincipal,
documentPrincipal, // loading principal
documentPrincipal, // triggering principal
doc,
EmptyCString(),
nullptr,

View file

@ -696,7 +696,8 @@ nsXMLContentSink::ProcessStyleLink(nsIContent* aElement,
int16_t decision = nsIContentPolicy::ACCEPT;
rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_XSLT,
url,
mDocument->NodePrincipal(),
mDocument->NodePrincipal(), // loading principal
mDocument->NodePrincipal(), // triggering principal
aElement,
type,
nullptr,

View file

@ -567,7 +567,8 @@ ShouldLoadCachedImage(imgRequest* aImgRequest,
int16_t decision = nsIContentPolicy::REJECT_REQUEST;
rv = NS_CheckContentLoadPolicy(aPolicyType,
contentLocation,
aLoadingPrincipal,
aLoadingPrincipal, // loading principal
aLoadingPrincipal, // triggering principal
aLoadingContext,
EmptyCString(), //mime guess
nullptr, //aExtra

View file

@ -1366,7 +1366,8 @@ FontFaceSet::IsFontLoadAllowed(nsIURI* aFontLocation, nsIPrincipal* aPrincipal)
int16_t shouldLoad = nsIContentPolicy::ACCEPT;
nsresult rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_FONT,
aFontLocation,
aPrincipal,
aPrincipal, // loading principal
aPrincipal, // triggering principal
mDocument,
EmptyCString(), // mime type
nullptr, // aExtra

View file

@ -1028,14 +1028,15 @@ Loader::ObsoleteSheet(nsIURI* aURI)
}
nsresult
Loader::CheckContentPolicy(nsIPrincipal* aSourcePrincipal,
nsIURI* aTargetURI,
nsISupports* aContext,
bool aIsPreload)
Loader::CheckContentPolicy(nsIPrincipal* aLoadingPrincipal,
nsIPrincipal* aTriggeringPrincipal,
nsIURI* aTargetURI,
nsISupports* aContext,
bool aIsPreload)
{
// When performing a system load (e.g. aUseSystemPrincipal = true)
// then aSourcePrincipal == null; don't consult content policies.
if (!aSourcePrincipal) {
// then aLoadingPrincipal == null; don't consult content policies.
if (!aLoadingPrincipal) {
return NS_OK;
}
@ -1046,7 +1047,8 @@ Loader::CheckContentPolicy(nsIPrincipal* aSourcePrincipal,
int16_t shouldLoad = nsIContentPolicy::ACCEPT;
nsresult rv = NS_CheckContentLoadPolicy(contentPolicyType,
aTargetURI,
aSourcePrincipal,
aLoadingPrincipal,
aTriggeringPrincipal,
aContext,
NS_LITERAL_CSTRING("text/css"),
nullptr, //extra param
@ -2039,15 +2041,20 @@ Loader::LoadStyleLink(nsIContent* aElement,
NS_ENSURE_TRUE(mDocument, NS_ERROR_NOT_INITIALIZED);
nsIPrincipal* principal =
aElement ? aElement->NodePrincipal() : mDocument->NodePrincipal();
nsIPrincipal* loadingPrincipal = aElement ? aElement->NodePrincipal()
: mDocument->NodePrincipal();
//SHOULD BE:
//nsIPrincipal* principal = aTriggeringPrincipal ? aTriggeringPrincipal
// : loadingPrincipal;
nsIPrincipal* principal = loadingPrincipal;
nsISupports* context = aElement;
if (!context) {
context = mDocument;
}
nsresult rv = CheckContentPolicy(principal, aURL, context, false);
nsresult rv = CheckContentPolicy(loadingPrincipal, principal, aURL, context, false);
if (NS_WARN_IF(NS_FAILED(rv))) {
// Don't fire the error event if our document is loaded as data. We're
// supposed to not even try to do loads in that case... Unfortunately, we
@ -2188,13 +2195,18 @@ Loader::LoadChildSheet(StyleSheet* aParentSheet,
owningNode = topSheet->GetOwnerNode();
}
nsISupports* context = owningNode;
if (!context) {
nsISupports* context = nullptr;
nsIPrincipal* loadingPrincipal = nullptr;
if (owningNode) {
context = owningNode;
loadingPrincipal = owningNode->NodePrincipal();
} else if (mDocument) {
context = mDocument;
loadingPrincipal = mDocument->NodePrincipal();
}
nsIPrincipal* principal = aParentSheet->Principal();
nsresult rv = CheckContentPolicy(principal, aURL, context, false);
nsresult rv = CheckContentPolicy(loadingPrincipal, principal, aURL, context, false);
NS_ENSURE_SUCCESS(rv, rv);
SheetLoadData* parentData = nullptr;
@ -2351,7 +2363,11 @@ Loader::InternalLoadNonDocumentSheet(nsIURI* aURL,
return NS_ERROR_NOT_AVAILABLE;
}
nsresult rv = CheckContentPolicy(aOriginPrincipal, aURL, mDocument, aIsPreload);
nsCOMPtr<nsIPrincipal> loadingPrincipal = (aOriginPrincipal && mDocument
? mDocument->NodePrincipal()
: nullptr);
nsresult rv = CheckContentPolicy(loadingPrincipal, aOriginPrincipal,
aURL, mDocument, aIsPreload);
NS_ENSURE_SUCCESS(rv, rv);
StyleSheetState state;

View file

@ -452,7 +452,8 @@ public:
private:
friend class SheetLoadData;
nsresult CheckContentPolicy(nsIPrincipal* aSourcePrincipal,
nsresult CheckContentPolicy(nsIPrincipal* aLoadingPrincipal,
nsIPrincipal* aTriggeringPrincipal,
nsIURI* aTargetURI,
nsISupports* aContext,
bool aIsPreload);

View file

@ -173,7 +173,10 @@ var ContentPolicy = {
windowId,
parentWindowId};
if (requestOrigin) {
data.originUrl = requestOrigin.spec;
data.documentUrl = requestOrigin.spec;
}
if (requestPrincipal && requestPrincipal.URI) {
data.originUrl = requestPrincipal.URI.spec;
}
if (block) {
let rval = mm.sendSyncMessage("WebRequest:ShouldLoad", data);