You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Summarizing, there's quite a bit of interest in exposing non-ecma globals in realms, current suggestions restrict things to safe deterministic APIs, however some use cases may want to restrict further, other use cases might actually want new copies of UNSAFE APIs.
As a couple of example use cases:
SES and similar use cases must remove all non-deterministic APIs. Depending on specifics, they may even want to hide determinstic ones that expose information about the environment
Testing use cases (e.g. test runners) probably want hosts to be able to insert many APIs including potentially unsafe ones such as Worker (e.g. new Worker("some-url") triggers a fetch, enables spectre attacks, etc), having to shim every non-deterministic global, and worse keep those shims up to date is a highly cumbersome task that we'd probably want to avoid (especially when hosts can install it directly)
Some plugin APIs may wish to expose some degree of unsafe surface without exposing all of it, e.g. perhaps exposing indexedDB but not exposing fetch
...and so on
Now these problems could be somewhat solved at the Realms level by filtering globals, but in practice some APIs have mixed levels of safety, for example Worker triggers a fetch to load the script/module, but for the most part it's relatively safe. Even ECMAScript itself has mixed safety APIs, for example Date with Date.now().
As such I'd like to propose a way for allowing hosts to compartmentalize their own behaviour (ideally with a note that any APIs exposed as a global on new Realms must be sufficiently compartmentalized). In particular I would like to suggest we allow hosts to expose additional hooks for any non-deterministic behaviour just as ECMAScript does for it's own sources of non-determinism.
As an example of what this could look like in a API surface:
Now in practice a lot of host APIs are probably not ready for arbitrary user code to run in various steps, for example it's likely many parts of fetch run on another thread, as such not all behaviours might be compartmentilizable. As such we should allow hosts to provide simplified hooks that simply disable the ability to use the API altogether (perhaps by simply forwarding a few arguments to the hook for validation), for example:
constcompartment=newCompartment({},{},{preConstructWorkerHook: (url)=>{if(!isSafeURL(url)){thrownewError("UNSAFE");}// Note we can't configure fetch steps, only prevent the worker triggering a fetch// these sort've hooks should be a lot simpler for hosts to expose than// providing completely hookable behaviour, for example in Worker this could be implemented// roughly like just adding a simple call to the hook immediately on construction:// class Worker extends EventTarget {// constructor(workerSrc) {// // Ensure it's safe to proceed with constructing this worker// [[Realm]].preConstructWorkerHook(workerSrc);// // Host behaviour can run as normal after simple pre check, arbitrary JS// // code probably isn't insertable in here as much of the setup code is// // probably running on another thread// InstantiateWorkerAsPerNormal();// }// }},});
Now to ensure safety of things like SES, we need to assert that hosts must hook any unsafe behaviour for any globals exposed, within something like SES, we can simply provide safe versions of host APIs, for unrecognised APIs we could provide a proxy e.g.:
constcompartment=newCompartment({},{},newProxy({randomHook: ()=>0.5,preWorkerConstructHook: (url)=>{if(!isSafeURL(url)){thrownewError("Not allowed")};},},{get(target,propName,receiver){returnReflect.get(target,propName,receiver)??()=>{thrownewError(`Unrecognized unsafe API used: ${propName}`);});}});compartment.evaluate(`const worker = new Worker("./foo.js"); // OK`);compartment.evaluate(`const req = indexedDB.open("some-store")`);// BLOCKED
The above could even be exposed a factory method on Compartments themselves, so that we don't need to manually create proxies e.g.:
constcompartment=Compartment.safe({},{},{randomHook: ()=>0.5,preWorkerConstructHook: (url)=>{if(!isSafeURL(url)){thrownewError("Not allowed")};},});compartment.evaluate(`const worker = new Worker("./foo.js");`);// OK (if isSafeURL(url))compartment.evaluate(`indexedDB.open("some-store")`);// BLOCKED, unimplemented hooks automatically throw
The text was updated successfully, but these errors were encountered:
With the latest revisions to the compartments proposal, this issue no longer applies as hooks for non-module loading behaviour are no longer part of the compartments proposal.
This is an issue raised in response to this issue on Realms particularly with regards to this suggestion.
Summarizing, there's quite a bit of interest in exposing non-ecma globals in realms, current suggestions restrict things to safe deterministic APIs, however some use cases may want to restrict further, other use cases might actually want new copies of UNSAFE APIs.
As a couple of example use cases:
Worker
(e.g.new Worker("some-url")
triggers a fetch, enables spectre attacks, etc), having to shim every non-deterministic global, and worse keep those shims up to date is a highly cumbersome task that we'd probably want to avoid (especially when hosts can install it directly)indexedDB
but not exposingfetch
Now these problems could be somewhat solved at the Realms level by filtering globals, but in practice some APIs have mixed levels of safety, for example
Worker
triggers a fetch to load the script/module, but for the most part it's relatively safe. Even ECMAScript itself has mixed safety APIs, for exampleDate
withDate.now()
.As such I'd like to propose a way for allowing hosts to compartmentalize their own behaviour (ideally with a note that any APIs exposed as a global on new Realms must be sufficiently compartmentalized). In particular I would like to suggest we allow hosts to expose additional hooks for any non-deterministic behaviour just as ECMAScript does for it's own sources of non-determinism.
As an example of what this could look like in a API surface:
Now in practice a lot of host APIs are probably not ready for arbitrary user code to run in various steps, for example it's likely many parts of
fetch
run on another thread, as such not all behaviours might be compartmentilizable. As such we should allow hosts to provide simplified hooks that simply disable the ability to use the API altogether (perhaps by simply forwarding a few arguments to the hook for validation), for example:Now to ensure safety of things like SES, we need to assert that hosts must hook any unsafe behaviour for any globals exposed, within something like SES, we can simply provide safe versions of host APIs, for unrecognised APIs we could provide a proxy e.g.:
The above could even be exposed a factory method on
Compartment
s themselves, so that we don't need to manually create proxies e.g.:The text was updated successfully, but these errors were encountered: