Safe, Closure-free, Serializable functions

Mark S. Miller erights at google.com
Wed Sep 25 17:32:27 PDT 2013


Hi François, your goals here have a tremendous overlap with SES. In what
ways is SES not satisfactory for these purposes?

The best short-but-accurate summary of SES, sufficient for this question,
is <http://research.google.com/pubs/pub40673.html> section 2.3.

SES does not remove eval and Function, but rather replaces them with
confining equivalents which should be better for your purposes. You can get
SES from either <``
https://code.google.com/p/google-caja/source/browse/trunk/src/com/google/caja/ses/>
or <https://code.google.com/p/es-lab/source/browse/trunk/src/ses/>.

The security of SES is analysed at <
http://theory.stanford.edu/~ataly/Papers/sp11.pdf>.


On Wed, Sep 25, 2013 at 4:29 PM, François REMY <
francois.remy.dev at outlook.com> wrote:

> Hi,
>
> TLDR ==> The web needs a way to express executable code that does not rely
> on its parent context, is guaranteed to be side-effect-free, and can be
> executed safely anywhere (even in a different thread/worker/window/device,
> or as callback for browser code being executed while the DOM is not ready
> to be accessed)
>
>
> It's been some time I've been working on this idea of a Closure-free,
> Serializable function. This kind of function would have no access to the
> parent closures they are defined in, and only limited (read-only) access to
> the enclosing environment (read-only Math, Object, Array, others...).
>
> To the difference of other functions, those objects would not be affected
> by the JavaScript running elsewhere on the page, so in this closure-free
> function, Array.prototype.slice is guaranteed to be the native slice
> function, not some kind of polyfill or replaced function.
>
> |    function sort(array) as serializable {
> |        Array.prototype.sort.call(array);
> |    }
>
> |    function sqrt(number) as serializable {
> |        return Math.sqrt(number);
> |    }
>
> |    function __BAD_CODE__() as serializable {
> |        return new XMLHttpRequest(); // xhr not defined in ES6
> |    }
>
> Trying to export a global variable or modify any of the host
> environment-defined objects would fail.
>
> |    function __BAD_CODE__(number) as serializable {
> |        globalNumber = number; // cannot write into the global object
> |    }
>
> |    function __BAD_CODE__() as serializable {
> |        Object.prototype.doSomething=function() {}; // cannot write into
> the native objects
> |    }
>
> It's also important to note that any Object or Array created inside this
> context will be passed to the calling context by deep-cloning (or by
> replacing the "safe" Math object by the host Math object of the calling
> code in the case of environmental objects). Objects that can't be cloned
> (non-serializable functions, for example) are just transformed into null.
> We could also maybe use the idea of a proxy though deep-cloning seems safer.
>
> This makes sure it's impossible to leak the "safe" objects to the calling
> context in any way (ie: the calling code can leak anything to the called
> code, but not the reverse).
>
> |    var RealSin = Math.sin;
> |    Math.sin=function() {};
> |
> |    function giveMeMath() as serializable {
> |        return [Math, Math.sin];
> |    }
> |
> |    var [m,s] = giveMeMath();
> |    // s === RealSin
> |    // m === Math
> |    // m.sin !== RealSin
> |
> |    // note that another possibility here
> |    // would be to have giveMeMath return [null,null]
> |    // (ie: consider host objects unserializable)
>
> To be honest, those functions are not really meant to expose new objects:
> even if they need some internally, they should just keep them internally
> and avoid distributing them. The deep-cloning algorithm is just there for
> the cases where you want to return multiple values at the end of a
> function, or when you need an options object.
>
> Still, the fact they run in a "safe" environment makes them a good
> candidate for further optimization and inlining, so we may end up seeing
> codes written as serializable to benefit from performance boost and safety
> from external attacks.
>
> |    function Point(x,y) as serializable {
> |        x = +x;
> |        y = +y;
> |        return {
> |            x:x,
> |            y:y,
> |            r: Math.sqrt(x*x+y*y),
> |            t: Math.atan(x,y)
> |        };
> |    }
>
> The arguments, however, could be any object, and those act totally
> normally. If an object is given as argument to the function that is an
> Object, the function can access the "real" Object.prototype by using
> Object.getPrototypeOf(...).
>
> |    window.newXHR = function newXHR(window) as serializable {
> |        return new this.XMLHttpRequest();
> |    }
> |
> |    var xhr = window.newXHR();
>
> However, it's also possible for the calling code not to give such
> information by passing only primitive values like string and numbers. I
> believe this is the most likely usage of this kind of function, at least
> from the web platform point of view.
>
>
>
> The good thing about those functions, is that they can safely be sent over
> the wires to another thread, or to another web page, because they do not
> possibly rely on any state or context.
>
> Formalizing those functions is also an important step towards enabling JS
> code to run safely deeper into the browser stack, by avoiding any possible
> use of objects that are not supposed to be interacted with at a given time
> (the calling code can control exactly what the called function has access
> to).
>
> A possible use case would be to defined arbitrary timing function for
> animations:
>
> |    function x2(x) as serializable { return x*x; }
> |
> |    // this is safe because SomeWebAnim knows he will call the function
>  only with numbers, so the code cannot access the DOM while it's still
> being computed, or because the DOM actually lives in another thread than
>  the animation code.
> |    SomeWebAnim.timingFunction = x2;
>
>
>
> Is there some interest from anyone else in formalizing this for a future
> version of EcmaScript? Or any comment?
> Francois
>
>
>
> PS: for the purposes of safety, we may want to disallow "eval" and
> "Function" inside this environment to make sure the code can be compiled
> ahead of time in all cases, and not force the usage of an interpreter. this
> could also be let to the choice of the author but be exposed as a slightly
> different concept (ie: compilable + serializable vs serializable only).
> _______________________________________________
> es-discuss mailing list
> es-discuss at mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
>



-- 
    Cheers,
    --MarkM
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20130925/0bcfa52c/attachment.html>


More information about the es-discuss mailing list