TOCTTOU issue in Proxy invariant checks
Tom Van Cutsem
tomvc.be at gmail.com
Mon Jul 21 23:27:02 PDT 2014
While reviewing some changes to the Proxy spec in the latest revision, it
occurred to me there is a potential time-of-check-to-time-of-use (TOCTTOU)
issue in the Proxy invariant checks.
Concretely, take revision 26, section 9.5.12 [[OwnPropertyKeys]]:
- step 11 checks whether the target object is extensible
- this result then gets used in step 21 and 28 (if the target was
non-extensible, more invariant checks are made)
- in between steps 11 and 21/28, control is transferred to internal methods
of the target, which may itself be a Proxy and so trigger arbitrary user
code to run.
- hence, the extensibility state checked in step 11 might have changed
before being used in steps 21/28
I think the issue is benign, because extensibility can only ever change
from 'true' to 'false' but not vice versa. This means we can end up in the
- assume a proxy and its target are extensible when [[OwnPropertyKeys]] is
- step 11 checks the extensibility state and stores 'true'
- assume user code runs between steps 11 and 21 that calls
Object.preventExtensions on the target, so the extensibility state is now
- Then, in step 21, even though the target is now non-extensible, the
algorithm terminates early and doesn't perform the invariant checks for
I think this is benign because the caller of the internal method, at the
time it made the call, had no reason to assume strong invariants on the
Basically, the way to think of this is that invariant checks are made based
upon the state of the target object when the internal method is first
invoked. While that internal method call is suspended, the target's state
may change, but invariant checks may still be based on the target's state
While I'm fairly confident the issue is benign, the reasoning is subtle and
could use more braincells to check if I missed anything.
This issue may appear for other Proxy internal methods, I haven't yet
checked. But generally I think they will also be benign for the same
reasons. An attacker can only modify the target to have stronger, not
weaker, invariants. Suspended calls that only assume weak invariants cannot
get confused if eventually more invariant checks are made.
-------------- next part --------------
An HTML attachment was scrubbed...
More information about the es-discuss