__proto__ security

# David Bruant (14 years ago)

This is an attempt to list and discuss how threats of a mutable proto can be prevented and how it is different in the data and accessor property cases.

One frame

Assuming code from 2 parties are running in the same "frame" (one set of built-ins)


var o = Object.create(Object.freeze({a:1})); o.a = 1; // and may assume it will keep being this way unless shadowing 'a'

// passing o to malicious code: o.proto = {a:2};

// back in normal code: o.a; // 2. hey! WTF!

How to prevent this?

delete Object.prototype.proto

Unconditionnally prevents using proto (setting and getting!) for everyone (even those who would have "legitimate" use cases).

In case the property is a configurable accessor, the prototype setting capability can be removed, getting can be left and the property can be made non-configurable. The party who does this can keep the prototype setting capability to herself and share with whoever she trusts. It is also possible to share an attenuated version of the capability (allowing to change the prototype of some objects and not some others)

non-extensible as protection

Object.preventExtensions(o) would protect just o. This technique and the previous one could be used together.

Several Object.prototype.proto in the same "Vat" (synchronous

access to several Object.prototype.proto)

Startup

If there are several Object.prototype at startup, the work to secure all of them is just the work to secure one (delete or finer-grained version of the accessor case), but repeated.

Dynamic creation of Object.prototype.proto instances

If a new Object.prototype.proto becomes reachable (by opening a same-origin iframe, for instance), if the parent can run before any script in the child, she can do whatever she wants:

  • deleting childframe.Object.prototype.proto if she wants to defend against what the child could do
  • redefine any built-ins to attack the child. If the child can run some code before the parent is notified that a new Object.prototype.proto is reachable, she can protect herself against the parent or attack (redefine any built-in) of her parent.

Questions

  • What are all the cases in nowadays browsers where a new Object.prototype.proto can be dynamically created? (The only one I can think of is same-domain iframe, but I think there exists some weird rules for one frame to access another by changing its own domain to a subdomain, or something like this)
  • For each case, who has access to the other first? The creater or the creature?
  • One difference that is made in the accessor case is that if one party runs before the other, then this first one can keep a reference to the setter. Does this increase the already existing attack surface?
# Gavin Barraclough (14 years ago)

On Jan 20, 2012, at 4:07 PM, David Bruant wrote:

  • What are all the cases in nowadays browsers where a new Object.prototype.proto can be dynamically created? (The only one I can think of is same-domain iframe, but I think there exists some weird rules for one frame to access another by changing its own domain to a subdomain, or something like this)
  • For each case, who has access to the other first? The creater or the creature?
  • One difference that is made in the accessor case is that if one party runs before the other, then this first one can keep a reference to the setter. Does this increase the already existing attack surface?

Hi David,

It seems that the best way to neutralize the thread from new proto instances, would be to simply prohibit proto taken from one iframe to be applied to objects created in another. I think this should be achievable with the following tweaks to the strawman:

  • The [[ProtoSetter]] method holds a private reference [[OwnerObjectPrototype]] to the ObjectPrototype upon which .
  • Add a step 2b to the definition of [ProtoSetter], specifying: Walk the prototype chain of O, comparing each successive prototype to the stored [[OwnerObjectPrototype]]. If the prototype chain does not contain [[OwnerObjectPrototype]], throw a TypeError.

What do you think? – are there holes this leaves open?

# Brendan Eich (14 years ago)

I don't think we should change proto unnecessarily from current implementations, including making it an accessor. Neither JSC nor SpiderMonkey does that.

We do need the ability to delete it, so it should live on Object.prototype and be configurable.

Ignoring the "don't gild the lily" (or "don't polish the turd") advice above, if we do reflect proto as an accessor, then the same-frame problem still exists. Perhaps it can be solved by proxies, but why require that?

# David Bruant (14 years ago)

Le 28/01/2012 18:16, Brendan Eich a écrit :

I don't think we should change proto unnecessarily from current implementations, including making it an accessor. Neither JSC nor SpiderMonkey does that.

We do need the ability to delete it, so it should live on Object.prototype and be configurable.

Having given more thought about it, I agree that making proto a setter is unnecessary and will lead to some additional complication. Benefits are things that are not wanted anyway.

It is unnecessary, because it is currently not a setter everywhere (so if people rely on proto, they do not rely in it being an accessor) and if proto was an accessor it would be an encouragement to use the setting part as a capability. If a setter could be extracted, people will write code extracting it and lead to a position from which implementors won't be able to come back, maybe permanently being stuck with a [[Prototype]] setting capability in "JS-of-reaity".

Regarding the specification (as optional normative) of proto as an data descriptor, either the spec can invoke some magic (which is what implementations already do from an ES5 point of view) or redefine Object.prototype as a proxy. The target of this proxy would be the standard Object.prototype and the handler would just define some trap behavior that deal with proto.

# Gavin Barraclough (14 years ago)

Le 28/01/2012 18:16, Brendan Eich a écrit :

I don't think we should change proto unnecessarily from current implementations, including making it an accessor. Neither JSC nor SpiderMonkey does that.

If the spec includes an optional normative definition of proto that requires it to be a configurable property of Object.prototype then a significant rewrite of JSC's proto implementation will be necessary. That's okay – it seems worthwhile doing so to make it possible to delete the proto property. The logical way to implement this in JSC is likely as an accessor property.

So the question for us is not whether changing our implementation is necessary (it is), but rather whether having cleaned this up, we will then need to add back in new magic to make proto masquerade as a data descriptor to match SpiderMonkey. The less magical proto is the better, so this seems undesirable. Since the implementation in JSC will need to change anyway, we're motivated to aim for the least magical behaviour, but for SpiderMonkey, which already has a better implementation for proto, I can see why requiring a change would be undesirable.

On Jan 28, 2012, at 10:20 AM, David Bruant wrote:

Regarding the specification (as optional normative) of proto as an data descriptor, either the spec can invoke some magic (which is what implementations already do from an ES5 point of view) or redefine Object.prototype as a proxy. The target of this proxy would be the standard Object.prototype and the handler would just define some trap behavior that deal with proto.

Given this is proto we're talking about, maybe it just isn't worth being overly specific here?

How about we just specify that: * The only permissible way to modify an object's [[Prototype]] is through proto. * proto must be a property of Object.prototype. * proto must be configurable.

This would mean that any conforming implementation would have a easy, spec-defined way to remove proto, without burdening browsers who implement this as a data descriptor to change their implementations to make it an accessor descriptor, or burdening browsers who implement this as an accessor descriptor to change their implementations to make it a data descriptor.

Are there a significant practical benefit of a more restrictive specification that this fails to cover?

# Allen Wirfs-Brock (14 years ago)

I don't think we would ever want to expose proto as an accessor property on Object.prototype as that would expose set/get functions that would also have the capabilities of proto without being associated with that special property.

I can easily write a specification for proto that essentially has the SpiderMonkey observable behavior (including exposing a data property on object prototype) without mandating the observable use of accessor properties or any other specific implementation mechanism. How you go about invisibly implementing it would be up to you. Since most implementations already seem to have special mechanism for giving "magic" behavior to certain properties I would expect them to use some of those mechanisms here.

# Mark S. Miller (14 years ago)

On Sat, Jan 28, 2012 at 12:16 PM, Brendan Eich <brendan at mozilla.org> wrote:

I don't think we should change proto unnecessarily from current implementations, including making it an accessor. Neither JSC nor SpiderMonkey does that.

We do need the ability to delete it, so it should live on Object.prototype and be configurable.

Ignoring the "don't gild the lily" (or "don't polish the turd") advice above, if we do reflect proto as an accessor, then the same-frame problem still exists. Perhaps it can be solved by proxies, but why require that?

I didn't follow that. The current strawman < strawman:magic_proto_property> says

in step 2 of [[ProtoSetter]]:

2. If O is not an object from this context, throw a *TypeError*

exception.

I don't say anything about how this test is performed because we don't yet know how we'll represent the extra bookkeeping needed to spec the interaction of multiple globals. This is inter-frame protection only.

I like your proposal because I think the intra-frame protection it provides is nice. But I don't think it is essential. If proto does reflect as an accessor as currently stated in the strawman, with the inter-frame restriction, I think that would be ok.

# Mark S. Miller (14 years ago)

On Sat, Jan 28, 2012 at 12:16 PM, Brendan Eich <brendan at mozilla.org> wrote:

I don't think we should change proto unnecessarily from current implementations, including making it an accessor. Neither JSC nor SpiderMonkey does that.

We do need the ability to delete it, so it should live on Object.prototype and be configurable.

Ignoring the "don't gild the lily" (or "don't polish the turd") advice above, if we do reflect proto as an accessor, then the same-frame problem still exists. Perhaps it can be solved by proxies, but why require that?

And what is the connection with proxies? I don't get it.

# Mark S. Miller (14 years ago)

On Sat, Jan 28, 2012 at 5:21 PM, Gavin Barraclough <barraclough at apple.com>wrote: [...]

Given this is proto we're talking about, maybe it just isn't worth being overly specific here?

How about we just specify that: * The only permissible way to modify an object's [[Prototype]] is through proto. * proto must be a property of Object.prototype. * proto must be configurable.

This would mean that any conforming implementation would have a easy, spec-defined way to remove proto, without burdening browsers who implement this as a data descriptor to change their implementations to make it an accessor descriptor, or burdening browsers who implement this as an accessor descriptor to change their implementations to make it a data descriptor.

Are there a significant practical benefit of a more restrictive specification that this fails to cover?

Reducing gratuitous observable differences between implementations. I care much more that we all agree on one alternatives than I care which one it is.

# Mark S. Miller (14 years ago)

On Sat, Jan 28, 2012 at 6:58 PM, Allen Wirfs-Brock <allen at wirfs-brock.com>wrote:

I don't think we would ever want to expose proto as an accessor property on Object.prototype as that would expose set/get functions that would also have the capabilities of proto without being associated with that special property.

As long as they are restricted to objects from their frame of origin, I don't see much wrong with it. Again, I have come to prefer Brendan's non-accessor approach, but I don't see any strong reason to prefer one over the other. From a SES security POV the difference matters not at all, since the first thing the SES initialization would do in such a frame is to delete proto anyway.

# Brendan Eich (14 years ago)

Mark S. Miller wrote:

On Sat, Jan 28, 2012 at 12:16 PM, Brendan Eich <brendan at mozilla.org <mailto:brendan at mozilla.org>> wrote:

I don't think we should change __proto__ unnecessarily from
current implementations, including making it an accessor. Neither
JSC nor SpiderMonkey does that.

We do need the ability to delete it, so it should live on
Object.prototype and be configurable.

Ignoring the "don't gild the lily" (or "don't polish the turd")
advice above, if we *do* reflect __proto__ as an accessor, then
the same-frame problem still exists. Perhaps it can be solved by
proxies, but why require that?

I didn't follow that. The current strawman strawman:magic_proto_property says in step 2 of [[ProtoSetter]]:

2. If O is not an object from this context, throw a 

TypeError exception.

I don't say anything about how this test is performed because we don't yet know how we'll represent the extra bookkeeping needed to spec the interaction of multiple globals. This is inter-frame protection only.

Yes, that's why I wrote "the same-frame problem still exists".

I like your proposal because I think the intra-frame protection it provides is nice. But I don't think it is essential.

It's hard to prove what is essential, but my "proxies" point was to ask: must membranes be used to protect here, when the pseudo-data-property approach relieves us of any such requirement?

If proto does reflect as an accessor as currently stated in the strawman, with the inter-frame restriction, I think that would be ok.

It's ok but I think the pseudo-data way is "more ok" ;-).

# Gavin Barraclough (14 years ago)

On Jan 28, 2012, at 3:58 PM, Allen Wirfs-Brock wrote:

Since most implementations already seem to have special mechanism for giving "magic" behavior to certain properties I would expect them to use some of those mechanisms here.

No - in JSC I'm pretty sure it's going to be faster and cleaner to implement this as a regular accessor property.

Now, it would certainly be possible to add a mechanism to allow this accessor to masquerade itself as a data property, but it just seems too magical and unnecessarily weird to do so. It behaves like an accessor, so it should look like one.

# Allen Wirfs-Brock (14 years ago)

On Jan 29, 2012, at 12:40 AM, Gavin Barraclough wrote:

On Jan 28, 2012, at 3:58 PM, Allen Wirfs-Brock wrote:

Since most implementations already seem to have special mechanism for giving "magic" behavior to certain properties I would expect them to use some of those mechanisms here.

No - in JSC I'm pretty sure it's going to be faster and cleaner to implement this as a regular accessor property.

Now, it would certainly be possible to add a mechanism to allow this accessor to masquerade itself as a data property, but it just seems too magical and unnecessarily weird to do so. It behaves like an accessor, so it should look like one.

Other standard properties that have accessor like characteristics but look like data properties:

array element properties array length property string character element properties argument object elements the "caller" property of function objects (see 15.3.5.4)

# Gavin Barraclough (14 years ago)

On Jan 29, 2012, at 11:36 AM, Allen Wirfs-Brock wrote:

Other standard properties that have accessor like characteristics but look like data properties:

array element properties array length property string character element properties argument object elements the "caller" property of function objects (see 15.3.5.4)

The special handling for setting array length and and numeric properties fits well with the spec's existing division of labour between the [[Put]] and [[DefineOwnProperty]] algorithms, and is well encapsulated. [[Put]] provides a simple set of rules for determining whether a [[DefineOwnProperty]] will be called on the base of the access, or whether a setter will be called on the prototype chain. The 'magic' here is constrained to certain objects overriding the [[DefineOwnProperty]] trap (e.g. 15.4.5.1).

It seems that any 'magic' to make proto work in the proposed fashion could not be constrained to a [[DefineOwnProperty]] trap for the Object prototype, since if proto is a data descriptor [[Put]] will trigger [[DefineOwnProperty]] trap on the base of the access. Any special handling would either need to also rework [[Put]] to cause the special proto trap to be triggered, or would need to be worked into Objects's [[DefineOwnProperty]] (8.12.9). Any special handling in 8.12.9 would need to be non-trivial, since setting an object's proto property would mean re-inspecting the prototype chain to see whether the nearest proto was the magic data descriptor. Either way seems unnecessarily complicated, and much less well encapsulated than Array's special handling of [[DefineOwnProperty]].

I just don't see why we would want to muddy up some core mechanisms of the object model, making them more difficult for users of the language to understand, for the non-benefit of making proto appear to be something that it isn't. It just seems like a bad idea wrapped in a bad idea to me.

# Allen Wirfs-Brock (14 years ago)

On Jan 29, 2012, at 3:25 PM, Gavin Barraclough wrote:

On Jan 29, 2012, at 11:36 AM, Allen Wirfs-Brock wrote:

Other standard properties that have accessor like characteristics but look like data properties:

array element properties array length property string character element properties argument object elements the "caller" property of function objects (see 15.3.5.4)

The special handling for setting array length and and numeric properties fits well with the spec's existing division of labour between the [[Put]] and [[DefineOwnProperty]] algorithms, and is well encapsulated. [[Put]] provides a simple set of rules for determining whether a [[DefineOwnProperty]] will be called on the base of the access, or whether a setter will be called on the prototype chain. The 'magic' here is constrained to certain objects overriding the [[DefineOwnProperty]] trap (e.g. 15.4.5.1).

It seems that any 'magic' to make proto work in the proposed fashion could not be constrained to a [[DefineOwnProperty]] trap for the Object prototype, since if proto is a data descriptor [[Put]] will trigger [[DefineOwnProperty]] trap on the base of the access. Any special handling would either need to also rework [[Put]] to cause the special proto trap to be triggered, or would need to be worked into Objects's [[DefineOwnProperty]] (8.12.9). Any special handling in 8.12.9 would need to be non-trivial, since setting an object's proto property would mean re-inspecting the prototype chain to see whether the nearest proto was the magic data descriptor. Either way seems unnecessarily complicated, and much less well encapsulated than Array's special handling of [[DefineOwnProperty]].

There are no rules that constrain [[Put]] in this manner you are suggesting.

I just don't see why we would want to muddy up some core mechanisms of the object model, making them more difficult for users of the language to understand, for the non-benefit of making proto appear to be something that it isn't. It just seems like a bad idea wrapped in a bad idea to me.

Well, arguably the existence of proto is what muddys up some of the core semantics of the object model.

I would specify it as a modification to the normal [[Get]] and [[Put]] behavior that special cases on the property key value "proto". That special case (of [[Put]]) would not call [[DefineOwnPropertry]]. It would include check the prototype chain but that is part of the proposed semantics.

This seems like a perfectly reasonable way to specify this. As proto does indeed affect the property access semantics for every object. Of course, I'm only talking specification. How you accomplish it in your implementation is up to you.

There are other, alternatives.

If we were willing to only define obj.proto and exclude obj["proto"] I could specify it in 11.2.1 as a special case semantics of dot property access notation and have to extend any of the internal methods.

# Gavin Barraclough (14 years ago)

On Jan 29, 2012, at 4:25 PM, Allen Wirfs-Brock wrote:

There are no rules that constrain [[Put]] in this manner you are suggesting.

Sorry, perhaps my comments were unclear. The observation I was intending to highlight was only that the current behaviour of [[Put]] will be to call [[DefineOwnProperty]] on a base object that is not the object that logically contains the 'magic' property, if the proto is specified as a data descriptor.

E.g.

Object.prototype.p = 1; var a = {}; a.p = 2;

The [[Put]] of '2' will call the [[DefineOwnProperty]] trap of 'a', not the object that currently contains a data descriptor for p.

Hence (as I think you recognize in your comments), it would not simply be sufficient to provide an overridden implementation for [[DefineOwnProperty]] for the object prototype. This does mean that the 'magic' behaviour cannot be as easily and cleanly encapsulated as it can for Array, where the 'magic' properties are directly on the base object passed to [[DefineOwnProperty]].

This seems like a perfectly reasonable way to specify this. As proto does indeed affect the property access semantics for every object. Of course, I'm only talking specification. How you accomplish it in your implementation is up to you.

There are other, alternatives.

I'm not questioning for a minute that this is possible – it certainly is – I'm just stating that it seems to be completely unnecessary, confusing, and not a good idea to do so. :-) Seriously, why are we doing this? – proto is an accessor, it's much simpler to just spec it as such, why are we trying to set up hoops for ourselves to jump through to avoid doing so?

# Herby Vojčík (14 years ago)

Gavin Barraclough wrote:

I just don't see why we would want to muddy up some core mechanisms of the object model, making them more difficult for users of the language to understand, for the non-benefit of making proto appear to be something that it isn't. It just seems like a bad idea wrapped in a bad idea to me.

One possibility to take the magic away from [[Put]] would be to revisit something that appeared while talking about "shared part" discussion on non-writable inherited properties. That is, to include fourth attribute, shadowable, with default on true; which when false, would mean the [[DefineOwnProperty]] trap should be called on containing object, not on this.

# Mark S. Miller (14 years ago)

On Sun, Jan 29, 2012 at 6:25 PM, Allen Wirfs-Brock <allen at wirfs-brock.com>wrote: [...]

I would specify it as a modification to the normal [[Get]] and [[Put]] behavior that special cases on the property key value "proto". That special case (of [[Put]]) would not call [[DefineOwnPropertry]]. It would include check the prototype chain but that is part of the proposed semantics.

Then how would you explain the absence of magic after

delete Object.prototype.__proto__;
Object.prototype.__proto__ = 8;

? After these two lines, it should be a normal data property with value 8. If the original property is an accessor, then this falls out nicely -- the magic is in the setter, which is dispensed with in the first line.

If we do make proto appear to be a data property, I think the right way to do it is to specify (and probably also to implement) it as an accessor, but then to specify magical behavior for [[GetOwnProperty]] that lies -- reporting that it is a data property. However, starting from that assumption, I become increasingly uncomfortable with other implications: When should [[DefineOwnProperty]] maintain the illusion vs simply replace it with the property described by the arguments to [[DefineOwnProperty]]? Perhaps the least surprising would be that any call to [[DefineOwnProperty]] replaces the magic with the property described. But any answer to this question will be surprising in some circumstances.

This seems like a perfectly reasonable way to specify this. As proto does indeed affect the property access semantics for every object. Of course, I'm only talking specification. How you accomplish it in your implementation is up to you.

There are other, alternatives.

If we were willing to only define obj.proto and exclude obj["proto"] I could specify it in 11.2.1 as a special case semantics of dot property access notation and have to extend any of the internal methods.

Again, if you specify it this way, how would you cope with deletion followed by addition?

From this discussion, I'm leaning towards Gavin's position. The first

element of language design style perhaps should be "Omit Needless Magic". Your five cases you enumerated are not needless. Aside from the toxic waste of non-strict mode, we are left with only three cases, all of which have to do with indexing into the array-like types Array and String. The trouble caused by array length has been quite painful, even though it is non-configurable. The problems I raise above happen when combining magic with configurability, which doesn't have any precedent among strict native objects.

The one argument I know for the magic, which initially convinced me, is the tighter intra-frame restriction that results. But this extra tightness is AFAICT not relevant to security, given that proto is limited to its own frame and can be deleted. Are there any other arguments in favor of magic here?

# Mark S. Miller (14 years ago)

-1 to adding yet another attribute to the object model (expanding it 16%) unless the payoff is huge. Regarding < strawman:fixing_override_mistake>,

we should simply make a decision one way or another rather than add yet another knob.

# Allen Wirfs-Brock (14 years ago)

On Jan 30, 2012, at 7:08 AM, Mark S. Miller wrote:

On Sun, Jan 29, 2012 at 6:25 PM, Allen Wirfs-Brock <allen at wirfs-brock.com> wrote: [...] I would specify it as a modification to the normal [[Get]] and [[Put]] behavior that special cases on the property key value "proto". That special case (of [[Put]]) would not call [[DefineOwnPropertry]]. It would include check the prototype chain but that is part of the proposed semantics.

Then how would you explain the absence of magic after

delete Object.prototype.__proto__;
Object.prototype.__proto__ = 8;

? After these two lines, it should be a normal data property with value 8. If the original property is an accessor, then this falls out nicely -- the magic is in the setter, which is dispensed with in the first line.

It would simply be part of the special case behavior I would define for [[Get]] and [[Put]]. The disabling effect doesn't require any sort was computational mechanism, a few prose words such as "if the "proto" own property of Object.prototype has been modified in any manner from its initial state described in B.x.y.z..."

If we do make proto appear to be a data property, I think the right way to do it is to specify (and probably also to implement) it as an accessor, but then to specify magical behavior for [[GetOwnProperty]] that lies -- reporting that it is a data property. However, starting from that assumption, I become increasingly uncomfortable with other implications: When should [[DefineOwnProperty]] maintain the illusion vs simply replace it with the property described by the arguments to [[DefineOwnProperty]]? Perhaps the least surprising would be that any call to [[DefineOwnProperty]] replaces the magic with the property described. But any answer to this question will be surprising in some circumstances.

This seems like a perfectly reasonable way to specify this. As proto does indeed affect the property access semantics for every object. Of course, I'm only talking specification. How you accomplish it in your implementation is up to you.

There are other, alternatives.

If we were willing to only define obj.proto and exclude obj["proto"] I could specify it in 11.2.1 as a special case semantics of dot property access notation and have to extend any of the internal methods.

Again, if you specify it this way, how would you cope with deletion followed by addition?

as above

From this discussion, I'm leaning towards Gavin's position. The first element of language design style perhaps should be "Omit Needless Magic". Your five cases you enumerated are not needless. Aside from the toxic waste of non-strict mode, we are left with only three cases, all of which have to do with indexing into the array-like types Array and String. The trouble caused by array length has been quite painful, even though it is non-configurable. The problems I raise above happen when combining magic with configurability, which doesn't have any precedent among strict native objects.

I suggest that you all just focus on the any open issues concerning the actual intended semantics and let me worry about drafting the specification language for it. Gavin's concern about whether or not proto manifests as a data property is such an issue. I can handle figuring out a way to best express that decision on the context of our specification. One it is in the draft you can comment on the actual spec. language.

The one argument I know for the magic, which initially convinced me, is the tighter intra-frame restriction that results. But this extra tightness is AFAICT not relevant to security, given that proto is limited to its own frame and can be deleted. Are there any other arguments in favor of magic here?

I don't seen any magic...I just we special cases that must be covered in the specification.

# Luke Hoban (14 years ago)

My takeaway from this thread is that there is support for the proposed proto semantics on the wiki [1], with a few modifications/additions. Are the following a correct summary of the deltas?

*** Accessor vs. Data property Although there does not appear to be a direct security implication of exposing Object.prototype.proto as a true accessor property, there is a desire to be conservative about exposing new proto capabilities beyond what is actually defacto available on browsers today. As a result, the initial value of proto should appear as a data property to developers, but remain internally an accessor property.

*** Object literals The wiki does not currently discuss the semantics of proto in object literals. Given the desire to allow proto to be removed, it seems more details are needed to nail down what this does:

delete Object.prototype.__proto__
{ __proto__: {x: 1} }

I believe there are two options: (1) proto in object literals always sets the [[Prototype]], irrespective of the value of Object.prototype.proto or (2) proto is treated as a [[Put]] instead of a [[DefineProperty]] in the Object Intialiser rules

The second option appears more inline with the goals of the wiki proposal.

When there are multiple proto in an object literal, I believe it has been suggested that this produce a SyntaxError.

*** JSON I believe there is a requirement that JSON.parse('{"proto": {}}') return an object with an own data property named proto whose value is {}. Browsers currently disagree on this though.

Thanks, Luke

[1] strawman:magic_proto_property

# Allen Wirfs-Brock (14 years ago)

Someone should probably ask me to just write the appropriate spec language :-)

On Feb 9, 2012, at 10:53 AM, Luke Hoban wrote:

My takeaway from this thread is that there is support for the proposed proto semantics on the wiki [1], with a few modifications/additions. Are the following a correct summary of the deltas?

*** Accessor vs. Data property Although there does not appear to be a direct security implication of exposing Object.prototype.proto as a true accessor property, there is a desire to be conservative about exposing new proto capabilities beyond what is actually defacto available on browsers today. As a result, the initial value of proto should appear as a data property to developers, but remain internally an accessor property.

Saying it is internally an accessor property really is describing one possible implementation. The real semantics would be that [[Put]]/[[Get]] of "proto" has the appropriate side-effects (conditional upon presence of original Object.prototype.proto"). You can implement that anyway you want as long as it has those semantics.

*** Object literals The wiki does not currently discuss the semantics of proto in object literals. Given the desire to allow proto to be removed, it seems more details are needed to nail down what this does:

but clearly {proto: obj} is needed for web interoperability

delete Object.prototype.proto { proto: {x: 1} }

I believe there are two options: (1) proto in object literals always sets the [[Prototype]], irrespective of the value of Object.prototype.proto or (2) proto is treated as a [[Put]] instead of a [[DefineProperty]] in the Object Intialiser rules

The second option appears more inline with the goals of the wiki proposal.

But we don't want {proto: 12} to change its standard [[DefineOwnProperty]] behavior if Object.prototype.proto has been deleted. this suggests a third option:

(3) proto If the enabling Object.prototype.proto property is present then proto in object literals has the same [[Put]] semantics as an assignment to proto

When there are multiple proto in an object literal, I believe it has been suggested that this produce a SyntaxError.

Duplicate data properties definitions always throw in ES5 strict code and the last definition is used in non-strict code.

{proto: a, proto: b} is a legal non-strict object literal that whose proto property has the value of b.

You can make it a early SyntaxError as part of this extension but cause where it is a [[Prototype]] modifier or just a regular property definition is dynamically defined. I suggest that you just follow the ES5 non-strict rules and use the last definition

*** JSON I believe there is a requirement that JSON.parse('{"proto": {}}') return an object with an own data property named proto whose value is {}.

yes!!

Browsers currently disagree on this though.

Any that mutate [[Prototype]] in this case are introducing a new and extension that should be strongly swatted down.

# Allen Wirfs-Brock (14 years ago)

I've written a draft proto specification for the working draft of the ES6 spec.

Just the proto part of the spec. can be seen here: harmony:draft_proto_spec_.pdf

# Mark S. Miller (14 years ago)

On Thu, Feb 9, 2012 at 4:11 PM, Allen Wirfs-Brock <allen at wirfs-brock.com> wrote:

I've written a draft proto specification for the working draft of the ES6 spec.

Just the proto part of the spec. can be seen here: harmony:draft_proto_spec_.pdfharmony:draft_proto_spec_.pdf

Hi Allen, regarding B3.1.1 and B3.1.2, I was afraid it would have an effect on the spec like that. This is a hack which crufts up the working of some of the most basic operations of the language. For those who would try to prove properties about programs in the language, this extra complexity is where they can least afford it. But given the behavior you're trying to specify, I don't see how to do better than this.

As I wrote earlier in response to Herby:

On Mon, Jan 30, 2012 at 7:13 AM, Mark S. Miller <erights at google.com> wrote:

-1 to adding yet another attribute to the object model (expanding it 16%) unless the payoff is huge.

Your UnderscoreProtoEnabled wouldn't seem to be as bad as that, since it is an internal property rather than an attribute. But it is an internal property effecting the behavior of the default [[Get]], [[Put]], and [[DefineOwnProperty]], whose semantics are already way more complex than we'd like.

If we can't indeed specify this behavior in a less invasive way than this, then I would rather see us adopt the approach advocated by Gavin and written up in the current strawman: The dynamic semantics is fully explained by a non-magical accessor property, that appears to be an accessor property, and whose setter is a genuine first class function with the exclusive ability to mutate the [[Prototype]] internal property of extensional objects in its frame. This approach is much much cleaner. It is more permissive, as Brendan points out, but not in a way that needs to harm security.

Regarding B3.1.3, in step 3 of the first algorithm, where does P come from?

# Mark S. Miller (14 years ago)

On Thu, Feb 9, 2012 at 6:11 PM, Mark S. Miller <erights at google.com> wrote: [...]

As I wrote earlier in response to Herby:

On Mon, Jan 30, 2012 at 7:13 AM, Mark S. Miller <erights at google.com> wrote:

-1 to adding yet another attribute to the object model (expanding it 16%)

unless the payoff is huge.

I should make clear that I originally wrote this in response to another issue. Nevertheless...

[...] mutate the [[Prototype]] internal property of extensional objects in its frame. [...]

Should be extensible.

# Allen Wirfs-Brock (14 years ago)

On Feb 9, 2012, at 6:11 PM, Mark S. Miller wrote:

On Thu, Feb 9, 2012 at 4:11 PM, Allen Wirfs-Brock <allen at wirfs-brock.com> wrote: I've written a draft proto specification for the working draft of the ES6 spec.

Just the proto part of the spec. can be seen here: harmony:draft_proto_spec_.pdf

Hi Allen, regarding B3.1.1 and B3.1.2, I was afraid it would have an effect on the spec like that. This is a hack which crufts up the working of some of the most basic operations of the language. For those who would try to prove properties about programs in the language, this extra complexity is where they can least afford it. But given the behavior you're trying to specify, I don't see how to do better than this.

I doubt that you will find anybody who will argue that the original functionality was ever anything more than a hack. But the I think this specification is pretty close to the minimum necessary to specify it.

Somebody trying to prove properties about program certainly could attempt to transform it into an equivalent specification.

As I wrote earlier in response to Herby:

On Mon, Jan 30, 2012 at 7:13 AM, Mark S. Miller <erights at google.com> wrote: -1 to adding yet another attribute to the object model (expanding it 16%) unless the payoff is huge.

Your UnderscoreProtoEnabled wouldn't seem to be as bad as that, since it is an internal property rather than an attribute. But it is an internal property effecting the behavior of the default [[Get]], [[Put]], and [[DefineOwnProperty]], whose semantics are already way more complex than we'd like.

and [[Delete]]. And its not a property, just a piece of internal state global state. Also, I made sure to make all the changes to these key internal methods as prologues to the normal definitions.

If we can't indeed specify this behavior in a less invasive way than this, then I would rather see us adopt the approach advocated by Gavin and written up in the current strawman: The dynamic semantics is fully explained by a non-magical accessor property, that appears to be an accessor property, and whose setter is a genuine first class function with the exclusive ability to mutate the [[Prototype]] internal property of extensional objects in its frame. This approach is much much cleaner. It is more permissive, as Brendan points out, but not in a way that needs to harm security.

I would expect Gavin's approach to ultimately be even worse than mine from a semantic analysis perspective. It expose (via Object.getOwnPropertyDescriptor) functions that have the ability to mutate any object's [[Prototype]] property and one those functions are exposed they can be installed as methods or explicitly called at any time. I think that tame them is likely to have even greater impact than what I have done. Certainly, for the ES5 language level (which is what my current spec. addresses) there is no way to talk about frames or the association of one of these functions or any other object with a frame. With my approach there is no need to match the proto mutator function's frame with the target object's frame, because there is no mutator function.

Finally there is the object literal issue which was not address by the original wiki proposal.

Regarding B3.1.3, in step 3 of the first algorithm, where does P come from?

oops, P should be propId.name also in step 5 of the second algorithm

# Allen Wirfs-Brock (14 years ago)

A newer versions with several corrections: harmony:draft_proto_spec_rev2.pdf

# Gavin Barraclough (14 years ago)

On Feb 9, 2012, at 7:18 PM, Allen Wirfs-Brock wrote:

I would expect Gavin's approach to ultimately be even worse than mine from a semantic analysis perspective. It expose (via Object.getOwnPropertyDescriptor) functions that have the ability to mutate any object's [[Prototype]] property and one those functions are exposed they can be installed as methods or explicitly called at any time. I think that tame them is likely to have even greater impact than what I have done. Certainly, for the ES5 language level (which is what my current spec. addresses) there is no way to talk about frames or the association of one of these functions or any other object with a frame. With my approach there is no need to match the proto mutator function's frame with the target object's frame, because there is no mutator function.

Hi Allen,

I completely agree with you that frame-based checks should not be a part of the solution, however they are no more necessary if proto is an accessor property then if it is a data descriptor. The solution I proposed was that the [[ProtoSetter]] should hold a private reference to the Object Prototype upon which it is initially assigned, and that upon being invoked it should walk the this object's prototype chain to see if it any entry matches the stored value. With a check such as this in place (I expect there are other ways we could achieve this), it would not be possible to apply a given [[ProtoSetter]] to any object other than those upon which it would initially have been available to operate via the Object Prototype.

Finally there is the object literal issue which was not address by the original wiki proposal.

You're right, we do need to expand the proposal to cover this. This doesn't seem too difficult. If the identifier being assigned to in an object literal initialization is "proto", then check whether the Object Prototype contains a property named "proto" whose descriptor has a "set" value equal to that Object Prototype's original [[ProtoSetter]] function, if so then the assignment sets the newly constructed object's prototype, otherwise it defines a own property as usual.

# David Bruant (14 years ago)

Le 10/02/2012 09:23, Gavin Barraclough a écrit :

On Feb 9, 2012, at 7:18 PM, Allen Wirfs-Brock wrote:

I would expect Gavin's approach to ultimately be even worse than mine from a semantic analysis perspective. It expose (via Object.getOwnPropertyDescriptor) functions that have the ability to mutate any object's [[Prototype]] property and one those functions are exposed they can be installed as methods or explicitly called at any time. I think that tame them is likely to have even greater impact than what I have done. Certainly, for the ES5 language level (which is what my current spec. addresses) there is no way to talk about frames or the association of one of these functions or any other object with a frame. With my approach there is no need to match the proto mutator function's frame with the target object's frame, because there is no mutator function.

Hi Allen,

I completely agree with you that frame-based checks should not be a part of the solution, however they are no more necessary if proto is an accessor property then if it is a data descriptor. The solution I proposed was that the [[ProtoSetter]] should hold a private reference to the Object Prototype upon which it is initially assigned, and that upon being invoked it should walk the this object's prototype chain to see if it any entry matches the stored value. With a check such as this in place (I expect there are other ways we could achieve this), it would not be possible to apply a given [[ProtoSetter]] to any object other than those upon which it would initially have been available to operate via the Object Prototype.

Maybe I'm missing something, but what you're proposing is exactly a frame-based check. By assuming there can exist several [[ProtoSetter]] and several Object.prototype, you're implicitely saying that there are several frames. You do not name them, but I can't see the difference between a frame and "a context where objects inherit from a particular Object.prototype".

What you're doing is identifying a frame to the identity of its Object.prototype.

# Gavin Barraclough (14 years ago)

On Feb 10, 2012, at 12:43 AM, David Bruant wrote:

Maybe I'm missing something, but what you're proposing is exactly a frame-based check.

Hi David,

No, the proposed check does not correlate exactly to a frame-based check. For example, an object created using Object.create(null) may be associated with the same frame as a [[ProtoSetter]] function, but the restriction I propose would inhibit the object's prototype from being modified, where a same-frame check would. The check I am proposing is more restrictive.

Also, and importantly (as Allen identifies), the proposed check does not require the spec to talk about frames or their association to objects.

# David Bruant (14 years ago)

Le 10/02/2012 10:07, Gavin Barraclough a écrit :

On Feb 10, 2012, at 12:43 AM, David Bruant wrote:

Maybe I'm missing something, but what you're proposing is exactly a frame-based check.

Hi David,

No, the proposed check does not correlate exactly to a frame-based check. For example, an object created using Object.create(null) may be associated with the same frame as a [[ProtoSetter]] function, but the restriction I propose would inhibit the object's prototype from being modified, where a same-frame check would. The check I am proposing is more restrictive.

Also, and importantly (as Allen identifies), the proposed check does not require the spec to talk about frames or their association to objects.

On Feb 9, 2012, at 7:18 PM, Allen Wirfs-Brock wrote:

Certainly, for the ES5 language level (which is what my current spec. addresses) there is no way to talk about frames or the association of one of these functions or any other object with a frame.

Oh ok, thanks for pointing the differences.

# Tom Van Cutsem (14 years ago)

I'm also in favor of exposing proto as an accessor on the grounds that it is least magical. I'm worried that the changes made here to the core internal methods [[Get]], [[Put]], [[DefineOwnProperty]] and [[Delete]] will give proxies a hard time to properly emulate this behavior if they would want to do that. How would a proxy handler be able to access the internal variable UnderscoreProtoEnabled?

(I currently assume that in any event, aProxy.proto would just trigger the "get" trap for "proto" and that all of this magical behavior does not apply to proxies, only built-in normal objects.)

Also +1 to Gavin's proposed alternative to the frame-check.

Cheers, Tom

2012/2/10 Gavin Barraclough <barraclough at apple.com>

# Andreas Rossberg (14 years ago)

On 10 February 2012 12:46, Tom Van Cutsem <tomvc.be at gmail.com> wrote:

I'm also in favor of exposing proto as an accessor on the grounds that it is least magical. I'm worried that the changes made here to the core internal methods [[Get]], [[Put]], [[DefineOwnProperty]] and [[Delete]] will give proxies a hard time to properly emulate this behavior if they would want to do that. How would a proxy handler be able to access the internal variable UnderscoreProtoEnabled?

I also agree that an accessor is much cleaner (if we really want to spec this at all -- which will de facto make it a blessed feature forever).

However, I'm not sure the proxy argument applies. Either way, it seems, proxies cannot "simulate" the magic of proto themselves, because they have no control over the prototype they disclose anyway. It can only work for proxies if the magic accessor (whether implicit or explicit) transparently forwards the assignment to proxy targets. No trap would be involved, just like there is no trap for getting the prototype of a proxy.

I suppose the real question is: do we want proxies to simulate this in full gory glory? That would be blessing this (mis)feature even more.

# Allen Wirfs-Brock (14 years ago)

On Feb 10, 2012, at 3:46 AM, Tom Van Cutsem wrote:

Hi,

I'm also in favor of exposing proto as an accessor on the grounds that it is least magical. I'm worried that the changes made here to the core internal methods [[Get]], [[Put]], [[DefineOwnProperty]] and [[Delete]] will give proxies a hard time to properly emulate this behavior if they would want to do that. How would a proxy handler be able to access the internal variable UnderscoreProtoEnabled?

function UnderScopeProtoEnabled() { var p={}; return Object.getPrototypeOf({proto:p})===p; }

I believe the root question is whether we are willing to expose for arbitrary usage a function that is able to modify the [[Prototype]] of any object. EG:

Object.setPrototypeOf = function (obj,proto) {Object.getOwnPropertyDescriptor(Object.getPrototypeOf({}),"__proto__").set.call(obj,proto)};

Once we have don this, that function can be used in arbitrary places, including as or within get and set functions of any accessor property with any name on any object.

(I currently assume that in any event, aProxy.proto would just trigger the "get" trap for "proto" and that all of this magical behavior does not apply to proxies, only built-in normal objects.)

Presumably.

Also +1 to Gavin's proposed alternative to the frame-check.

Yes, Gavin check amounts to the same thing as mine, once you allow for differences in how we define Object.prototype.__proto

The important ifference is whether that check is make in the internals of a function that is visible as an accessor get function or whether the check is hidden inside the implementation of the standard internal methods.

# Allen Wirfs-Brock (14 years ago)

On Feb 10, 2012, at 4:08 AM, Andreas Rossberg wrote:

On 10 February 2012 12:46, Tom Van Cutsem <tomvc.be at gmail.com> wrote:

I'm also in favor of exposing proto as an accessor on the grounds that it is least magical. I'm worried that the changes made here to the core internal methods [[Get]], [[Put]], [[DefineOwnProperty]] and [[Delete]] will give proxies a hard time to properly emulate this behavior if they would want to do that. How would a proxy handler be able to access the internal variable UnderscoreProtoEnabled?

I also agree that an accessor is much cleaner (if we really want to spec this at all -- which will de facto make it a blessed feature forever).

I share you concern.

However, we discussed this at the last TC39 meeting. Because of the current dominance of the smart mobile device space by browsers that support proto browsers that have traditionally not implemented it in the more diverse desktop space are under growing pressure to include proto support if they want to compete in the mobile space.

This is rapidly driving proto towards being a de facto standard. Part of TC39's mission is to turn de facto standards into de jure standards and in the process provide a uniform definition for the edge cases where current implementation differ. That is exactly the sort of technical issue that we are now discussing.

However, I'm not sure the proxy argument applies. Either way, it seems, proxies cannot "simulate" the magic of proto themselves, because they have no control over the prototype they disclose anyway. It can only work for proxies if the magic accessor (whether implicit or explicit) transparently forwards the assignment to proxy targets. No trap would be involved, just like there is no trap for getting the prototype of a proxy.

Proxies could presumably trap the initial [Put] call and from that point do whatever they want. To change the this objects prototype (without reentering the trap) they would presumably use reflect.set which does a non-trapping invocation of the default [[Put]] internal method.

I suppose the real question is: do we want proxies to simulate this in full gory glory? That would be blessing this (mis)feature even more.

how would we prevent it?

# Brendan Eich (14 years ago)

this may repeat parts of replies from others, if so please bear with me:

I think proto should be a bit magical, and in particular should not be proxy-able. Annex B is becoming "Normative Optional", meaning you are not required to implement its contents to conform to ECMA-262, but if you do support the specified APIs, then Annex B's spec is normative.

For proto we do not need to over-specify (as we generally do elsewhere, for interoperation). The appearance of a data property matches some implementations today and it could be spec'ed as Allen wrote up. This adds some risk to the main spec and proxies, but if we do not want proto to be proxy-able then it might be the right approach.

The temptation to polish proto to fit the spec and language is high but my gut says we should resist it. We may help enshrine it in ways we do not want (proxies). We may err in inventing a new de-jure spec that does not match existing implementations.

# Domenic Denicola (14 years ago)

I am generally with Brendan that specifying proto is not very necessary. But, one thing I would like enshrined in the spec is that "__proto__" in Object.create(null) === false.

# Brendan Eich (14 years ago)

Domenic Denicola wrote:

I am generally with Brendan that specifying proto is not very necessary.

"over-specifying", right? I am in favor of specifying proto minimally in Annex B.

But, one thing I would like enshrined in the spec is that "__proto__" in Object.create(null) === false.

For sure!

# Allen Wirfs-Brock (14 years ago)

On Feb 10, 2012, at 11:24 AM, Brendan Eich wrote:

Hi Tom, this may repeat parts of replies from others, if so please bear with me:

I think proto should be a bit magical, and in particular should not be proxy-able. Annex B is becoming "Normative Optional", meaning you are not required to implement its contents to conform to ECMA-262, but if you do support the specified APIs, then Annex B's spec is normative.

A different approach is to tie the semantics to language syntax instead of making it part of the "virtual machine" that is defined by the internal methods. For example, I could specify the [[Prototype]] mutating behavior of an assignment to the proto property as an extension to the evaluation semantics of the simple assignment operator (11.13.1). An advantage to doing it this way is that it can only be trigger by using that specific syntactic form. In particular, other syntactic constructs that in do [[Put]]'s and all the [[Put]]'s in built-in and host functions would not trigger it.

The approach I took in my proposal for the handling of proto in object literals is another example of this syntactic approach.

This sort of approach really focuses limiting the "damage" (or magic, if you prefer) to the actual source code use cases that we feel must be supported for interoperability and limits the spread of the contagion .

For proto we do not need to over-specify (as we generally do elsewhere, for interoperation). The appearance of a data property matches some implementations today and it could be spec'ed as Allen wrote up. This adds some risk to the main spec and proxies, but if we do not want proto to be proxy-able then it might be the right approach.

The temptation to polish proto to fit the spec and language is high but my gut says we should resist it. We may help enshrine it in ways we do not want (proxies). We may err in inventing a new de-jure spec that does not match existing implementations.

But I think we do want to have a way to disable this feature, even though that capability does not exists (at least consistently) in existing implementations.

The existence of a Object.prototype.proto property (perhaps a special one) seems like a plausible way to do this this. On the other hand, there is also nothing preventing us from simply specify a new global function proto__disable (or any other triggering mechanism we might agree on)that could be called to disable the proto feature.

We can under specify Object.prototype.proto but doing so clearly opens up the at least the possibility of hypothetical interpretability issues of the sort we have historically tried to eliminate from the specificatiion. The fact, that nobody has brought forward any examples of such interoperability problems among the current somewhat divergent implementations of proto shows th't the current differences aren't an issue so we could probably get away with it. But it does seem like a slippery slope. If we decide it is ok to under-specify here what about the next time there is a difference of option or preference about the edge cases manifested by some new functionality (say, just as an example, closure capture in the initializer expressions of for(let;;) loops). Are we going to be more inclined to just under-specify? I hope not.

# Brendan Eich (14 years ago)

Allen Wirfs-Brock wrote:

On Feb 10, 2012, at 11:24 AM, Brendan Eich wrote:

Hi Tom, this may repeat parts of replies from others, if so please bear with me:

I think proto should be a bit magical, and in particular should not be proxy-able. Annex B is becoming "Normative Optional", meaning you are not required to implement its contents to conform to ECMA-262, but if you do support the specified APIs, then Annex B's spec is normative.

A different approach is to tie the semantics to language syntax instead of making it part of the "virtual machine" that is defined by the internal methods. For example, I could specify the [[Prototype]] mutating behavior of an assignment to the proto property as an extension to the evaluation semantics of the simple assignment operator (11.13.1). An advantage to doing it this way is that it can only be trigger by using that specific syntactic form. In particular, other syntactic constructs that in do [[Put]]'s and all the [[Put]]'s in built-in and host functions would not trigger it.

Some engines do use syntactic specialization, in particular I recall Rhino doing that. But do web-facing engines that support proto do that? What do they do with o['proto'+''] and the like? Anyone know?

The approach I took in my proposal for the handling of proto in object literals is another example of this syntactic approach.

That case needs special handling, and the syntax can be specialized there without loss of generality.

The existence of a Object.prototype.proto property (perhaps a special one) seems like a plausible way to do this this. On the other hand, there is also nothing preventing us from simply specify a new global function proto__disable (or any other triggering mechanism we might agree on)that could be called to disable the proto feature.

We shouldn't go too far afield from today's code. True, SpiderMonkey has O.p.proto non-configurable, but we can and (I think) will change that so it can be deleted. That's the shortest path to a disabling API, no need for mumble APIs.

We can under specify Object.prototype.proto but doing so clearly opens up the at least the possibility of hypothetical interpretability issues of the sort we have historically tried to eliminate from the specificatiion. The fact, that nobody has brought forward any examples of such interoperability problems among the current somewhat divergent implementations of proto shows th't the current differences aren't an issue so we could probably get away with it. But it does seem like a slippery slope. If we decide it is ok to under-specify here what about the next time there is a difference of option or preference about the edge cases manifested by some new functionality (say, just as an example, closure capture in the initializer expressions of for(let;;) loops). Are we going to be more inclined to just under-specify? I hope not.

Not for normative-mandatory stuff. For normative-optional, maybe. Consider that engines still feel the need to support foo.arguments. We've never spec'ed that even informatively.

# Oliver Hunt (14 years ago)

On Feb 10, 2012, at 2:29 PM, Brendan Eich wrote:

Allen Wirfs-Brock wrote:

On Feb 10, 2012, at 11:24 AM, Brendan Eich wrote:

Hi Tom, this may repeat parts of replies from others, if so please bear with me:

I think proto should be a bit magical, and in particular should not be proxy-able. Annex B is becoming "Normative Optional", meaning you are not required to implement its contents to conform to ECMA-262, but if you do support the specified APIs, then Annex B's spec is normative.

A different approach is to tie the semantics to language syntax instead of making it part of the "virtual machine" that is defined by the internal methods. For example, I could specify the [[Prototype]] mutating behavior of an assignment to the proto property as an extension to the evaluation semantics of the simple assignment operator (11.13.1). An advantage to doing it this way is that it can only be trigger by using that specific syntactic form. In particular, other syntactic constructs that in do [[Put]]'s and all the [[Put]]'s in built-in and host functions would not trigger it.

Some engines do use syntactic specialization, in particular I recall Rhino doing that. But do web-facing engines that support proto do that? What do they do with o['proto'+''] and the like? Anyone know?

The only rules we have in JSC wrt syntactic identification of proto are to prevent people from naming functions proto :D

The approach I took in my proposal for the handling of proto in object literals is another example of this syntactic approach.

That case needs special handling, and the syntax can be specialized there without loss of generality.

Indeed, if we switched to any value on the Object prototype for proto we'd need to special case it in JSC (presumably spider monkey already does) actually JSC already specialises, purely to allow proto to work in literals :D

# Allen Wirfs-Brock (14 years ago)

On Feb 10, 2012, at 2:29 PM, Brendan Eich wrote:

Some engines do use syntactic specialization, in particular I recall Rhino doing that. But do web-facing engines that support proto do that? What do they do with o['proto'+''] and the like? Anyone know?

I worried about this a bit when I first thought about this approach. However, it really doesn't matter if the behavior is tied to the semantics of the basic assignment operator. That operator gets a Reference as its RHS value so it doesn't matter if you say obj.proto or obj[proto] or obj["pro"+"to"].

The existence of a Object.prototype.proto property (perhaps a special one) seems like a plausible way to do this this. On the other hand, there is also nothing preventing us from simply specify a new global function proto__disable (or any other triggering mechanism we might agree on)that could be called to disable the proto feature.

We shouldn't go too far afield from today's code. True, SpiderMonkey has O.p.proto non-configurable, but we can and (I think) will change that so it can be deleted. That's the shortest path to a disabling API, no need for mumble APIs.

The main reason I mention the turn-off via a global function alternative, is that it in combination with a syntax linked specification eliminates the need to worry about whether O.p.proto is an accessor or data property or its attribute values. It simply is not a property under that approach.

# Brendan Eich (14 years ago)

Allen Wirfs-Brock wrote:

The main reason I mention the turn-off via a global function alternative, is that it in combination with a syntax linked specification eliminates the need to worry about whether O.p.proto is an accessor or data property or its attribute values. It simply is not a property under that approach.

Yeah, but delete does that more obviously.

The frame check or equivalent is still too coarse-grained for my future-proofing happiness. I could get over this, but combined with overspecifying as an accessor when I know of no implementations that reflect proto as an accessor, the sum total for me is still negative on accessor.

# Gavin Barraclough (14 years ago)

On Feb 10, 2012, at 11:55 AM, Brendan Eich wrote:

"over-specifying", right? I am in favor of specifying proto minimally in Annex B.

But, one thing I would like enshrined in the spec is that "__proto__" in Object.create(null) === false. For sure!

The idea of a minimal specification sounds really encouraging. It seems there are a few really key points that everyone appears to be in complete agreement on – that the proto property should be a member of the Object Prototype, that this should be the only mechanism available to change an object's prototype, and that it should be configurable.

On Feb 10, 2012, at 3:16 PM, Brendan Eich wrote:

I know of no implementations that reflect proto as an accessor,

WebKit is using an accessor in nightly builds.

# Brendan Eich (14 years ago)

Gavin Barraclough wrote:

On Feb 10, 2012, at 11:55 AM, Brendan Eich wrote:

"over-specifying", right? I am in favor of specifying proto minimally in Annex B.

But, one thing I would like enshrined in the spec is that "__proto__" in Object.create(null) === false. For sure!

The idea of a minimal specification sounds really encouraging. It seems there are a few really key points that everyone appears to be in complete agreement on – that the proto property should be a member of the Object Prototype, that this should be the only mechanism available to change an object's prototype, and that it should be configurable.

Yes.

BTW in taking our lumps (and dishing them out at fellow members) for CSS WG failure to codify de-facto style property standards, I've mentioned Ecma turning a blind eye toward proto. Great to finally get a normative/optional spec for it (whatever one thinks of the thing itself). proto is used by Zepto.js and other mobile frameworks.

On Feb 10, 2012, at 3:16 PM, Brendan Eich wrote:

I know of no implementations that reflect proto as an accessor,

WebKit is using an accessor in nightly builds.

Heh, I knew that was coming. I'll amend to say "of long standing" after "implementations" :-P.

I still have a gut feeling that someone is going to take advantage of the setter for bad purposes that will be harder to block than would be the case if proto reflected as a data property. But I can't prove this.

# Oliver Hunt (14 years ago)

On Feb 12, 2012, at 11:28 AM, Brendan Eich wrote:

Heh, I knew that was coming. I'll amend to say "of long standing" after "implementations" :-P.

I still have a gut feeling that someone is going to take advantage of the setter for bad purposes that will be harder to block than would be the case if proto reflected as a data property. But I can't prove this.

I'm not sure about this -- the JSC+V8 model for proto was a magic property on the object itself, not the prototype, so anything that could access an object could mutate its prototype. Pushing the property onto the prototype doesn't add any more restrictions over that (if you can access an object, by definition you can access its prototype). If you pull the setter function off of the prototype you can still only apply it to objects you could already access.

# Brendan Eich (14 years ago)

Oliver Hunt wrote:

On Feb 12, 2012, at 11:28 AM, Brendan Eich wrote:

Heh, I knew that was coming. I'll amend to say "of long standing" after "implementations" :-P.

I still have a gut feeling that someone is going to take advantage of the setter for bad purposes that will be harder to block than would be the case if proto reflected as a data property. But I can't prove this.

I'm not sure about this

Likewise, as noted -- I'm not sure but my gut is unhappy :-P.

-- the JSC+V8 model for proto was a magic property on the object itself, not the prototype, so anything that could access an object could mutate its prototype. Pushing the property onto the prototype doesn't add any more restrictions over that (if you can access an object, by definition you can access its prototype).

Yes, that's all clear.

If you pull the setter function off of the prototype you can still only apply it to objects you could already access.

The concern (no trolling here) is at least about attack surface. If there's no setter that can be extracted, there's no need for the "frame check" (however phrased). Adding that check adds more machinery to get wrong or have interact in unexpected ways with other moving parts.

# Axel Rauschmayer (14 years ago)

proto is used by Zepto.js and other mobile frameworks.

Is it mainly used to create array instances? Would it make sense to push for Array.create() as quickly as possible, as a shim-able alternative (using proto on some browsers, being native on others)?

# David Bruant (14 years ago)

Le 12/02/2012 23:47, Brendan Eich a écrit :

Oliver Hunt wrote:

On Feb 12, 2012, at 11:28 AM, Brendan Eich wrote:

Heh, I knew that was coming. I'll amend to say "of long standing" after "implementations" :-P.

I still have a gut feeling that someone is going to take advantage of the setter for bad purposes that will be harder to block than would be the case if proto reflected as a data property. But I can't prove this.

I'm not sure about this

Likewise, as noted -- I'm not sure but my gut is unhappy :-P

The case where you have to protect against someone who kept a reference to the setter is when you haven't deleted the property at the beginning (assuming you have a way to run first in the environment) Within one "vat", if you forgot, you're screwed, but you know it is easy to fix (in your code, not necessarily the consequence on the attacked code). An issue arise when other proto setters pop up without you necessarily knowing. And as far as I know, the only way it can happen is when there are several frames within the same vat. So the cross-frame check (or the stricter version based on Object.prototype) takes care of it.

But first thing, just delete Object.prototype.proto anytime you don't need it. Knowing this makes my guts feel far better than with the current situation where, in Firefox, for instance, it is not possible to get rid of Object.prototype.proto:


var o = {a:1}, o2 = {a:2};

var o3 = {b:3}; o3.proto = o; console.log(o3.a); // 1 delete Object.prototype.proto o3.proto = o2;

console.log(o3.a); // should be 1 if proto was deletable, but is currently 2 in Firefox Web Console

If you pull the setter function off of the prototype you can still only apply it to objects you could already access.

The concern (no trolling here) is at least about attack surface. If there's no setter that can be extracted, there's no need for the "frame check" (however phrased). Adding that check adds more machinery to get wrong or have interact in unexpected ways with other moving parts.

I'm not sure what you've described is directly a concern of attack surface. I think it's rather a concern of "potential bugs surface" (which can indirectly lead to security issues) and I agree that it's a valid concern. However, the version where the check is based on the Object.prototype identity sounds it could be written quite safely in a couple of lines of JS, no ?

# Brendan Eich (14 years ago)

David Bruant wrote:

Le 12/02/2012 23:47, Brendan Eich a écrit :

The concern (no trolling here) is at least about attack surface. If there's no setter that can be extracted, there's no need for the "frame check" (however phrased). Adding that check adds more machinery to get wrong or have interact in unexpected ways with other moving parts. I'm not sure what you've described is directly a concern of attack surface.

No, there is new attack surface (API in the language) compared to not reflecting proto as an accessor at all.

I think it's rather a concern of "potential bugs surface"

Yes, that goes with attack surface unless it's redundant API to no new internals. But the frame check requires new internal implementation work.

(which can indirectly lead to security issues) and I agree that it's a valid concern. However, the version where the check is based on the Object.prototype identity sounds it could be written quite safely in a couple of lines of JS, no ?

Let's stop making a trivial matter of something that isn't fully attacked yet. proto as pseudo-data property has been around for ~13 years. An accessor variant, days at most. My gut is still unhappy!

# Andreas Rossberg (14 years ago)

On 12 February 2012 23:47, Brendan Eich <brendan at mozilla.org> wrote:

The concern (no trolling here) is at least about attack surface. If there's no setter that can be extracted, there's no need for the "frame check" (however phrased). Adding that check adds more machinery to get wrong or have interact in unexpected ways with other moving parts.

One could also make the proto accessor special in that reflecting it does only return a poisoned pair of getter/setters. Doesn't seem more magic or hacky than pretending that it is a data property. :)

# Allen Wirfs-Brock (14 years ago)

Let's try to get this back to concrete issues that I can incorporate into a specification.

The current draft is at harmony:draft_proto_spec_rev2.pdf

Gavin and Oliver seem to really want to use an accessor for Object.prototype.proto

Brendan has expressed a willingness to accepting under specify some the Object.prototype.proto property in ways that we normally wouldn't for mandatory parts of the specification.

I could accommodate these two perspective by changing the first paragraph of the draft B.3.1.1 to read:

The proto property of the Object prototype property initially has the attributes {[[Enumerable]]: false, [[Configurable]]: true}. The state of other attributes and whether it is an accessor or data property is implementation defined.

This would allow implementations to use either a data property or a access property for Object.prototype.proto. However, the internal method extensions are still needed in order to define the semantics in a manner that allows either implementation approach to be used.

Finally, an alternative to extending [[Get]] and [[Put]] would be to extend the GetValue abstraction operation (8.7.1) and the Simple Assignment evaluation semantics (11.13.1).

[[DefineOwnProperty]] and [[Delete]] still need to be extended but, independent of any of the above, these two can probably be made over-riding implementations on Object.prototype rather than extending the default implementations used by all objects.

# Brendan Eich (14 years ago)

Andreas Rossberg wrote:

On 12 February 2012 23:47, Brendan Eich<brendan at mozilla.org> wrote:

The concern (no trolling here) is at least about attack surface. If there's no setter that can be extracted, there's no need for the "frame check" (however phrased). Adding that check adds more machinery to get wrong or have interact in unexpected ways with other moving parts.

One could also make the proto accessor special in that reflecting it does only return a poisoned pair of getter/setters.

That is strictly better than "innovating" by providing a setter that can be reflected upon and then called on other (same-"frame") objects.

Doesn't seem more magic or hacky than pretending that it is a data property. :)

Hate to argue about devils on pinheads but the always-throwing poisoned accessor patterns (first seen in ES5 strict) smell worse to me than a data property with magic behind it. We had lots of those in various DOMs since day 1 (Netscape 2). Perhaps I'm just used to the odor :-/.

# Gavin Barraclough (14 years ago)

On Feb 12, 2012, at 11:28 AM, Brendan Eich wrote:

Heh, I knew that was coming. I'll amend to say "of long standing" after "implementations" :-P.

:-D

I still have a gut feeling that someone is going to take advantage of the setter for bad purposes that will be harder to block than would be the case if proto reflected as a data property. But I can't prove this.

Understood. We needed to change our implementation to fix ES5 compatibility issues with our prior mechanism. Implementing this internally as a accessor is much cleaner for us, and I think we'd want to keep it implemented this way even if we were to add the magic necessary to allow us to make it masquerade as a data descriptor (I still firmly side with Mark's strawman as to how this should be presented to users, but I didn't intend our current implementation to preclude alternatives).

# Gavin Barraclough (14 years ago)

On Feb 13, 2012, at 9:55 AM, Allen Wirfs-Brock wrote:

Finally, an alternative to extending [[Get]] and [[Put]] would be to extend the GetValue abstraction operation (8.7.1) and the Simple Assignment evaluation semantics (11.13.1).

[[DefineOwnProperty]] and [[Delete]] still need to be extended but, independent of any of the above, these two can probably be made over-riding implementations on Object.prototype rather than extending the default implementations used by all objects.

Hi Allen,

I don't know if this is helpful, but Mark's strawman seemed to make this much simpler, perhaps it might make for a less intrusive specification to define that this should behave as if it is an accessor property following Mark's ProtoGetter/ProtoSetter descriptions, whilst leaving how the property is reflected ambiguous? I think this should amount to the same thing, just might be easier to encapsulate this way?

# Allen Wirfs-Brock (14 years ago)

On Feb 13, 2012, at 11:43 AM, Gavin Barraclough wrote:

On Feb 13, 2012, at 9:55 AM, Allen Wirfs-Brock wrote:

Finally, an alternative to extending [[Get]] and [[Put]] would be to extend the GetValue abstraction operation (8.7.1) and the Simple Assignment evaluation semantics (11.13.1).

[[DefineOwnProperty]] and [[Delete]] still need to be extended but, independent of any of the above, these two can probably be made over-riding implementations on Object.prototype rather than extending the default implementations used by all objects.

Hi Allen,

I don't know if this is helpful, but Mark's strawman seemed to make this much simpler, perhaps it might make for a less intrusive specification to define that this should behave as if it is an accessor property following Mark's ProtoGetter/ProtoSetter descriptions, whilst leaving how the property is reflected ambiguous? I think this should amount to the same thing, just might be easier to encapsulate this way?

I believe what that amounts to is specifying the property as (not "as if") an accessor property with ProtoGetter/ProtoSetter get/set functions and then specifying a [[GetOwnProperty]] over-ride for Object.prototype.proto that allows an implementation to choose between returning a data property descriptor and returning a accessor property descriptor with censored get/set functions.

There would still need to be a way to specify that special treatment of proto in object literals is disabled when Object.prototype.proto is modified or deleted. While this could be done with prose I think using [[Delete]] and [[DefineOwnProperty]] hooks (and the UnderscoreProtoEnabled variable) is a more precise why to specify what actions are required to actually disables proto.

In general, I prefer preciseness over conciseness in the specification.

Also, I think we need some more thought about how the approaches (specified as accessor vs. specified as [[Put]]/[[Get]] extensions) differ in the presence of proxies.

# Mark S. Miller (14 years ago)

On Mon, Feb 13, 2012 at 9:55 AM, Allen Wirfs-Brock <allen at wirfs-brock.com>wrote: [...]

This would allow implementations to use either a data property or a access property for Object.prototype.proto.

-1. I prefer any securable fully specified alternative discussed in this thread (including your prior draft) over leaving such broad observables unspecified.

It reminds me of a story:

I am old enough that I remember when programmers felt passionately about byte order. There were high endian machines and their advocates, and there were low endian machines and their advocates. (I was low endian myself back then.)

Decades later, I forgot all about these strong feelings until I heard someone (Bill Frantz?) observe:

Compared to the status quo, both sides now prefer that the other side

had won.

I certainly do.

# Geoffrey Sneddon (14 years ago)

On 13/02/12 17:55, Allen Wirfs-Brock wrote:

Let's try to get this back to concrete issues that I can incorporate into a specification.

The current draft is at harmony:draft_proto_spec_rev2.pdf

Gavin and Oliver seem to really want to use an accessor for Object.prototype.proto

On the whole this is my preference too, as it practically eliminates special-casing for the proto property, which on the whole I'm in favour of.

I've basically implemented something close to what is attributed to Dave Herman on the wiki in Carakan now, albeit without the context check, though I agree it's a good idea. I wonder if it's web-compatible to disallow cross-context prototype chains (both through proto and Object.create).

Brendan has expressed a willingness to accepting under specify some the Object.prototype.proto property in ways that we normally wouldn't for mandatory parts of the specification.

I could accommodate these two perspective by changing the first paragraph of the draft B.3.1.1 to read:

The proto property of the Object prototype property initially has the attributes {[[Enumerable]]: false, [[Configurable]]: true}. The state of other attributes and whether it is an accessor or data property is implementation defined.

This would allow implementations to use either a data property or a access property for Object.prototype.proto. However, the internal method extensions are still needed in order to define the semantics in a manner that allows either implementation approach to be used.

I'm with Mark on this: I'd much rather see there be (rough) consensus on this than divergent implementations.

The one thing I would prefer, however, would be that the setter is optional (i.e., it is permissible to have proto have just a getter or have both a getter and a setter, but not just a setter).

# David Bruant (14 years ago)

Le 26/02/2012 01:23, Geoffrey Sneddon a écrit :

On 13/02/12 17:55, Allen Wirfs-Brock wrote:

Let's try to get this back to concrete issues that I can incorporate into a specification.

The current draft is at harmony:draft_proto_spec_rev2.pdf

Gavin and Oliver seem to really want to use an accessor for Object.prototype.proto

On the whole this is my preference too, as it practically eliminates special-casing for the proto property, which on the whole I'm in favour of.

I've basically implemented something close to what is attributed to Dave Herman on the wiki in Carakan now, albeit without the context check, though I agree it's a good idea. I wonder if it's web-compatible to disallow cross-context prototype chains (both through proto and Object.create).

What is asked to be disallowed is only changing the prototype with proto in a cross-context manner. Creating cross-context chains with Object.create has not been discussed I think and should be fine...

....or not? Given an attacker from context A, a defender from context D (I'll use these letters to refer to the global object of each context). An attacker can create an object like

var maliciousProto = Object.create(D.Object.prototype); // Add whatever own properties to maliciousProto

someObjectInD.proto = maliciousProto

I was enthusiastic by Gavin Object.prototype ownership-based solution, but it seems that as long as an attacker has the possibility to create cross-context objects, an Object.prototype-based solution actually does not prevent anything.

The one thing I would prefer, however, would be that the setter is optional (i.e., it is permissible to have proto have just a getter or have both a getter and a setter, but not just a setter).

I think that it's unrealistic since the web does use the setter as well. If the setter was standardized as optional, all implementations would implement it anyway.

# Mark S. Miller (14 years ago)

On Sun, Feb 26, 2012 at 1:39 AM, David Bruant <bruant.d at gmail.com> wrote:

Le 26/02/2012 01:23, Geoffrey Sneddon a écrit :

On 13/02/12 17:55, Allen Wirfs-Brock wrote:

Let's try to get this back to concrete issues that I can incorporate into a specification.

The current draft is at

harmony:draft_proto_spec_rev2.pdf

Gavin and Oliver seem to really want to use an accessor for Object.prototype.proto

On the whole this is my preference too, as it practically eliminates special-casing for the proto property, which on the whole I'm in favour of.

I've basically implemented something close to what is attributed to Dave Herman on the wiki in Carakan now, albeit without the context check, though I agree it's a good idea. I wonder if it's web-compatible to disallow cross-context prototype chains (both through proto and Object.create). What is asked to be disallowed is only changing the prototype with proto in a cross-context manner. Creating cross-context chains with Object.create has not been discussed I think and should be fine...

....or not? Given an attacker from context A, a defender from context D (I'll use these letters to refer to the global object of each context). An attacker can create an object like

var maliciousProto = Object.create(D.Object.prototype); // Add whatever own properties to maliciousProto

someObjectInD.proto = maliciousProto

If D has already deleted F.Object.prototype.proto, then your attack fails at the above step.

# David Bruant (14 years ago)

Le 26/02/2012 17:10, Mark S. Miller a écrit :

On Sun, Feb 26, 2012 at 1:39 AM, David Bruant <bruant.d at gmail.com <mailto:bruant.d at gmail.com>> wrote:

Creating cross-context chains with Object.create has not been
discussed
I think and should be fine...

....or not?
Given an attacker from context A, a defender from context D (I'll use
these letters to refer to the global object of each context). An
attacker can create an object like
-----
var maliciousProto = Object.create(D.Object.prototype);
// Add whatever own properties to maliciousProto

someObjectInD.__proto__ = maliciousProto

If D has already deleted F.Object.prototype.proto, then your attack fails at the above step.

True. I guess it's the reason why you said that proto being an accessor or data property does not make that big of a difference from a security standpoint.

# Geoffrey Sneddon (14 years ago)

On 26/02/12 09:39, David Bruant wrote:

Le 26/02/2012 01:23, Geoffrey Sneddon a écrit :

I've basically implemented something close to what is attributed to Dave Herman on the wiki in Carakan now, albeit without the context check, though I agree it's a good idea. I wonder if it's web-compatible to disallow cross-context prototype chains (both through proto and Object.create). What is asked to be disallowed is only changing the prototype with proto in a cross-context manner. Creating cross-context chains with Object.create has not been discussed I think and should be fine...

....or not? Given an attacker from context A, a defender from context D (I'll use these letters to refer to the global object of each context). An attacker can create an object like

var maliciousProto = Object.create(D.Object.prototype); // Add whatever own properties to maliciousProto

someObjectInD.proto = maliciousProto

I was enthusiastic by Gavin Object.prototype ownership-based solution, but it seems that as long as an attacker has the possibility to create cross-context objects, an Object.prototype-based solution actually does not prevent anything.

I don't think there's much in the way of a security risk here (given that if you have access to D anyway you can execute arbitrary code within it). Even if proto has been deleted you can just create a new object "someObjectInD" with mailiciousProto through Object.create.

The only reason to prefer to avoid cross-context prototype chains is one of elegance: in my view it seems somewhat inelegant, though the more I think about it the less I can justify that position.

The one thing I would prefer, however, would be that the setter is optional (i.e., it is permissible to have proto have just a getter or have both a getter and a setter, but not just a setter). I think that it's unrealistic since the web does use the setter as well. If the setter was standardized as optional, all implementations would implement it anyway.

I was speaking to Jeff Walden a few or two back about this — both of us at least still live in hope of someday getting rid of the setter. As far as either of us are aware, there isn't much legacy for the setter, mostly concentrated within a few libraries, which hopefully we can evangelize it out of — and then re-evaluate where we are in a few years and see whether the legacy has decreased, and older versions of the libraries have gone. Being obliged per spec to implement the setter forever seems undesirable, if we can manage to get rid of the legacy.

# Mark S. Miller (14 years ago)

On Thu, Mar 1, 2012 at 9:54 AM, Geoffrey Sneddon <gsneddon at opera.com> wrote:

On 26/02/12 09:39, David Bruant wrote:

Le 26/02/2012 01:23, Geoffrey Sneddon a écrit :

I've basically implemented something close to what is attributed to

Dave Herman on the wiki in Carakan now, albeit without the context check, though I agree it's a good idea. I wonder if it's web-compatible to disallow cross-context prototype chains (both through proto and Object.create).

What is asked to be disallowed is only changing the prototype with proto in a cross-context manner. Creating cross-context chains with Object.create has not been discussed I think and should be fine...

....or not? Given an attacker from context A, a defender from context D (I'll use these letters to refer to the global object of each context). An attacker can create an object like

var maliciousProto = Object.create(D.Object.**prototype); // Add whatever own properties to maliciousProto

someObjectInD.proto = maliciousProto

I was enthusiastic by Gavin Object.prototype ownership-based solution, but it seems that as long as an attacker has the possibility to create cross-context objects, an Object.prototype-based solution actually does not prevent anything.

I don't think there's much in the way of a security risk here (given that if you have access to D anyway you can execute arbitrary code within it).

Hi Geoffrey, I agree with your conclusion -- the Object.prototype-based solution seems sound -- see my previous reply to David. But I completely disagree with your reasoning. Now that ES5 is deployed, you can lock down D so that you can execute untrusted code in it securely. In fact, this is the only form of execution in which modern browsers support confinement of untrusted code. HTML5 unique origin sandboxed iframes are much weaker as a security mechanism -- in this and many other ways.