Security Demands Simplicity (was: Private Slots)

Axel Rauschmayer axel at rauschma.de
Thu Jan 17 09:43:27 PST 2013


Right. That could work in favor of this approach.

On Jan 17, 2013, at 18:35 , Brandon Benvie <brandon at brandonbenvie.com> wrote:

> 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
> 
> 

-- 
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/46a5e430/attachment-0001.html>


More information about the es-discuss mailing list