Private symbols auto-unwrapping proxies (was: Security Demands Simplicity (was: Private Slots))
brendan at mozilla.com
Wed Jan 23 09:19:22 PST 2013
Tom Van Cutsem wrote:
> 2013/1/23 Brendan Eich <brendan at mozilla.com <mailto:brendan at mozilla.com>>
> Brandon Benvie wrote:
> It is my opinion that the primary use case for private symbols
> is for properties that proxies expressly shouldn't be given a
> chance, in any manner, to corrupt or modify. They are likely
> used for sensitive internal state that will only be accessed
> by methods or friend classes created in service of the target.
> A membrane becomes less valuable if breaking the target is an
> easily accomplished accidental side effect. This is already
> visible in practice today when you attempt to use WeakMaps to
> create private state for objects and they are proxied, since
> the private state will be keyed on `this` in the constructor
> which won't match `this` in methods invoked on the proxy.
> ding ding ding ding ding ding....
> Let's try to separate the issues here:
Thanks, did not mean to ring Pavlov's bell there ;-).
> 1) proxies and private symbols: Brandon strengthens the case that
> proxies should be oblivious to private symbols.
> 2) any sort of private state (regardless of whether it's stored using
> private symbols or weakmaps) is always keyed off of the identity of
> the target.
> 3) because of JS's "invoke = get + apply" semantics, by default a
> proxy always leaves the |this| value pointing at the proxy.
> The combination of 2) and 3) is problematic (as in: not transparent).
This is an aspect of JS's dynamic-by-default |this| binding, it seems to me.
> Looking only at 3), sometimes this is what you want, and sometimes it
Very true. For HTML5, given function f written in JS, loaded in window
referenced from another frame by w, referencing a WindowProxy, w.f()
binds |this| in f to the WindowProxy. We do not want to expose the
Window on the scope chain directly -- it is too easy to leak that
capability and bypass the same-origin security membraning done by the
For a built-in function written in C++, implementations I know of all
auto-unwrap to get the Window. One might then want to self-host such
legacy C++ built-ins, and want auto-unwrapping. The burden of not
leaking the capability still exists, but the self-hosted built-in is
part of the TCB, same as the C++ counterpart.
So the issue is situational, depending on trusted computing base
membership among other things.
> In the case of membranes I agree the more natural thing to do is to
> rebind |this| to the real target, not a membraned proxy for it. I
> think membranes can do that already without added cost: the "get" trap
> already needs to return a wrapper for the actual function object
> anyway. That wrapper, when called, can call the real function with the
> real target as the |this| value.
> Looking back at the code for an identity-preserving membrane
> I think this membrane actually properly unwraps the |this| value
> before forwarding. I haven't yet tried expressing this code using
> Direct proxies, but off the top of my head I don't see how the change
> from proxies to direct proxies would impact this particular aspect of
> So 3) may be an issue in general, but membranes should be able to
> avoid it.
More information about the es-discuss