Object.prototype.* writable?

Mark S. Miller erights at google.com
Sat May 7 18:37:55 PDT 2011

On Sat, May 7, 2011 at 5:05 PM, Kyle Simpson <getify at gmail.com> wrote:

> My first reaction to this assertion is to say: "so?" It's a rather moot
>>> argument to suggest that code which can be altered before it's run isn't
>>> trustable... of course it isn't. [...] because any malicious script (if it's
>>> first on the page) can completely hijack another part of the page? Yup, I
>>> agree.
>> That was my point. Since you agree, I don't understand your point:
> My point was that your argument was deflecting from the premise of the
> original request in a way that makes the conversation impossible to proceed.
> If you re-define the premise/assumptions to an unreasonable level, you make
> logical reasoning impossible.

Good, we're making progress. Previously I was not responding to your
original request, I was responding to your response to Crock's message.
Hence our confusion about premises. Thanks for making your's clearer. As for
your original request, now that I better understand what you're looking for,
I think SES is again a good answer. Should SES become a directly supported
standard, there would be some opt-in as you suggest. For now, for SES as
implemented on ES5 <http://codereview.appspot.com/4249052/>, the interim
opt-in is to run initSES.js first in the JavaScript context in question. In
the case of a browser frame, the interim opt-in is to place

    <script src="initSES.js></script>

before any other scripts.

Whereas the strict mode and anticipated harmony opt-ins are per-script
within a context, the SES opt-in needs to be per-context (i.e., per frame).
Here, I'll avoid speculating about the concrete form of a standard SES
opt-in and answer your original request in terms of this interim SES-as-ES5
library opt-in:

On Sat, May 7, 2011 at 9:44 AM, Kyle Simpson <getify at gmail.com> wrote:

> I apologize if the question I'm about to ask has already been "dealt with",
> but I just ran across a nasty instance of it, and wanted to just ping the
> topic to see what the language guardians have to say about it.
> It's a well known fact that overwriting anything in Object.prototype (like
> Object.prototype.toString, for instance) is a very bad idea, because it
> breaks for-in looping. It also affects every single object, including even
> natives/built-ins, often in unexpected ways.
> So, a few questions:
> 1. Would it be possible to specify that changes to Object.prototype.* do
> NOT affect any of the natives/built-ins?
> 2. Would it be possible for Object.prototype.* to be read-only for
> ES-Harmony (or even just strict mode)?

By placing

    <script src="initSES.js></script>

at the beginning of your frame, earlier than loading any other scripts, you
opt-in to SES and make Object.prototype.* read-only.

> 3. By read-only, I mean that changes to it would just silently be
> discarded. Alternatively (especially for strict mode), warnings/errors could
> be thrown if attempting to override them?

Exactly. Strict assignments to these properties will fail with a thrown
exception. Non-strict assignments will fail silently. But neither can mutate
these properties.

> I think that being able to override something like
> Object.prototype.toString to "lie" about objects/values is a "security" hole
> we should consider plugging. For instance, you can "lie" to
> `document.location.href.toString()`... or a call like
> `Object.prototype.toString.call(window.opera) == "[object Opera]"` (a common
> browser inference for Opera) is easily fake'able.

SES does not freeze objects or properties outside the ES5 spec. So it does
nothing to freeze document's "location", location's "href", or window's
"opera". If you want to prevent these from being modified by post-opt-in
scripts, you can extend your initialization-time "opt-in" to opt-in to SES
and whatever additional freezing you'd like.

But again I may be answer something other than what you are really asking.
Given that document.location.href and window.opera return what you expect,
SES guarantees the rest of your expressions --- <string>.toString() and
Object.prototype.toString.call(*) -- do what you expect. Is that what you
were really asking for here?

Note that even this "rest of your expressions" require more that just
Object.prototype.* to remain reliable. The first also requires
String.prototype.toString. The latter also requires Function.prototype.call.
SES guarantees that all these and more remain reliable.

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20110507/894165a5/attachment.html>

More information about the es-discuss mailing list