Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the best method to dynamically sandbox inline JavaScript?

I have a WordPress plugin that loads pages with AJAX and to ensure compatibility with other plugins and "widgets."

As of right now I use the following code to evaluate all inline JS that is inside the content blocks to be updated:

  function do_JS(e){
        var Reg = '(?:<script.*?>)((\n|.)*?)(?:</script>)';
        var match    = new RegExp(Reg, 'img');
        var scripts  = e.innerHTML.match(match);
        var doc = document.write;
        document.write = function(p){ e.innerHTML = e.innerHTML.replace(scripts[s],p)};
        if(scripts) {
            for(var s = 0; s < scripts.length; s++) {
                var js = '';
                var match = new RegExp(Reg, 'im');
                js = scripts[s].match(match)[1];
                js = js.replace('<!--','');
                js = js.replace('-->','');
                eval('try{'+js+'}catch(e){}');
            }
        }
        document.write = doc;
    }

I'd like to be able to sandbox the JS a bit better so that the risk of conflicts are minimized. One idea I had was to dynamically create an <iframe> and run the JS inside of it, but I was hoping there was a bit better method to both ensure compatibility and increase security.

like image 794
Aaron Harun Avatar asked Jun 28 '10 04:06

Aaron Harun


2 Answers

You could try recompiling the javascript with caja: http://en.wikipedia.org/wiki/Caja_project

like image 166
Joeri Sebrechts Avatar answered Oct 22 '22 23:10

Joeri Sebrechts


Chances are this won't give you exactly what you need, but how about wrapping your script text inside a function or self-executing function literal (function(){/*...*/})().

var strEval =  'try{';
strEval += 'widget[' + intWidgetNumber + '] = (function(){';
strEval += js;
strEval += '})();';
strEval += '}catch(e){}';

This provides more protection than straight evaluation and keeps the code in the same document. The downside is that if the code you are importing is messy about global variables (which is probably why you are asking this exact question), you could still have their code stomping on other code. And if they use the this keyword, their code likely won't work as intended. But this at least will keep properly declared variables and function declarations in an encapsulated scope.

I've worked with third-party code a lot (mostly horribly, horribly written ad code) and I've found the best solution is to keep your site code wrapped in a lengthy and unique namespace (mySiteUtils, mySiteGames, etc. or com.mysite.utils, com.mysite.games, etc.). If an ad agency decides to drop in code that matches your exact namespace they will destroy your page, but so far that's never happened.

like image 29
Andrew Avatar answered Oct 22 '22 23:10

Andrew