Make sandbox around Function() in Javascript

后端 未结 3 1222
误落风尘
误落风尘 2020-12-31 13:49

Can I limit the access of a string-generated function (using the Function constructor) to the parent/global scopes?

For example: the following code, as it is, prints

相关标签:
3条回答
  • 2020-12-31 14:39

    I don't think so. You could name the globals you want to protect in the parameters so that they shadow them:

    window.a = 4;
    Function("a", "a=3;")()
    console.log(a === 4);
    

    But the function is going to have access to global no matter what you try... that's why it's called global.

    Depending on what you are trying to do, there are other work-arounds such as web workers... and as always, hidden iframe hacks.

    0 讨论(0)
  • 2020-12-31 14:39

    @Esailija's answer is right. Additionally, I would recommend limiting the number of global variables that you have to protect in the first place. Put anything that you would normally put in the global namespace in an APP scope that you control:

    var APP = (function() {
        return {
            a: 4
        };
    }());
    

    There's no way to completely limit access to the global scope, but at least this way you only need to protect one object: APP.

    0 讨论(0)
  • 2020-12-31 14:46

    Here is an additional idea which could be quite powerful together with Esailija's proposal (see the comments on his answer for the discussion).

    You could create dummy iframe and use its Function function. The function created with that will only have access to the scope of the iframe by default, though it could still break out of it. Fortunately it is easy to prevent that, by the way Esailija suggested.

    I could imagine the function to be like this:

    function sandboxed(code) {
        var frame = document.createElement('iframe');
        document.body.appendChild(frame);
    
        var F = frame.contentWindow.Function,
            args = Object.keys(frame.contentWindow).join();
    
        document.body.removeChild(frame);
    
        return F(args, code)();
    }
    

    DEMO

    Optionally you might want to prepend 'use strict'; to the code.


    This works at least in Chrome. Whether the function created this way has access to the iframe's global scope or the page's global scope can be easily tested with:

    (function() {
        var frame = document.createElement('iframe');
        document.body.appendChild(frame);
        var same = window === frame.contentWindow.Function('return window;')();
        alert(same ? ':(' : ':)');
        document.body.removeChild(frame);
    }());
    
    0 讨论(0)
提交回复
热议问题