commit c41e8cbc9278967392559e42dce29626c0173c64
parent 4f8dd6362437a8db3a80452c9d333c1fd5e1ae20
Author: Tom Ritter <tom@mozilla.com>
Date: Fri, 7 Nov 2025 16:34:27 +0000
Bug 1994841: Add an option to JSContext to disable filename validation, and propagate it to CompileOptions r=necko-reviewers,spidermonkey-reviewers,arai
Differential Revision: https://phabricator.services.mozilla.com/D269084
Diffstat:
3 files changed, 31 insertions(+), 2 deletions(-)
diff --git a/js/public/ContextOptions.h b/js/public/ContextOptions.h
@@ -29,6 +29,7 @@ class JS_PUBLIC_API ContextOptions {
testWasmAwaitTier2_(false),
disableIon_(false),
disableEvalSecurityChecks_(false),
+ disableFilenameSecurityChecks_(false),
asyncStack_(true),
asyncStackCaptureDebuggeeOnly_(false),
throwOnDebuggeeWouldRun_(true),
@@ -105,6 +106,9 @@ class JS_PUBLIC_API ContextOptions {
return *this;
}
+ // These next two checks are needed for PAC Scripts: we cannot enforce
+ // restrictions on them because they are user provided.
+
// Override to allow disabling the eval restriction security checks for
// this context.
bool disableEvalSecurityChecks() const { return disableEvalSecurityChecks_; }
@@ -113,6 +117,19 @@ class JS_PUBLIC_API ContextOptions {
return *this;
}
+ // Override to allow disabling the filename security checks (checks that
+ // ensure the script doesn't come from the web) for this context. There is a
+ // lower-level flag for this same check in CompileOptions which will be set by
+ // this flag; this is needed here to propagate the flag down into eval
+ // contexts
+ bool disableFilenameSecurityChecks() const {
+ return disableFilenameSecurityChecks_;
+ }
+ ContextOptions& setDisableFilenameSecurityChecks() {
+ disableFilenameSecurityChecks_ = true;
+ return *this;
+ }
+
bool asyncStack() const { return asyncStack_; }
ContextOptions& setAsyncStack(bool flag) {
asyncStack_ = flag;
@@ -172,9 +189,10 @@ class JS_PUBLIC_API ContextOptions {
// JIT options.
bool disableIon_ : 1;
- bool disableEvalSecurityChecks_ : 1;
// Runtime options.
+ bool disableEvalSecurityChecks_ : 1;
+ bool disableFilenameSecurityChecks_ : 1;
bool asyncStack_ : 1;
bool asyncStackCaptureDebuggeeOnly_ : 1;
bool throwOnDebuggeeWouldRun_ : 1;
diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp
@@ -2637,6 +2637,10 @@ JS::CompileOptions::CompileOptions(JSContext* cx) {
alwaysUseFdlibm_ = realm->creationOptions().alwaysUseFdlibm();
discardSource = realm->behaviors().discardSource();
}
+
+ if (cx->options().disableFilenameSecurityChecks()) {
+ skipFilenameValidation_ = true;
+ }
}
JS::InstantiateOptions::InstantiateOptions() {
diff --git a/netwerk/base/ProxyAutoConfig.cpp b/netwerk/base/ProxyAutoConfig.cpp
@@ -392,7 +392,14 @@ class JSContextWrapper {
JSContext* cx = JS_NewContext(JS::DefaultHeapMaxBytes + aExtraHeapSize);
if (NS_WARN_IF(!cx)) return nullptr;
- JS::ContextOptionsRef(cx).setDisableIon().setDisableEvalSecurityChecks();
+ // PAC scripts are user-provided scripts that run in the parent process.
+ // Disable Ion because we don't require it and it reduces attack surface.
+ // Disable security checks because we cannot enforce restrictions on these
+ // scripts.
+ JS::ContextOptionsRef(cx)
+ .setDisableIon()
+ .setDisableEvalSecurityChecks()
+ .setDisableFilenameSecurityChecks();
JSContextWrapper* entry = new JSContextWrapper(cx);
if (NS_FAILED(entry->Init())) {