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.

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@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss

Reply via email to