Nuking misleading properties in `Object.getOwnPropertyDescriptor`

Mark S. Miller erights at google.com
Wed Mar 13 08:49:59 PDT 2013


On Wed, Mar 13, 2013 at 8:26 AM, Nathan Wall <nathan.wall at live.com> wrote:

> David Bruant wrote:
> > Tom Van Cutsem wrote:
> > > To my mind, the blame for the breakage lies with `Object.prototype`
> > > being mutated by the third-party script, not with property descriptors
> > > inheriting from Object.prototype. Thus, a fix for the breakage should
> > > address that directly, rather than tweaking the design of property
> > > descriptors, IMHO.
> > I agree.
> >
> > The first (security) decision any JavaScript application should make
> > would be to freeze all built-ins like SES [3][4] does. (In the future,
> > it could even make sense to add a CSP [5] directive for that)
> > If necessary, the application can first enhance the environment by
> > adding polyfills/libraries and such, but that's pretty much the only
> > thing that's acceptable to run before freezing everything.
>
> Hey David and Tom.  This is good advice for application authors, but I
> don't work at the application level; I write libraries.  I don't want to
> freeze everything because I want to leave the environment open to
> monkey-patching and shimming by other libraries and the application
> authors. So this isn't an option for me.
>
> > "what if an attacker switches Array.prototype.push and
> Array.prototype.pop?"
>
> These are issues that are easy to address by using stored late-bound
> function references rather than methods and array-likes instead of true
> arrays.
>
>     var push = Function.prototype.call.bind(Array.prototype.push),
>         arrayLike = Object.create(null);
>     arrayLike.length = 0;
>     push(arrayLike, 'item-1');
>
> As long as the environment is correct when my script initializes, I get
> all methods I need to use stored inside my library's closure. Freezing
> isn't needed.
>

That's correct. I've written a bit of code like that myself. At first, for
those used to JS or even just conventional oo, the style needed is very
counter-intuitive and awkward -- it goes against the grain of what the
language tries to make convenient. But amazingly, it is possible, and one
even gets used to it after a while.

We need a name for your use case. It is definitely distinct from the normal
JS library writing practice, which implicitly assumes that the primordials
haven't been too corrupted but does nothing to detect if this is true. And
distinct from the opposite extreme -- the SES library practice, which may
rely on the primordials having been made incorruptible. Amusingly, these
extremes resemble each other much more than they resemble your middle
ground.

For your use case, your analysis of the defineProperty problem is indeed
valid. To date, few if any language design decisions have purposely been
made to accommodate this use case, although some language changes have
helped anyway. I think perhaps the shortest path towards anything like the
defineProperty reform you seek is to argue first why this use case is
important.




>
> It's also possible to write around the `defineProperty` problem by
> converting the descriptor into a prototype-less object. However, I actually
> encountered some performance problems with this. I was able to improve the
> performance by only dropping the prototype when necessary (as long as
> `get`, `set`, `value` or `writable` haven't been added to
> `Object.prototype`, it's not necessary). However, as a matter of principle,
> my argument is that `Object.getOwnPropertyDescriptor` should, at the bare
> minimum, return a descriptor that can be known to work in
> `Object.defineProperty`.  If `Object.defineProperty` doesn't accept it,
> then you `getOwnPropertyDescriptor` didn't really give me a valid
> descriptor.
>
> I think that this behavior (1) limits the creativity of developers to
> define properties like `Object.prototype.get`, (2) is a potential stumbling
> block, (3) has no real benefit -- really, there's not anything positive
> about this behavior, and (4) forces developers who want to support
> `Object.prototype.get` to add an extra layer of cleaning before using
> `defineProperty`.
>
> Nathan
> _______________________________________________
> es-discuss mailing list
> es-discuss at mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
>



-- 
    Cheers,
    --MarkM
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20130313/a882bcda/attachment-0001.html>


More information about the es-discuss mailing list