Revisiting Disable JavaScript Execution From Console

Recent changes done by Chrome team have made my previous technique for disabling JavaScript execution redundant. The post was referenced in StackOverflow after which it was reported as a bug in Chromium. I have my reservation on bug description and what they actually fixed but that’s for a later post.

Before we proceed further, a DISCLAIMER – any technique that we may learn in this post may get deprecated by browser as they evolve and hence the code should never be considered for production environment. It is good to know what you can do in JavaScript world however things, which are not within the capacity of application, should never be controlled by web application. You must leave them to browser to handle it at their level best.

Done reading disclaimer? Ready to dive? Read on.

Stop! If you have not read my previous post yet, please go and read it first.

With recent changes, chrome now does following thing –

  1. It renamed the property to __commandLineAPI instead of _commandLineAPI (additional underscore at the beginning, seriously?)
  2. Moved the property hosting object from window.console to window.
  3. Property gets created only during the console execution. So whether you start typing in for code completion feature or execution feature, the property gets created and at the end of it, it gets deleted too.
  4. It now also checks that if the property has already been attached to window, if so, it won’t create it and directly execute the code without using the “with” scope mechanism. (so, don’t bother changing the code from previous code to align with new name and hosting container. It won’t work)

With all of the above, it becomes very difficult to break this type of logic since it involves existence check for property, runtime creation/deletion of property and then execution within the scope of property. Also, all the variables are setup within closure so adding a trap for them also won’t work. In short, they made it very difficult.

However considering the capability provided by JavaScript, I found a place where I can setup a hook and can still stop the execution. (What were you thinking? I mentioned it already that they made it difficult, not impossible.)

I noticed that they are preparing the expression typed/pasted by user , adding prefix/suffix as necessary and passing it to evaluate function via call method. So if you override call function and look for string containing “__commandLineAPI” ? Let’s see the code

( function(){
	var __x = Function.prototype.call;
        Function.prototype.call = function( thisArg ){
             if( arguments[1] && arguments[1].indexOf &&
                 arguments[1].indexOf( "with (__commandLineAPI" ) !== -1 ) {
			throw "Sorry, Execution via Console has been disabled!";
             }
             
	     __x.apply( this, arguments );
        };
})();

With the above in web application, try opening console and start typing any JavaScript code. Notice the error message!

Having described way to disable console yet again, I still recommend not to use such technique cause of multiple reason. Foremost being controlling browser behavior is not something which a web application can do and hence should refrain from doing so.

Disable JavaScript execution from console

Most modern browser today offers developer tools either as part of browser engine (like Chrome Developer Tools in Google Chrome) or as extension mechanism (like firebug in Mozilla Firefox). These tools are certainly in a way responsible for making JavaScript a much matured language because they provide a powerful tool to debug through the script. Those shortcut keys (F8, F10, F11 etc), which use to work in powerful IDEs, was almost a privilege to other programming languages have finally arrived to JavaScript developers. Matter of no debate, powerful debugging tools is a mandate for any programming language to become mature enough to attract wide audience from developer community.

However as the debugging, which is open for all (remember, it is attached to browser and not to a particular IDE), gets more and more popular, anyone can write script snippet using console and get it executed in the host application environment (i.e., the web page which is being displayed in the browser). Obviously this cannot be considered as security threat since the user who is trying to execute any script snippet has execution permission. For example, if user has no permission to view account statement for other user, he/she cannot do so via executing script using console since the permission are governed by backing server code.

In certain cases, it is still possible that you may want to disable any kind of script execution via console for your web application due to business demands. For the practical reason, neither you can configure user’s browser to disable console nor ask them to stop using console (both won’t work, billions of user and why would they listen to you?)

In such case, the only practical possibility would be to host code in your web application which disallows any script execution via console. Wow! First question, is that even possible? How?

Yes, that’s kind of possible and which is what I am going to explain now. Let’s take example of Google Chrome Developer tools.

Chrome developer tools takes anything which is typed in to console as an input and simply passes it to evaluate function to run it in the host application environment. Before doing so, they create a property “_commandLineAPI” in console object and whole script gets executed in with block as

with ((window && window.console && window.console._commandLineAPI) || {}) {
// your script here.
}

Now seeing what we have above, it is very easy to say that the only way to stop execution of “script code typed in console” is to throw an exception before that.

A simplest way would be to save the console object in a function variable and define console property in window object with accessor/mutators (i.e., get/set). In get function, we could simply check if the property attached by chrome developer tool exists and if yes, throw exception (obviously which is not handled by anyone and hence stops execution of further code).

Here’s the full code snippet

<script type="'text/javascript'">
(function(){

    var _z = console;
    Object.defineProperty( window, "console", {
	get : function(){
	    if( _z._commandLineAPI ){
		throw "Sorry, Can't exceute scripts!";
            }
	    return _z; 
	},
	set : function(val){
	    _z = val;
	}
    });

})();
</script>

With the above script added in your web application, try launching console and execute any script. You would notice the following message in console (and yes, typed in script in console did not get executed!)

Script Execution Using Chrome Developer Tools

Whoa!!!