endojs / endo

Endo is a distributed secure JavaScript sandbox, based on SES
Apache License 2.0
829 stars 72 forks source link

Repair Proxy with stamping power #1756

Open mhofman opened 1 year ago

mhofman commented 1 year ago

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 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:

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.