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

David Bruant bruant.d at gmail.com
Thu Jan 24 01:43:57 PST 2013


Le 24/01/2013 09:52, Tom Van Cutsem a écrit :
> 2013/1/23 David Bruant <bruant.d at gmail.com <mailto: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.
True, I had read this post too quickly.

>     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'm not worried about the |this|-reliability for the method, but rather 
that the target instance can be left in an inconsistent state because of 
a malicious handler. The important part in the above expression isn't 
the .call, but that an actual Counter instance is the proxy target.

>     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.
I agree with you, I suggested to add an option, not to change the 
default semantics. Because of the too-dynamic |this| and everyone being 
used to it, protecting yourself from malicious proxies from attacks like 
the one above ("method.call(new Proxy(legitObject, maliciousProxy))") 
has to be an opt-in. Basically, methods make sure their |this| is an 
object that came out of the class constructor.
It would be nice if this opt-in could be made as simple as an optional 
keyword in the class syntax. This option would just desugar differently 
(put all objects created by the constructor in a WeakSet, add a prolog 
to each method verifying |this| is part of the weakset, continue if yes, 
throw if not).

> 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).
I agree. The selector matching use case convinced me there is no chance 
to put proxies or weird objects in a DOM tree.

David
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20130124/f5ce8486/attachment-0001.html>


More information about the es-discuss mailing list