Private symbols auto-unwrapping proxies (was: Security Demands Simplicity (was: Private Slots))

Tom Van Cutsem tomvc.be at gmail.com
Thu Jan 24 00:52:32 PST 2013


2013/1/23 David Bruant <bruant.d at gmail.com>

> Le 23/01/2013 09:38, Tom Van Cutsem a écrit :
>
>> 3) because of JS's "invoke = get + apply" semantics, by default a proxy
>> always leaves the |this| value pointing at the proxy.
>>
>> Looking only at 3), sometimes this is what you want, and sometimes it
>> isn't.
>>
> In which case would it be what you want?
>

See the example by Brendan just upstream in this thread.


> The example Brandon (and Kevin before him) provided showed something very
> intrusive about proxies related to your 3). That proxies mediate the access
> to the public method is one thing, that they pretend to be the object acted
> on inside the method opens a entire world.
>
> Even with fixes suggested by Allen, the hazard can still exist if someone
> does:
>     Counter.prototype.increment.**call(new Proxy(counter,
> maliciousHandler))
>

I don't understand why this is a hazard. Even without proxies, |this| is
never reliable, unless you use .bind().


> I have no idea how this can be mitigated in general without creating a
> mechanism that can be abused to unwrap proxies. For classes specifically,
> maybe an option can make that classes keep track of generated objects and
> throw if non-instance is passed in a method as |this| (...which is exactly
> the kind of things DOM Node tree manipulation methods will need)


Recall that it was a goal for classes to be a form of sugar over the
existing object model. That means the use of |this| within a method
specified using class syntax should really be no different from using
|this| outside of classes. Let's try to avoid making up special rules for
class instances.

The OP was about a proposal that auto-unwraps proxies specifically for
private symbol access. This decouples proxies and private symbols, but in a
potentially dangerous way (cf. the need to change membranes).
Auto-unwrapping a proxy without consulting the handler inherently breaks
abstraction boundaries.

Another alternative that crossed my mind, which may be as simple, and less
"dangerous":

We could make proxies have their own private state, such that
proxy[privateSymbol] just accesses the proxy's private state (without
trapping!). That means there is no a priori relationship between
proxy[privateSymbol] and target[privateSymbol]. Basically this is also how
WeakMaps interact with proxies today (different identities, different
mappings).

Under this proposal:
- private symbols are never leaked to proxies
- private symbol access is "reliable" (it never throws)
- private symbols don't pierce membranes
- proxies don't need facilities to interact with private symbols (the
whitelist and unknownPrivateSymbol trap)

What you lose is the ability to call a method that expects an object with
certain built-in state, and that will "just work" when passed a proxy for
an object with such state. Maybe this was a bad idea anyway.

Going back to the big discussion thread about proxying DOM objects, I
maintain that it's a bad idea to try to make existing APIs (that expect
objects of a very specific type) work with any random proxy, either by
interacting with it or by unwrapping it. The cleaner thing to do would be
to replace/wrap the API with one that also recognizes and accepts certain
proxies (still not just anyone's proxies).

Cheers,
Tom
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20130124/d230face/attachment.html>


More information about the es-discuss mailing list