Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 8008379
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 4, 20262026-06-04T18:07:14+00:00 2026-06-04T18:07:14+00:00

In a quest to have an interface capable of running arbitrary javascript code inside

  • 0

In a quest to have an interface capable of running arbitrary javascript code inside the browser, without having a security hole the size of a typical yo-mama joke, Esailija proposed using Web Workers. They run in a semi-sandboxed environment (no DOM access and already inside the browser) and can be killed so the user can’t put them in an infinite loop.

Here’s the example he brought up: http://tuohiniemi.fi/~runeli/petka/workertest.html (open your console)

jsfiddle (Google chrome only)

Now, this seems like a good solution; however, is it a complete (or approaching complete) one? Is there anything obvious missing?

The entire thing (as it’s hooked up to a bot) can be found on github: worker, evaluator

main:

workercode = "worker.js";

function makeWorkerExecuteSomeCode( code, callback ) {
    var timeout;

    code = code + "";
    var worker = new Worker( workercode );

    worker.addEventListener( "message", function(event) {
        clearTimeout(timeout);
        callback( event.data );
    });

    worker.postMessage({
        code: code
    });

    timeout = window.setTimeout( function() {
        callback( "Maximum execution time exceeded" );
        worker.terminate();
    }, 1000 );
}

makeWorkerExecuteSomeCode( '5 + 5', function(answer){
    console.log( answer );
});

makeWorkerExecuteSomeCode( 'while(true);', function(answer){
    console.log( answer );
});

var kertoma = 'function kertoma(n){return n === 1 ? 1 : n * kertoma(n-1)}; kertoma(15);';

makeWorkerExecuteSomeCode( kertoma, function(answer){
    console.log( answer );
});

worker:

var global = this;

/* Could possibly create some helper functions here so they are always available when executing code in chat?*/

/* Most extra functions could be possibly unsafe */

    var wl = {
        "self": 1,
        "onmessage": 1,
        "postMessage": 1,
        "global": 1,
        "wl": 1,
        "eval": 1,
        "Array": 1,
        "Boolean": 1,
        "Date": 1,
        "Function": 1,
        "Number" : 1,
        "Object": 1,
        "RegExp": 1,
        "String": 1,
        "Error": 1,
        "EvalError": 1,
        "RangeError": 1,
        "ReferenceError": 1,
        "SyntaxError": 1,
        "TypeError": 1,
        "URIError": 1,
        "decodeURI": 1,
        "decodeURIComponent": 1,
        "encodeURI": 1,
        "encodeURIComponent": 1,
        "isFinite": 1,
        "isNaN": 1,
        "parseFloat": 1,
        "parseInt": 1,
        "Infinity": 1,
        "JSON": 1,
        "Math": 1,
        "NaN": 1,
        "undefined": 1
    };

    Object.getOwnPropertyNames( global ).forEach( function( prop ) {
        if( !wl.hasOwnProperty( prop ) ) {
            Object.defineProperty( global, prop, {
                get : function() {
                    throw new Error( "Security Exception: cannot access "+prop);
                    return 1;
                }, 
                configurable : false
            });    
        }
    });

    Object.getOwnPropertyNames( global.__proto__ ).forEach( function( prop ) {
        if( !wl.hasOwnProperty( prop ) ) {
            Object.defineProperty( global.__proto__, prop, {
                get : function() {
                    throw new Error( "Security Exception: cannot access "+prop);
                    return 1;
                }, 
                configurable : false
            });    
        }
    });




onmessage = function( event ) {
    "use strict";
    var code = event.data.code;
    var result;
    try {
        result = eval( '"use strict";\n'+code );
    }
    catch(e){
        result = e.toString();
    }
    postMessage( "(" + typeof result + ")" + " " + result );
};
  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-04T18:07:15+00:00Added an answer on June 4, 2026 at 6:07 pm

    The current code (listed below) has been now in use in the Stackoverflow javascript chat room for a while
    and so far the toughest problem was Array(5000000000).join("adasdadadasd") instantly crashing some
    browser tabs for me when I was running the code executor bot. Monkeypatching Array.prototype.join seems to have fixed this and the maximum
    execution time of 50ms has worked for any other attempt to hog memory or crash the browser.

    var global = this;
    
    /* Could possibly create some helper functions here so they are always available when executing code in chat?*/
    
    /* Most extra functions could be possibly unsafe */
    
    var wl = {
        "self": 1,
        "onmessage": 1,
        "postMessage": 1,
        "global": 1,
        "wl": 1,
        "eval": 1,
        "Array": 1,
        "Boolean": 1,
        "Date": 1,
        "Function": 1,
        "Number" : 1,
        "Object": 1,
        "RegExp": 1,
        "String": 1,
        "Error": 1,
        "EvalError": 1,
        "RangeError": 1,
        "ReferenceError": 1,
        "SyntaxError": 1,
        "TypeError": 1,
        "URIError": 1,
        "decodeURI": 1,
        "decodeURIComponent": 1,
        "encodeURI": 1,
        "encodeURIComponent": 1,
        "isFinite": 1,
        "isNaN": 1,
        "parseFloat": 1,
        "parseInt": 1,
        "Infinity": 1,
        "JSON": 1,
        "Math": 1,
        "NaN": 1,
        "undefined": 1
    };
    
    Object.getOwnPropertyNames( global ).forEach( function( prop ) {
        if( !wl.hasOwnProperty( prop ) ) {
            Object.defineProperty( global, prop, {
                get : function() {
                    throw "Security Exception: cannot access "+prop;
                    return 1;
                }, 
                configurable : false
            });    
        }
    });
    
    Object.getOwnPropertyNames( global.__proto__ ).forEach( function( prop ) {
        if( !wl.hasOwnProperty( prop ) ) {
            Object.defineProperty( global.__proto__, prop, {
                get : function() {
                    throw "Security Exception: cannot access "+prop;
                    return 1;
                }, 
                configurable : false
            });    
        }
    });
    
    Object.defineProperty( Array.prototype, "join", {
    
        writable: false,
        configurable: false,
        enumerable: false,
    
        value: function(old){
            return function(arg){
                if( this.length > 500 || (arg && arg.length > 500 ) ) {
                    throw "Exception: too many items";
                }
    
                return old.apply( this, arguments );
            };
        }(Array.prototype.join)
    
    });
    
    
    (function(){
        var cvalues = [];
    
        var console = {
            log: function(){
                cvalues = cvalues.concat( [].slice.call( arguments ) );
            }
        };
    
        function objToResult( obj ) {
            var result = obj;
            switch( typeof result ) {
                case "string":
                    return '"' + result + '"';
                    break;
                case "number":
                case "boolean":
                case "undefined":
                case "null":
                case "function":
                    return result + "";
                    break;
                case "object":
                    if( !result ) {
                        return "null";
                    }
                    else if( result.constructor === Object || result.constructor === Array ) {
                        var type = ({}).toString.call( result );
                        var stringified;
                        try {
                            stringified = JSON.stringify(result);
                        }
                        catch(e) {
                            return ""+e;
                        }
                        return type + " " + stringified;
                    }
                    else {
                        return ({}).toString.call( result );
                    }
                    break;
    
            }
    
        }
    
        onmessage = function( event ) {
            "use strict";
            var code = event.data.code;
            var result;
            try {
                result = eval( '"use strict";\n'+code );
            }
            catch(e) {
                postMessage( e.toString() );
                return;
            }
            result = objToResult( result );
            if( cvalues && cvalues.length ) {
                result = result + cvalues.map( function( value, index ) {
                    return "Console log "+(index+1)+":" + objToResult(value);
                }).join(" ");
            }
            postMessage( (""+result).substr(0,400) );
        };
    
    })();
    
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

In my quest to correctly grasp Interface best practices, I have noticed declarations such
In my quest to generate new code in a Scala compiler plugin, I have
I have 4 string variables name, quest, favorite_color, speed that might be empty. I
I have a form that has many long-methods. My quest is: What is the
In my quest for a version-wide database filter for an application, I have written
In my quest to further my knowledge, I'm trying to get get NHibernate running.
In my quest for my first iPhone app I have posted about the correct
Quest I am looking to fetch rows that have accented characters. The encoding for
I have a chatprogram which contains users and channels. My next quest is to
I have a PlaceHolder control inside of a ListView that I am using to

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.