Bug 1905239 - Add new parameters to HostEnsureCanCompileStrings hook. r=tschuster

Currently, we do this via isRuntimeCodeGenEnabled whose single argument
is equivalent to codeString in "Dynamic Code Brand Checks" spec [1]. We
extend this hook to accept new parameters from that spec and adjust
PerformEval and CreateDynamicFunction accordingly. We don't change the
behavior for PerformShadowRealmEval [2] and WASM, i.e. we keep dummy
parameters.

[1] https://tc39.es/proposal-dynamic-code-brand-checks
[2] https://github.com/tc39/proposal-shadowrealm/issues/414

Differential Revision: https://phabricator.services.mozilla.com/D229588
This commit is contained in:
Frédéric Wang
2024-12-11 20:00:32 +00:00
parent 410b2420a9
commit c94fbf2e3e
12 changed files with 367 additions and 37 deletions

View File

@@ -73,6 +73,8 @@
#include "nsJSUtils.h"
#include "nsILoadInfo.h"
#include "js/ColumnNumber.h" // JS::ColumnNumberOneOrigin
#include "js/GCVector.h"
#include "js/Value.h"
// This should be probably defined on some other place... but I couldn't find it
#define WEBAPPS_PERM_NAME "webapps-manage"
@@ -462,7 +464,12 @@ NS_IMPL_ISUPPORTS(nsScriptSecurityManager, nsIScriptSecurityManager)
///////////////// Security Checks /////////////////
bool nsScriptSecurityManager::ContentSecurityPolicyPermitsJSAction(
JSContext* cx, JS::RuntimeCode aKind, JS::Handle<JSString*> aCode) {
JSContext* cx, JS::RuntimeCode aKind, JS::Handle<JSString*> aCodeString,
JS::CompilationType aCompilationType,
JS::Handle<JS::StackGCVector<JSString*>> aParameterStrings,
JS::Handle<JSString*> aBodyString,
JS::Handle<JS::StackGCVector<JS::Value>> aParameterArgs,
JS::Handle<JS::Value> aBodyArg, bool* aOutCanCompileStrings) {
MOZ_ASSERT(cx == nsContentUtils::GetCurrentJSContext());
nsCOMPtr<nsIPrincipal> subjectPrincipal = nsContentUtils::SubjectPrincipal();
@@ -477,13 +484,14 @@ bool nsScriptSecurityManager::ContentSecurityPolicyPermitsJSAction(
if (contextForbidsEval) {
nsAutoJSString scriptSample;
if (aKind == JS::RuntimeCode::JS &&
NS_WARN_IF(!scriptSample.init(cx, aCode))) {
NS_WARN_IF(!scriptSample.init(cx, aCodeString))) {
return false;
}
if (!nsContentSecurityUtils::IsEvalAllowed(
cx, subjectPrincipal->IsSystemPrincipal(), scriptSample)) {
return false;
*aOutCanCompileStrings = false;
return true;
}
}
@@ -503,6 +511,7 @@ bool nsScriptSecurityManager::ContentSecurityPolicyPermitsJSAction(
}
// don't do anything unless there's a CSP
if (!csp) {
*aOutCanCompileStrings = true;
return true;
}
}
@@ -522,7 +531,8 @@ bool nsScriptSecurityManager::ContentSecurityPolicyPermitsJSAction(
nsresult rv = csp->GetAllowsEval(&reportViolation, &evalOK);
if (NS_FAILED(rv)) {
NS_WARNING("CSP: failed to get allowsEval");
return true; // fail open to not break sites.
*aOutCanCompileStrings = true; // fail open to not break sites.
return true;
}
} else {
if (NS_FAILED(csp->GetAllowsWasmEval(&reportViolation, &evalOK))) {
@@ -545,8 +555,7 @@ bool nsScriptSecurityManager::ContentSecurityPolicyPermitsJSAction(
auto caller = JSCallingLocation::Get(cx);
nsAutoJSString scriptSample;
if (aKind == JS::RuntimeCode::JS &&
NS_WARN_IF(!scriptSample.init(cx, aCode))) {
JS_ClearPendingException(cx);
NS_WARN_IF(!scriptSample.init(cx, aCodeString))) {
return false;
}
uint16_t violationType =
@@ -559,7 +568,8 @@ bool nsScriptSecurityManager::ContentSecurityPolicyPermitsJSAction(
caller.mLine, caller.mColumn, u""_ns, u""_ns);
}
return evalOK;
*aOutCanCompileStrings = evalOK;
return true;
}
// static

View File

@@ -28,6 +28,7 @@ class SystemPrincipal;
namespace JS {
enum class RuntimeCode;
enum class CompilationType;
} // namespace JS
/////////////////////////////
@@ -91,9 +92,13 @@ class nsScriptSecurityManager final : public nsIScriptSecurityManager {
virtual ~nsScriptSecurityManager();
// Decides, based on CSP, whether or not eval() and stuff can be executed.
static bool ContentSecurityPolicyPermitsJSAction(JSContext* cx,
JS::RuntimeCode kind,
JS::Handle<JSString*> aCode);
static bool ContentSecurityPolicyPermitsJSAction(
JSContext* aCx, JS::RuntimeCode aKind, JS::Handle<JSString*> aCodeString,
JS::CompilationType aCompilationType,
JS::Handle<JS::StackGCVector<JSString*>> aParameterStrings,
JS::Handle<JSString*> aBodyString,
JS::Handle<JS::StackGCVector<JS::Value>> aParameterArgs,
JS::Handle<JS::Value> aBodyArg, bool* aOutCanCompileStrings);
static bool JSPrincipalsSubsume(JSPrincipals* first, JSPrincipals* second);