Security Demands Simplicity (was: Private Slots)

Brandon Benvie brandon at brandonbenvie.com
Thu Jan 17 09:35:41 PST 2013


Well keep in mind that Symbols of any type already require using a new
function, getOwnKeys (or whatever the name is) so they are already
essentially "super non-enumerable". They are reflectable if someone really
wants to see them, but they are never reflected in Object.keys,
Object.getOwnPropertyNames, or for...in enumeration.


On Thu, Jan 17, 2013 at 12:32 PM, Axel Rauschmayer <axel at rauschma.de> wrote:

> Can we separate of concerns?
>
> 1. I love symbols.
>
> 2. I also love the idea that you can mark properties as private, as
> invisible to the outside. Currently I prefix my properties with `_` to do
> so, but it’s an ugly namespace pollution.
>
> 3. But, for me and probably most applications, the privacy does not have
> to be bullet proof. For the rare cases where we need. bullet-proofing, weak
> maps might be enough.
>
> 4. Enumerability still seems like something that only exists because for
> for-in. Unfortunately, it can’t take up role #2, because so many things are
> already non-enumerable that are clearly public.
>
> Does that mean that the current ES6 model could be simplified? For
> example: another property attribute `visible`, making properties invisible.
> Not sure where the invisibility matters: at an IDE level, when you do an
> expansion (e.g. type `myobj.`). Or should it also be hidden from all
> current iteration operations (Object.getOwnPropertyNames() etc.)? In either
> case, there would still be a way of iterating over all properties, making
> copying etc. straightforward.
>
>
> On Jan 17, 2013, at 18:00 , "Mark S. Miller" <erights at google.com> wrote:
>
> First, I agree with David that security is important, both for
> security per se and for modularity in general. ES5 improved the
> language when it fixed the accidental leaks between the world of
> objects and scope-chain objects, like thrown functions. ES5/strict
> improved the language when it made functions really encapsulated,
> poisoned caller and arguments, and repaired the remaining violations
> of static scoping. ES6 modules and CommonJS/Node modules were born and
> remain encapsulated. I have not heard anyone suggesting any of these
> would be improved by introducing pliers for opening them against their
> will (except in a debugger, which is a different issue). Tons of code
> have been written in ES3. We still made the world a better place when
> we plugged its leaks.
>
> I also agree with David that unique symbols are not an encapsulation
> mechanism, but rather, merely a mechanism to avoid namespace
> collisions.
>
> As for Java's reflective breakage of "private",
> <
> http://www.nbcnews.com/technology/technolog/us-warns-java-software-security-concerns-escalate-1B7938755
> >.
>
>
> However, after the "Private Slots" thread, I spent a sleepless night
> chewing on getting rid of private symbols. I now think we should.
> Going back to my earlier
>
>
> On Wed, Jan 16, 2013 at 12:37 PM, Mark S. Miller <erights at google.com>
> wrote:
>
> My position on private symbols.
>
> My position on classes is and has always been that classes are worth
> introducing into the language *only* if they give us, or can be used
> with, an affordable means for true object encapsulation. Assuming
> Allen is right about what actual implementors will do (which I find
> plausible) then WeakMaps are not that means.
>
>
> I still have this position on classes. But I no longer buy that
> pessimistic conclusion about WeakMaps. Consider how WeakMaps would be
> used by the expansion of classes-with-private. Just 'cause it's on the
> top of my head, below I use the old representation of one WeakMap per
> class providing access to a record of all the private state. For the
> same reason, I'll use the encapsulation of the Purse example without
> any of the numeric checks.
>
> class Purse {
>    constructor(private balance) {
>    getBalance() { return balance; }
>    makePurse() { return Purse(0); }
>    deposit(amount, srcPurse) {
>        private(srcPurse).balance -= amount;
>        balance += amount;
>    }
> }
>
> expansion
>
> let Purse = (function() {
>    let amp = WeakMap();
>    function Purse(balance) {
>        amp.set(this, Object.seal({
>            get balance() { return balance; },
>            set balance(newBalance) { balance = newBalance; }
>        }));
>    }
>    Purse.prototype = {
>        getBalance: function() { return balance; },
>        makePurse: function() { return Purse(0); },
>        deposit: function(amount, srcPurse) {
>            amp.get(srcPurse).balance -= amount;
>        }
>    }
>    return Purse;
> })();
>
>
> Ignore the issues about whether we should use one WeakMap per class
> and a private record as above, or a WeakMap per private field name
> declaration.
>
> Ignore the use of accessors so that private field names track
> variables. If we had instead stored the state in the private field and
> compiled getBalance to use the field, that doesn't affect the
> important issue.
>
>
>
> **********************
> Notice that the lifetime of amp cannot be shorter than the lifetimes
> of the Point instances, since the instances retain amp, and these
> instances are the only objects ever stored as keys in amp.
> **********************
>
>
>
> For this usage common pattern, the lifetime of the keys of amp cannot
> outlive the lifetime of amp.
>
> Thus, no matter what the spec says, normatively or not, about expected
> storage costs, competitive pressures will drive JS engine implementors
> to make this efficient. The way to make this efficient is by the
> technique previously discussed -- hang the private state off of the
> object, not the weakmap. Use the weakmap only as an unforgeable token
> for naming and accessing this state. If we get rid of private symbols,
> we should expect this pattern of usage of WeakMap to have the same
> cost that private symbols would have had. We can help implementors
> achieve that by having this expansion call instead
> "WeakMap(USE_KEY_LIFETIME_HINT)" or whatever it is called. Then
> implementations would not have to recognize the pattern by other
> means.
>
> Complexity is the enemy of security. We already have four
> encapsulation mechanisms in ES6 in addition to private symbols:
> 1) functions encapsulating lexical variables
> 2) WeakMaps
> 3) proxies encapsulating handlers and targets
> 4) modules encapsulating what they don't export.
>
> With enough spec and engineering effort, any of these could be grown
> into a means for providing efficient class/object encapsulation. Of
> them, I think #2 is most plausible. Even is we find #2 does not work
> out, we should think about growing one of the other candidates as an
> alternative to private symbols. Security demands simplicity, and
> semantic simplicity is more important than implementation simplicity.
>
>
>
> --
>    Cheers,
>    --MarkM
> _______________________________________________
> es-discuss mailing list
> es-discuss at mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
>
>
> --
> Dr. Axel Rauschmayer
> axel at rauschma.de
>
> home: rauschma.de
> twitter: twitter.com/rauschma
> blog: 2ality.com
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20130117/9e869406/attachment.html>


More information about the es-discuss mailing list