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

Brendan Eich brendan at
Wed Jan 23 09:19:22 PST 2013

Tom Van Cutsem wrote:
> 2013/1/23 Brendan Eich <brendan at <mailto:brendan at>>
>     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 
> isn't.

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 
> membranes.
> So 3) may be an issue in general, but membranes should be able to 
> avoid it.



More information about the es-discuss mailing list