Is It Possible to Sandbox JavaScript Running In the Browser?

前端 未结 15 814
北海茫月
北海茫月 2020-11-22 13:58

I\'m wondering if it\'s possible to sandbox JavaScript running in the browser to prevent access to features that are normally available to JavaScript code running in an HTML

15条回答
  •  野性不改
    2020-11-22 14:29

    An improved version of @RyanOHara's web workers sandbox code, in a single file (no extra eval.js file is necessary).

    function safeEval(untrustedCode)
        {
        return new Promise(function (resolve, reject)
        {
    
        var blobURL = URL.createObjectURL(new Blob([
            "(",
            function ()
                {
                var _postMessage = postMessage;
                var _addEventListener = addEventListener;
    
                (function (obj)
                    {
                    "use strict";
    
                    var current = obj;
                    var keepProperties = [
                        // required
                        'Object', 'Function', 'Infinity', 'NaN', 'undefined', 'caches', 'TEMPORARY', 'PERSISTENT', 
                        // optional, but trivial to get back
                        'Array', 'Boolean', 'Number', 'String', 'Symbol',
                        // optional
                        'Map', 'Math', 'Set',
                    ];
    
                    do {
                        Object.getOwnPropertyNames(current).forEach(function (name) {
                            if (keepProperties.indexOf(name) === -1) {
                                delete current[name];
                            }
                        });
    
                        current = Object.getPrototypeOf(current);
                    }
                    while (current !== Object.prototype);
                    })(this);
    
                _addEventListener("message", function (e)
                {
                var f = new Function("", "return (" + e.data + "\n);");
                _postMessage(f());
                });
                }.toString(),
            ")()"], {type: "application/javascript"}));
    
        var worker = new Worker(blobURL);
    
        URL.revokeObjectURL(blobURL);
    
        worker.onmessage = function (evt)
            {
            worker.terminate();
            resolve(evt.data);
            };
    
        worker.onerror = function (evt)
            {
            reject(new Error(evt.message));
            };
    
        worker.postMessage(untrustedCode);
    
        setTimeout(function () {
            worker.terminate();
            reject(new Error('The worker timed out.'));
            }, 1000);
        });
        }
    

    Test it:

    https://jsfiddle.net/kp0cq6yw/

    var promise = safeEval("1+2+3");
    
    promise.then(function (result) {
          alert(result);
          });
    

    It should output 6 (tested in Chrome and Firefox).

提交回复
热议问题