How to ensure that your script runs first in a webpage

John J Barton johnjbarton at johnjbarton.com
Fri Feb 3 16:14:24 PST 2012


On Fri, Feb 3, 2012 at 3:14 PM, David Bruant <bruant.d at gmail.com> wrote:
> Le 03/02/2012 23:26, John J Barton a écrit :
>> On Fri, Feb 3, 2012 at 1:08 PM, David Bruant <bruant.d at gmail.com> wrote:
>>> Le 03/02/2012 17:54, John J Barton a écrit :
>>>> iframes seem to be effective for the cases David outlined.
>>> I can come up with more use cases ;-) Regardless of use cases iframes
>>> will always have an overhead against just loading some code with
>>> attenuated authority.
>> To support the attenuation of authority you have to create a container
>> (authority boundary) and you have to attenuate the API you give the
>> loaded code.  These activities are not free.
> I've been looking at Caja's code recently [1] and noticed that they take
> (untrusted) code and eval it. Of course, doing a dummy eval would be
> harmful because eval evaluates with the lexical environment of the
> calling context. Instead, they've found a way to wrap the eval call and
> make that when the eval code accesses something, they get to decide what
> this value is. In a way, they provide the lexical environment of their
> choice.

And I'm guessing, but the objects in that environment need to be
special in two ways: the need to have limited API and they need the
restrictions like freeze(). This would true of all their properties as
well, including Object, Function etc.

The result (which is not unreasonable) is that the API objects have to
be low level things, not say dojo widgets or so. Because otherwise the
restrictions propagate through out the higher level code.

>
> A second argument to eval to provide a lexical environment could make
> things easier. Just to be clear, I am not suggesting a second argument
> like it was before [2]. The object properties would be the lexical
> environment of the eval code (and not the lexical environment of the
> function if what is provided is a function as second argument). It seems
> to me that such a solution would enable fine granularity attenuated
> authority at a very small cost:
> ------
> // codeInString:
> localStorage.set('a', 1);
> var a = localStorage.get('a');
> localStorage.set('b', 2);
>
> // ...
> var codeInString = // code above, but as a string
> var chosenKey;
> var oneSlotLocalStorage = {
>  get: function(key){
>     if(typeof chosenKey === 'string')
>         return localStorage.get(chosenKey, val);
>  }
>  set: function(key, val){
>    if(!chosenKey || chosenKey === key){
>        chosenKey = key;
>        localStorage.set(chosenKey, val);
>    }
>    else{
>        throw new Error('You're not allowed to use more than one key!')
>    }
>  }
> }
>
> eval(codeInString, {localStorage:oneSlotLocalStorage});
> // 'a' is chosen as the key and an error is thrown when trying to set 'b'.
> -----
> Of course, it's a dummy example (and the second eval argument doesn't
> exist), but it seems that this kind of attenuation will be far cheaper
> (especially when direct proxies will be deployed) than iframes which
> always recreate an entire environment (ECMAScript built-ins, DOM
> built-ins, a document instance, etc.)

Well I have a soft spot for eval(), but your comparison seems bizarre
to me. The codeInString would not have access to ECMAScript built-ins,
DOM built-ins, a document instance, etc. So sure the result will have
better performance, the only problem is it also can't do anything
useful.

>
>
>
>> For the container, the important question (which I do not know the
>> answer to): can the container be isolated from the rest of the Web app
>> running in the window? Is there any impact on the rest of the
>> application from the choice to allow untrusted code to be loaded into
>> it?
> If the second argument of eval is what you call a container, then yes,
> you can fully isolate this code. The only threat remaning threats
> (besides bugs in your isolation code) is DoS (if the scripts decides to
> allocate infinite memory or to get stuck in an infinite loop).
>
>
>> To ask the same question in a more personal way: I've read code with
>> PropertyDescriptor/freeze() etc. Will I have to write that kind of
>> code?
> Considering the idea of the eval with a second argument from above, the
> answer is: it's up to you. If you want to freeze your objects, do it. If
> you feel like passing attenuated APIs as I showed above is enough to
> enforce the security you need, then, don't freeze your objects.
>
>
>>> For instance, if we want to create a game where participants submit some
>>> code to compete with each other. When loading the participants code,
>>> iframes can have a performance issue and asynchronous communication as
>>> done in the browser (with HTML5 cloning algorithm as the "richest form
>>> of sharing") may be very limitating.
>> Both technologies require the attenuated API. Since this API is the
>> security hole, it will require a great deal of attention. I think in
>> practical cases this effort will dwarf other issues.
> I'm not sure I understand. What do you call "the attenuated API".
> Especially for iframes, there is currently no API besides
> postMessage/onmessage event in the different-origin case.

You might take a look at q-comm. A little bit of JS wrapper code and
you have RPC calls. The only real difference is that the these calls
will be async, but that is probably what you want for untrusted code
anyway.

>
>>> However, being able to load the
>>> code in the same frame ("vat" as said in the concurrency strawman) would
>>> certainly yield better performance.
>> I thought this way as well only a few months ago. But the Chrome
>> multi-process architecture convinced me to reconsider. Integration
>> calls, the kind of API a security barrier can support, are just not
>> performance sensitive by design.
> It's an overhead anyway. Maybe constant, maybe small, but that's an
> overhead.

Sure, but your eval/lexical environment is overhead also.

>
>> And JSON messaging performs very well.
> It requires a copy. Maybe it's not big, but it's an overhead you can
> avoid as well.
>
> What I'm advocating here is the same security properties without the
> overheads. Maybe these overheads are small, but they exist by design.
>
>>> The only remaining threat would be DoS (both in memory and CPU time), an
>>> alternative allowing performance, rich interaction and preventing by
>>> design DoS is what is presented on the concurrency strawman. But we're
>>> not there and iframes are far from providing the same level of control.
>> Will the security solution prevent the untrusted code from
>> manipulating the DOM tree outside of a specific element?
> Considering the 2-argument eval example from above, you could define a
> 'document' property is the second argument and this document (what the
> eval code gets when it asks for the "document" variable) could be an
> emulation of an HTMLDocument, but forward all (relevant) calls
> (appendChild...) to a given element you've chosen.
>
> It seems it could be easily implemented.

I'd guess not, but overall I think the restricted eval or similar
system sounds interesting to explore.

jjb


More information about the es-discuss mailing list