C. Scott Ananian (2015-04-29T18:08:35.000Z)
d at domenic.me (2015-05-11T16:44:24.665Z)
On Wed, Apr 29, 2015 at 1:37 PM, Mark S. Miller <erights at google.com> wrote: > Isn't this still vulnerable to the Promise.resolve attack? IIUC, this > attack enables the attacker to cause this.constructor to lie, so how would > checking it help? > Because I only allow `DefensivePromise.resolve` to check `this.constructor` (via the call to super.resolve) if I know that `this.constructor` is not lying (because I froze `this.constructor` before adding it to `goodPromises`). All other promises get wrapped in a new `DefensivePromise`, which should enforce the desired "not on this turn" invariant. In this particular example, I'm not exporting DefensivePromise, just using it internally to sanitize "anything provided by a potential attacker" (while preserving efficiency if the attacker is in good faith giving my promises back to me). If you want to export `DefensivePromise` and allow malicious code to subclass it, then you should perform some additional checks after freezing and before adding to `goodPromises`, perhaps something like: ``` constructor(x) { super(x); Object.freeze(this); if (this.constructor==DefensivePromise && this.then === DefensivePromise.prototype.then && /*) { goodPromises.add(this); } } ``` You probably need to make the test a little bit more careful, in case `then` is a malicious getter or something like that. But my point is that you can do all this in userland, you don't need to expose its complexity or bake any of it into the Promise spec.