Mark S. Miller (2015-02-19T18:06:32.000Z)
On Thu, Feb 19, 2015 at 9:54 AM, Andrea Giammarchi <
andrea.giammarchi at gmail.com> wrote:

> Just as workaround, if you really need that much to freeze the
> `Object.prototype`, you could:
>
> ```js
> Object
>   .getOwnPropertyNames(Object.prototype)
>   .filter((name) => !/^constructor|toString|valueIOf$/.test(name))
>   .forEach((name) => Object.defineProperty(
>     Object.prototype,
>     name,
>     {value: Object.prototype[name]}
>   ))
>


Your defineProperty call above has no effect. When doing a defineProperty
on an existing property, recall that omitting attributes means that the
setting of these attributes should not be changed. Omitted attributes only
default to false when the property does not already exist.

Interesting that I've seen this bug several times now, by several different
authors. Apparently, it is an unanticipated footgun in the ES5 reflection
API.



> ;
> Object.preventExtensions(Object.prototype);
> ```
>
> You can eventually fix those 3 properties somehow via accessors.
>
> Not ideal, but it should hopefully make your project work (at least)
>
> Best Regards
>
>
> On Thu, Feb 19, 2015 at 5:23 PM, David Bruant <bruant.d at gmail.com> wrote:
>
>> Hi,
>>
>> Half a million times the following meta-exchange happened on es-discuss:
>> - if an attacker modifies Object.prototype, then you're doomed in all
>> sorts of ways
>> - Don't let anyone modify it. Just do Object.freeze(Object.prototype)!
>>
>> I've done it on client-side projects with reasonable success. I've just
>> tried on a Node project and lots of dependencies started throwing errors.
>> (I imagine the difference is that in Node, it's easy to create projects
>> with a big tree of dependencies which I haven't done too much on the client
>> side).
>>
>> I tracked down a few of these errors and they all seem to relate to the
>> override mistake [1].
>> * In jsdom [2], trying to add a "constructor" property to an object fails
>> because Object.prototype.constructor is configurable: false, writable: false
>> * in tough-cookie [3] (which is a dependency of the popular 'request'
>> module), trying to set Cookie.prototype.toString fails because
>> Object.prototype.toString is configurable: false, writable: false
>>
>> Arguably, they could use Object.defineProperty, but they won't because
>> it's less natural and it'd be absurd to try to fix npm. The
>> Cookie.prototype.toString case is interesting. Of all the methods being
>> added, only toString causes a problem. Using Object.defineProperty for this
>> one would be an awkward inconsistency.
>>
>>
>> So, we're in a state where no module needs to modify Object.prototype,
>> but I cannot freeze it because the override mistake makes throw any script
>> that tries to set a toString property to an object.
>> Because of the override mistake, either I have to let Object.prototype
>> mutable (depite no module needing it to be mutable) or freeze it first hand
>> and not use popular modules like jsdom or request.
>>
>> It's obviously possible to replace all built-in props by accessors [4],
>> of course, but this is a bit ridiculous.
>> Can the override mistake be fixed? I imagine no web compat issues would
>> occur since this change is about throwing less errors.
>>
>> David
>>
>> [1] http://wiki.ecmascript.org/doku.php?id=strawman:fixing_
>> override_mistake
>> [2] https://github.com/tmpvar/jsdom/blob/6c5fe5be8cd01e0b4e91fa96d02534
>> 1aff1db291/lib/jsdom/utils.js#L65-L95
>> [3] https://github.com/goinstant/tough-cookie/blob/
>> c66bebadd634f4ff5d8a06519f9e0e4744986ab8/lib/cookie.js#L694
>> [4] https://github.com/rwaldron/tc39-notes/blob/
>> c61f48cea5f2339a1ec65ca89827c8cff170779b/es6/2012-07/july-
>> 25.md#fix-override-mistake-aka-the-can-put-check
>> _______________________________________________
>> es-discuss mailing list
>> es-discuss at mozilla.org
>> https://mail.mozilla.org/listinfo/es-discuss
>>
>
>
> _______________________________________________
> 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/20150219/f4fb24e4/attachment-0001.html>
d at domenic.me (2015-02-22T03:29:31.596Z)
On Thu, Feb 19, 2015 at 9:54 AM, Andrea Giammarchi <andrea.giammarchi at gmail.com> wrote:

> Just as workaround, if you really need that much to freeze the
> `Object.prototype`, you could:

Your defineProperty call above has no effect. When doing a defineProperty
on an existing property, recall that omitting attributes means that the
setting of these attributes should not be changed. Omitted attributes only
default to false when the property does not already exist.

Interesting that I've seen this bug several times now, by several different
authors. Apparently, it is an unanticipated footgun in the ES5 reflection
API.