endo icon indicating copy to clipboard operation
endo copied to clipboard

`with (scopeProxy) { foo() }` leaks scopeProxy if foo mentions `this`.

Open erights opened this issue 6 years ago • 7 comments

Typing valueOf() into the evaluator shim playground (demo/index.html) and hitting the Evaluate button causes the error

please report internal shim error: unexpected scope handler trap called: ownKeys

Unlike other surprising scopeProxy traps, this does not look like an engine bug. We see identical symptoms on Brave, FF, and Safari.

[edit by @kriskowal 2020-08-12:]

Actions needed (to be independently tracked, and this issue closed)

  • ~~Create a specification proposal that introduces a hiddenWith symbol that with would respect.~~
  • [ ] Document this known-limitation of SES-shim, ~~barring eventual engine support for a hiddenWith symbol.~~
  • [ ] Confirm that ~~absent hiddenWith,~~ revealing the ScopeProxy does not break containment.

erights avatar Oct 27 '19 01:10 erights

Due to https://github.com/google/caja/wiki/SES#this-binding-of-global-function-calls The weird trap isn't happening in evaluating the user code. Rather, the valueOf() causes the scopeProxy to leak as the completion value. The playground code then treats it as a more normal object, provoking the surprising trap.

The scopeProxy was never supposed to leak. The problem is only caused by with lookup of a function that mentions this, followed by a function-call-syntax invocation of that function.

At an unmodified normal JS prompt,

const obj = { foo() {'use strict'; return this;} };
with (obj) { foo() === obj; }  // true
with (obj) { (1,foo)() === undefined; }  // true

This leakage of obj on line 2 is according to the spec, and is an unrepairable deficiency emulating global scope with with. Had we noticed it in time, we likely could have fixed it in ES5 strict-mode. But even by https://github.com/google/caja/wiki/SES#this-binding-of-global-function-calls (2015) it was already too late. Attn @allenwb @jfparadis @caridy @warner @XmiliaH

What this means under the evaluator-shim and the realms-shim, and therefore under SES:

const e = new Evaluator();

function foo() { return this; }
e.evaluate('foo()', { foo });  // evaluates to the scopeProxy.

Amusingly, once Agoric/SES-beta#18 is fixed by Agoric/evaluator-shim#3 the following works

const e = new Evaluator();

function foo() { return this; }
e.evaluate('foo()', Object.freeze({ foo }));  // undefined

because foo becomes an optimized const variable.

If we cannot practically prevent the scopeProxy from leaking, we need to ensure that no vulnerability follows from leaking the scopeProxy. We could probably make the scopeProxy no more powerful than the safeGlobal plus the values of the endowments. That should be both possible and adequate.

erights avatar Oct 27 '19 03:10 erights

(grr...it's too easy to accidentally loose/close a github tab with an unsaved text entry field...trying again)

This should be easy (at least at the ECMA-262 spec. level) to fix. Object Environment Records already have a specification mechanism that controls whether or not they make their backing object available for inclusion in resolved References. This is controlled by the setting their withValue to true. With statements normally do that for all with objects. What we need to do is not set withValue to true when the with object is a ScopeProxy.

There are various ways this might be done in the spec, but I suggest doing all the work in with statement evaluation. Specifically we need to put a "not a ScopeProxy" guard on step 5 which currently unconditionally sets withValue.

What does the guard look like? We really don't want to build knowledge of a specific ScopeProxy definition into this level of ECMA-262. Instead, I suggest we define a new well-known symbol named @@hiddenWith. The guard would be: HasOwnProperty(obj, @@hiddenWith) is false. The definition of ScopeProxy (its proxy handler) would ensure that they always report that they have a @@hiddenWith own property. That's it!

Actually updating implementations to do this is probably not quite so simple, I assume that they don't have anything that exactly corresponds to an Object environment record with a withValue flag. But I suspect that adapting an implementation to conform to this updated specification would be a modest effort—and well worth it.

allenwb avatar Oct 27 '19 05:10 allenwb

I left out of my redo: this ECMA-262 specification change appears be backwards compatible with all existing ES code.

allenwb avatar Oct 27 '19 05:10 allenwb

This is a use of this, not a mention of this, no?

...
function foo() { return this; }
...

dckc avatar Jun 07 '21 16:06 dckc

Well, it is also a mention of this. But good point. I genuinely do not know what the least confusing short title would be. "Uses this" can be misunderstood in other ways (such as "uses the value that this evaluates to"). I'll just let these notes in this issue thread clarify, and leave the title as is. Thanks.

erights avatar Jun 07 '21 20:06 erights

Well, it is also a mention of this.

Ah. I see. Thanks.

dckc avatar Jun 07 '21 20:06 dckc

We've noticed that some Web APIs such as fetch are sensitive to the this / context. If it's null-ish or a real window object, it works fine, but fails with a TypeError if any other object: Failed to execute 'fetch' on 'Window': Illegal invocation (message on v8/Chrome) or 'fetch' called on an object that does not implement interface Window (message in SpiderMonkey/Gecko).

This fidelity bug of the shim causes code that would otherwise work to break if these functions are endowed to a compartment's global.

mhofman avatar Sep 22 '22 22:09 mhofman

How has multi-backflip affected this?

erights avatar Dec 24 '22 01:12 erights

It still leaks, but only the globalThis regular object.

Main problem left is for module lexical created by the shim, as detailed in #912.

Should we rename the title of this issue? It might be good to keep tracking an engine level change allowing to disable the current with context behavior.

mhofman avatar Dec 24 '22 02:12 mhofman

Should we rename the title of this issue?

Please do!

erights avatar Dec 24 '22 02:12 erights

Narrowed scope and posted for follow-up: https://github.com/endojs/endo/issues/1954

kriskowal avatar Jan 10 '24 06:01 kriskowal