JavaScript – How to Protect Namespace of an Object

code-securityjavascriptobject-orientedSecurity

Continuing from my previous question: Javascript simple code to understand prototype-based OOP basics
Let's say we run into console this two separate objects(even if they are called child and parent there is no inheritance between them):

var parent = {
    name: "parent",
    print: function(){
       console.log("Hello, "+this.name);
    }
};

var child = {
    name: "child",
    print: function(){
       console.log("Hi, "+this.name);
    }
};

parent.print()
// This will print: Hello, parent
child.print()
// This will print: Hi, child

temp =parent;
parent = child;
child = temp;


parent.print()
// This will now print: Hi, child
child.print() 
// This will now print: Hello, parent

Now suppose that parent is a library, as a HTML5 application in a browser this cannot do much harm because is practically running sandboxed, but now with the advent of the ChromeOS, FirefoxOS and other [Browser] OS they will also be linked to a native API, that would be a head out of the „sandbox”. Now if someone changes the namespace it would be harder for a code reviewer (either automated or not ) to spot an incorrect use if the namespaces changes.

My question would be: Are there many ways in which the above situation can be done and what can be done to protect this namespaces? (Either in the javascript itself or by some static code analysis tool)

Best Answer

There is really very little you can do (in all browsers) to protect global variables.

However a common (good) practice is to encapsulate all of your scripts in (IIFE) functional closures.

(function() {
    var parent = {
        name: "parent",
        print: function(){
           console.log("Hello, "+this.name);
        }
    };

    var child = {
        name: "child",
        print: function(){
           console.log("Hi, "+this.name);
        }
    };

    parent.print()
    // This will print: Hello, parent
    child.print()
    // This will print: Hi, child
})();

This means that you may only use parent and child inside the scope of that function. While that is limiting, it is also protecting. If you needed them globally, one option would be maintain a namespace object:

var myGlobals = {};

(function( global ) {
    global.parent = {
        name: "parent",
        print: function(){
           console.log("Hello, "+this.name);
        }
    };

    global.child = {
        name: "child",
        print: function(){
           console.log("Hi, "+this.name);
        }
    };

    global.parent.print()
    // This will print: Hello, parent
    global.child.print()
    // This will print: Hi, child
})(myGlobals);

Or if you really needed them as individual globals, you could just do:

(function() {
    window.parent = {
        name: "parent",
        print: function(){
           console.log("Hello, "+this.name);
        }
    };

    window.child = {
        name: "child",
        print: function(){
           console.log("Hi, "+this.name);
        }
    };

    parent.print()
    // This will print: Hello, parent
    child.print()
    // This will print: Hi, child
})();

But that leaves you back at square one. In this case you would need to make sure that you do something to protect those variables at the time of shuffling. Instead of writing:

temp =parent;
parent = child;
child = temp;

You may write:

(function( parent, child ) {

    // Do some stuff.

    // Note: parent and child are references,
    // although they are switched, something like:
    //    child.hello = "hello";
    // will still edit the `parent` object in the outer scope

})(child, parent); // Pass them in swapped.

Freeze and Seal (two new JS Object methods) are worth noting in this thread despite not exactly solving your problem nor having cross-browser support yet.

Related Topic