Subclassing ES6 objects with ES5 syntax.

Domenic Denicola d at domenic.me
Sun Apr 26 04:56:12 UTC 2015


It's possible Reflect.construct has introduced a security hole that was not present before the recent instantiation reform. Hopefully Mark can comment more.






On Sat, Apr 25, 2015 at 9:52 PM -0700, "C. Scott Ananian" <ecmascript at cscott.net<mailto:ecmascript at cscott.net>> wrote:

On Sat, Apr 25, 2015 at 6:58 PM, Kevin Smith <zenparsing at gmail.com<mailto:zenparsing at gmail.com>> wrote:
I think I'd rather see `Promise.resolve` changed to use `this.constructor` instead of `this.[[PromiseConstructor]]`, like every other Promise-related method.  Can someone who feels strongly otherwise give me the use case for `[[PromiseConstructor]]` existing?

I shouldn't have written `this.constructor` here.  I think looking at the object's prototype would be preferable.

"Promise.resolve", executed on a constructor C, with argument x, should only return x if x was created by C.[[Construct]].  Otherwise it should create an instance of C which is resolved with x.

"was created by C.[[Construct]] with NewTarget equal to C" is roughly how it is written currently.  But I think "should only return x if x is an instanceof C" (or "if the prototype of C is exactly C.prototype") would be the most logical behavior, since:

If we used "x.constructor" to determine the actual constructor, then someone could just change the "constructor" property for x and fool someone who wrote "C.resolve(x)" and expected to get an instance of C back.
It would be an unreliable, unsound conversion function.

I don't think this argument holds water since:

x = Reflect.construct(Promise, x, C);

is another fine way to fool someone who wrote "C.resolve(x)" and expected to get an instance of C back.

What's more, I can then do:

Object.setPrototype(x, SomeArbitraryThing);

and still fool C.resolve, and now x behaves nothing like a Promise (much less a C).

So we've got an unreliable, unsound conversion function.  What is it good for?

If our conversion is inherently "unsound", we might as well have it preserve duck typing.  If it's currently quacking like a duck (that is, x.prototype = Duck.prototype), then let's just call it a duck and be done with it.   Adding complexity to try to "preserve soundness" isn't actually working.

Again: but maybe I'm wrong.  Can someone with a security-sensitive application explain how Promise.resolve is actually the right thing for them?
  --scott

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20150426/37ef8f42/attachment-0001.html>


More information about the es-discuss mailing list