Hardened JS provides and OCap environment, however because of some of the remaining JS semantics, that is not sufficient for mutually suspicious parties in the same vat / agent to easily reason about their interactions.
In particular, property access on an object, even hardened, may throw or become re-entrant. Or adopting a Promise can also cause re-entrancy. There are actually 2 situations that can cause these surprising behaviors:
an object / promise with accessors instead of data properties
a proxy pretending data properties
While the former can and is protected by disallowing accessors when sharing objects through a boundary between mutually suspicious code (as implemented by passStyleOf checks), the latter cannot be protected against with normal JS features since proxies are meant to be completely transparent.
Description of the Design
Hardened JS would replace the Proxy constructor with a version that stamps instances (e.g. add them to a WeakMap), and create a power in the start compartment that allows detecting whether an object is a proxy instance.
This predicate power could be provided to makePassStyleOf to let it detect these exotic proxy object, and disqualify them as passable. In the case of the agoric-sdk, liveslots would arrange to instantiate passStyleOf and endow it to compartments in which user code runs.
Some open questions are whether the Proxy constructor in the initial compartment should be the stamping version of not, and where to place the predicate. For example we could arrange for the %InitialProxy% to be exempt from stamping (only for%SharedProxy%to stamp its instances), and for the predicate to live on%InitialProxy%.isSharedProxy`.
Alternative / Rejected Design
The main concern with proxies is its ability to execute user code in objects that may be considered inert. One alternative would be to change the semantics of proxies to bypass the handler traps once the object is frozen. However there are some problems with that approach:
testing whether an object is frozen can itself trigger traps if the object is not frozen
proxy invariants regarding get / set of non-own properties are lax and cannot be cached (unless we change the invariants to require non-exotic behavior, aka lookup on the prototype chain)
In the case of OCap checks, the first issue is the biggest problem. We would need to implement an "isFrozen" / "isExtensible" predicate that is guaranteed to no trigger proxy traps, which reduced back to the isProxy predicate.
What is the Problem Being Solved?
Hardened JS provides and OCap environment, however because of some of the remaining JS semantics, that is not sufficient for mutually suspicious parties in the same vat / agent to easily reason about their interactions.
In particular, property access on an object, even hardened, may throw or become re-entrant. Or adopting a Promise can also cause re-entrancy. There are actually 2 situations that can cause these surprising behaviors:
While the former can and is protected by disallowing accessors when sharing objects through a boundary between mutually suspicious code (as implemented by passStyleOf checks), the latter cannot be protected against with normal JS features since proxies are meant to be completely transparent.
Description of the Design
Hardened JS would replace the
Proxy
constructor with a version that stamps instances (e.g. add them to a WeakMap), and create a power in the start compartment that allows detecting whether an object is a proxy instance.This predicate power could be provided to
makePassStyleOf
to let it detect these exotic proxy object, and disqualify them as passable. In the case of the agoric-sdk, liveslots would arrange to instantiatepassStyleOf
and endow it to compartments in which user code runs.Some open questions are whether the
Proxy
constructor in the initial compartment should be the stamping version of not, and where to place the predicate. For example we could arrange for the%InitialProxy% to be exempt from stamping (only for
%SharedProxy%to stamp its instances), and for the predicate to live on
%InitialProxy%.isSharedProxy`.Alternative / Rejected Design
The main concern with proxies is its ability to execute user code in objects that may be considered inert. One alternative would be to change the semantics of proxies to bypass the handler traps once the object is frozen. However there are some problems with that approach:
In the case of OCap checks, the first issue is the biggest problem. We would need to implement an "isFrozen" / "isExtensible" predicate that is guaranteed to no trigger proxy traps, which reduced back to the
isProxy
predicate.Security Considerations
This would enable solving the following issues:
Other relevant issues:
Scaling Considerations
N/A
Test Plan
Unit tests
Upgrade Considerations
This is a new capability which by itself does not result in any behavioral changes for existing code.