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.

Menu based Environment Selection Script

During development, you will often see yourself playing with different environment (in unix based system). For example, at one instance, you will need Oracle DB environment so that you can use sql prompt. In other case, you might need your application environment to work with it. Or you might just need default environment.

It is always painful to set proper environment after logging in to the machine as you will need to remember which environment script to source (probably alias can help here!). I always had this problem until I implemented environment selection script.

Basically the idea was to

1) Create scripts which can source required environment variable and put all the scripts at one location.

2) Prepare another script which would execute at login. Lets call it "ShellEnv".

3)  “ShellEnv” should read all the environment specific scripts from the predefined location and show a console based menu.

4) Based on user selection, “ShellEnv” would source the corresponding script and hence your environment would have correct configuration.

So the script would look like 

#! /bin/ksh
export ENV_FILE_LOC=/home/kunalkumar/env
prepareMenu
displayMenu
readValues
executeOptions

Now the problem is, how would “ShellEnv” determine which script is for which environment and how it should present the menu? Obviously, script should have certain indicator which can help in preparing menu. I choose to add “DISPLAY_MENU_STRING” in all my configuration files. For example, my Oracle DB scripts contains the following (Note that DISPLAY_MENU_STRING is commented in the script.)

#DISPLAY_MENU_STRING=Oracle 11.2g (kspace)
export ORACLE_HOME=/usr/oracle/11.2
export ORACLE_SID=test

With this, “ShellEnv” can determine how the menu should be constructed to display. Using “DISPLAY_MENU_STRING”, function prepareMenu

prepareMenu(){
        unset fileName
        unset menuString
        set -a fileName
        set -a menuString
        index=0;
        for file in `ls $ENV_FILE_LOC`
        do
                string=`grep "DISPLAY_MENU_STRING" $ENV_FILE_LOC/$file | awk -F"=" '{ print $2 }'`
                if [[ $string != "" ]]; then
                        fileName[index]=$file;
                        menuString[index]=$string;
                        index=`expr $index + 1 `;
                fi
        done
}

Basically, It prepared array of file names and corresponding display string while looking into the predefined directory. After preparing the list, next task was to display the menu and hence

displayMenu(){
        echo "Available Shell Configuration. ";
        index=1;
        totalMenuItem=${#fileName[*]};
        while [[ $index < $totalMenuItem ]]; do
                echo "$index  - ${menuString[$index]}";
                index=`expr $index + 1`
        done;
        echo "Please select configuration : ";
}

After displaying the menu, user could choose the environment by providing input. The input would be consumed by readValues and used by executeOptions. Function executeOptions would source the environment as selected by the user. I also included a script to source default configuration which should be available irrespective of any environment selected. and hence the function

executeOptions(){
        OLDIFS=$IFS;
        export IFS=" ";
        inputArray=$inputOptions;
        totalInputOptions=${#inputArray[*]};
        echo "Sourcing Default Environment...";
        . $ENV_FILE_LOC/1_Default
        if [[ $totalInputOptions -eq 0 ]]; then
                echo "No option selected!";
                return;
        fi

        index=0;
        while [[ $index < $totalInputOptions ]]; do
                echo "Sourcing environment from ${fileName[ ${inputArray[$index]} ]}";
                . $ENV_FILE_LOC/${fileName[${inputArray[$index]}]};
                index=`expr $index + 1`;
        done
        export IFS=$OLDIFS
}

I included this script in .profile so that it gets executed at login and I can choose my environment by typing the option.

login: kunal
password:
Available Shell Configuration. 
1 – Oracle 11.2g (kspace)
2 – My App Environment
3 – Test Environment
Please select configuration : 1
Sourcing Default Environment...
Sourcing environment from Oracle_11_2.ksh

If you are interested in this script, you can find it at github.