Mark S. Miller (2015-04-29T17:00:45.000Z)
I have not responded on list yet because I haven't yet been able to find
the time to absorb this thread. But since Allen mentioned it, what I wrote
was:


The invariant I am interested in:


In a realm where we (the trusted defender who runs first) make Promise
defensive as follows

* Freeze everything primordial, as SES does

* Make a DefensivePromise subclass of Promise that differs minimally,
hopefully only by ensuring that its instances are frozen.

* "Promise = DefensivePromise;" do "Promise" below refers to
DefensivePromise

* Freezing whitelisted global properties, as SES currently does for ES5
globals, but for ES6 including "Promise"


then it must be the case that

    Promise.resolve(anything).then(anycallback)

for an anything provided by a potential attacker, when executed in the
middle of a turn does not call callback during that turn. If it calls
anycallback at all, it calls it back *as* a later turn, i.e., in a later
turn starting from an empty stack.








On Wed, Apr 29, 2015 at 9:49 AM, Allen Wirfs-Brock <allen at wirfs-brock.com>
wrote:

>
> On Apr 29, 2015, at 8:44 AM, C. Scott Ananian wrote:
>
> On Wed, Apr 29, 2015 at 1:06 AM, Brendan Eich <brendan at mozilla.org> wrote:
>
>> Kevin Smith wrote:
>>
>>> So what would the ideal Promise.resolve semantics do?  I'm not sure,
>>> maybe use SpeciesConstructor instead of [[PromiseConstructor]]?
>>>
>>
>> This removes the wart in my view, has no less integrity. C. Scott?
>
>
> Making this concrete, here would be the new text for 25.4.4.5
> Promise.resolve(x):
>
>> The resolve function returns either a new promise resolved with the
>> passed argument, or the argument itself if the argument is a promise
>> produced by this constructor.
>> 1. Let C be the this value.
>> 2. If IsPromise(x) is true,
>>     a. Let constructor be the value of SpeciesConstructor(x, %Promise%)
>
>     b. If SameValue(constructor, C) is true, return x.
>> 3. If Type(C) is not Object, throw a TypeError exception.
>> 4. Let S be Get(C, @@species).
>> 5. ReturnIfAbrupt(S).
>> 6. If S is neither undefined nor null, let C be S.
>> 7. Let promiseCapability be NewPromiseCapability(C)
>
> [...remainer elided...]
>
>
> Step 2a is the only change.  (It was previously "Let constructor be the
> value of x's [[PromiseConstructor]] internal slot.")
>
>
> But SpeciesConstructor (or any access to x's @@species) goes through
> `x.constructor` and my recollection is that the motivation for adding
> [[PromiseConstructor]] was that 'constructor'  was not sufficiently tamper
> proof.  From that perspective, it seems that SpeciesConstructor is actually
> worse than just accessing `x.constructor`.
>
> Also, in a private message Mark Miller mentioned that the primarily
>  security invariant he's concerned about really relates to the behavior of
> the `then` method of the object returned by `Promise.resolve(x)`.  Neither
> testing `construct` or SpeciesConstructor really tells you anything about
> `then`.   It seems that the root problem here is trying to apply nominal
> type based reasoning to JS.
>
> Allen
>
>


-- 
    Cheers,
    --MarkM
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20150429/28d52da4/attachment-0001.html>
d at domenic.me (2015-05-11T16:43:22.913Z)
I have not responded on list yet because I haven't yet been able to find
the time to absorb this thread. But since Allen mentioned it, what I wrote
was:


The invariant I am interested in:


In a realm where we (the trusted defender who runs first) make Promise
defensive as follows

* Freeze everything primordial, as SES does

* Make a DefensivePromise subclass of Promise that differs minimally,
hopefully only by ensuring that its instances are frozen.

* "Promise = DefensivePromise;" do "Promise" below refers to
DefensivePromise

* Freezing whitelisted global properties, as SES currently does for ES5
globals, but for ES6 including "Promise"


then it must be the case that

    Promise.resolve(anything).then(anycallback)

for an anything provided by a potential attacker, when executed in the
middle of a turn does not call callback during that turn. If it calls
anycallback at all, it calls it back *as* a later turn, i.e., in a later
turn starting from an empty stack.