-
Notifications
You must be signed in to change notification settings - Fork 205
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix(resolve): protect against reentrancy attack #401
Conversation
packages/eventual-send/src/index.js
Outdated
getPrototypeOf(p) === promiseProto && | ||
promiseResolve(p) === p && | ||
gopd(p, 'then') === undefined && | ||
(isSES || gopd(promiseProto, 'then').value === originalThen) // unnecessary under SES |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Outside of SES, if we're not checking isFrozen(promiseProto)
and we are checking gopd(promiseProto, 'then').value === originalThen
, we should also check that this data property is non-writable, non-configurable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I found that using harden()
anywhere in eventual-send
meant that we are taking a stand in hardening HandledPromises. Going all the way, I instead harden things that are returned by HandledPromise.resolve
which simplifies the test and makes it behave more consistently inside and outside SES. This helped ERTP pass all its unit tests again.
I hope I made an acceptable tradeoff.
If that's not acceptable, then we need a much more convincing story of what we should actually harden in eventual-send
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@erights PTAL.
Sorry, but I'm not qualified to review this. |
Object.setPrototypeOf(HandledPromise, Promise); My apologies! I saw the comment, and interpreted it as being about setting HandledPromise.prototype = promiseProto; which was never turned off. Regarding the line that I mistakenly asked you to change, I actually have no strong feeling one way or the other. I'm happy with what you changed it to, and with making the corresponding change to the spec. But I'd also be happy without it. Feel free to revert this portion of this PR before merging, or not, as you wish. Sorry for the confusion! |
After using agoric-labs/tape-xs#3 I discovered that the test suite under XS is hanging with the following output:
|
@dckc, the hanging test is at an awaited promise |
@dckc Aha! I'm narrowing down on the problem, and it looks like a legit portability bug in this PR. |
It's the override mistake. Under XS, I cannot override the That's actually a good thing. This prevents having to assimilate promises under XS. I've updated the tests accordingly. Will retry. |
The override mistake only protects against override by assignment. It doesn't prevent override by |
Oh, okay. I'll rewrite the test accordingly. |
The harden calls in eventual-send already need an SES-like environment for proper security. Make HandledPromise.resolve simpler and prevent proxy trickery.
8f3dc3b
to
3bfb6ce
Compare
Bingo! The workaround of the override mistake using Still, it was interesting to reveal Moddable-OpenSource/moddable#322 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
Closes #9
Note that the test for
isNormalPromiseThen
does not check that thePromise.prototype
is frozen as this is always true under SES and too strict outside of SES (tries assimilating all Promises). It also checks ifp
is frozen only when under SES, as it is too strict outside of SES (tries assimilating platform Promises).Please review carefully. There is no rush.