Private symbols auto-unwrapping proxies (was: Security Demands Simplicity (was: Private Slots))
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
> 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,
> 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.
-------------- next part --------------
An HTML attachment was scrubbed...
More information about the es-discuss