In Mozilla's JavaScript environment, it is possible to load other script from a URL using the loadSubScript() method of the mozIJSSubScriptLoader interface.
It is possible to specify an object used as the scope object for the script being executed. However, as explained in this Stackoverflow answer, "undeclared variables will still be created in the outer scope and the outer scope will be searched for variables that cannot be resolved in the subscript scope."
This answer recommends to use Components.utils.Sandbox as an alternative.
However, this mechanism apparently enables security restrictions. For Mozilla bug 876089, I tried out simply replacing the regular JS object with a sandbox. The loaded script could then no longer use Components.utils, placed in the scope object as "Cu":
EXCEPTION: Permission denied for to call method UnnamedClass.import
Now the question: In the Mozilla environment, how can I best load scripts in a way that just prevents leaking of symbols via the caller's global object, but still allows it to use all the symbols explicitly placed in the scope object without imposing any security restrictions?
Indeed, using a Sandbox is the right approach. Security settings can be managed by using a special principal as the scope object, instead of a plain JavaScript object.
By using the system principal, all security checks are disabled.
The code then looks like this:
Components.utils.import("resource://gre/modules/Services.jsm");
var systemPrincipal = Services.scriptSecurityManager.getSystemPrincipal();
var scopeObject = new Components.utils.Sandbox(systemPrincipal);
// set properties of the scope object like this:
// scopeObject.someProperty = someValue;
var loader = Components.classes["#mozilla.org/moz/jssubscript-loader;1"]
.getService(Components.interfaces.mozIJSSubScriptLoader);
// Set uri to the uri of the script to load
loader.loadSubScript(uri, module, "UTF-8");
Related
Loading a module from a source dynamically:
var src="HERE GOES MY SOURCE"
var Module = module.constructor;
var m = new Module();
m._compile(src, 'a-path-that-does-not-exist');
Need to achieve following:
Pass some variables/functions so that they can be used inside the src script globally. Can set them in "m.foo", but want the script to use "foo" without using "module.foo". "global.foo" works, but see the point 2.
How to restrict the src script from accessing global scope?
How to restrict the src from loading other modules using require or other means.
How to restrict the src from running async operations?
All, I can think of is to wrap the script in its own function, kind of like nodejs already does for commonJS modules. This is the regular wrapper.
(function(exports, require, module, __filename, __dirname) {
// Module code actually lives in here
});
If you wrap that user code with your own wrapper and then when you call it to execute it, you can define your own values for require, module and any other semi-global symbols.
If you also put 'use strict'; as the very first line of your wrapper function (before any of the user code), then that will eliminate default assignment to the global object with just something like x = 4 because that will be an error without explicitly defining x first. If you then also make your own global object and pass it as an argument, that can keep anyone from assigning to the real global object. I don't think you can prevent implicit read access to pre-existing globals.
So, your wrapper could look like this:
(function(exports, require, module, __filename, __dirname, global) {
'use strict';
// insert user code here before evaluating it with eval()
// and getting the function which you can then call and pass the desired arguments
});
Then, when you call this function, you pass it the values you want to for all the arguments (something other than the real ones).
Note, it's hard to tell how leak-proof this type of scheme really is. Any real security should likely be run in a resource restricted VM.
Another idea, you could run in a Worker Thread which has it's own virgin set of globals. So, you do all of the above and run it in a Worker Thread.
Addressing your questions in comments:
Does the 'use strict'; need to go inside the wrapper function or outside?
It needs to be the first line of code inside the wrapper function, right before where you insert the user code. The idea is to force that function scope (where the user code lives) inside that wrapper to be in strict mode to limit some of the things it can do.
Could you explain the "I don't think you can prevent implicit read access to pre-existing globals."? If i provide my own object as global, how can the inner script access preexisting globals?
Any code, even strict mode code can access pre-existing globals without the global prefix. While you can prevent the code from creating new globals by shadowing it with your own global in the wrapper function arguments and by forcing it into strict mode, you can't prevent strict mode code from reading existing globals because they can do so without the global prefix. So, if there's a pre-existing global called "foo", then existing code can reference that like:
console.log(foo);
or
foo = 12;
If there is no foo in a closer scope, the interpreter will find the foo on the global object and use that.
Note that strict mode prevents the automatic creation of a new global with something like:
greeting = "happy birthday"
Could you elaborate more no "resource restricted VM"?
I was talking about real hardware/OS level VMs that allow you to fully control what resources a process may use (disk access, sockets, memory, hardware, etc...). It's essentially a virtual computer environment separate from any other VMs on the same system. This is a more rigorous level of control.
WorkerThread is a very interesting concept. will take a look! My understanding was that WorkerThreads provide memory isolation and the only way to share data is by sending messages (effectively creating copies)?
Yes, Worker Threads provide pretty good isolation as they start up a whole new JS engine and have their own globals. They can shared ArrayBuffers in certain ways (if you choose to do that), but normal JS variables are not accessible across thread boundaries. They would normally communicate via messaging (which is automatically synchronized through the event queue), but you could also communicate via sockets if you wanted.
Web App Model
Suppose I have a sensitive JS object by which I can do critical stuff. My requirement is that I would like to wrap this object entirely such that no one can access it. Here is my pattern to wrap this object.
var proxy = (function (window){
// A private reference to my critical object (i.e. big apple)
var bigApple = window.bigApple;
// Delete this property so that no one else can access it
delete window.bigApple;
// Oooah, It's mine! I'm now eating it :)
// Public APIs exposed globally
return {
doStuffWithBigApple: function (){
// The Script element being executed now
var who = document.currentScript;
// Access control
if(isLegitimate(who)){
return bigApple.doStuff();
}
}
};
}) (window);
By this code I export a public literal object named proxy so that every one can access it.
What is that isLegitimate? It is an abstract function to be implemented which decides which script elements access to which methods of my big apple. The decision is made with regard to src attribute of the script element. (i.e. their domain)
Others use this public API like this:
proxy.doStuffWithBigApple();
Attack Model
In my web app there are placeholders for advertising such that external contents including JavaScript codes could be loaded and get executed. All of these external resources eagerly would want to access my big apple.
Note: Those are added after my scripts resulting in there is no access to the original window.bigApple.
My Question
Is there any circumventing way for my security model?
Critical edges:
Changing src attribute at parse-time. --- Not possible, because src can only be set once.
Adding script element at run-time --- No problem is raised
Your idea of creating a proxy is good imo, however, if you have access to ES6, why not looking into Proxy? I think it does what you want out-of-the-box.
The MDN provides good examples on how do traps for value validation in a setter, etc.
EDIT :
Possible trap I have imagined :
document.currentScript is not supported in IE. So if you care about it and decide to polyfill it/use a pre-exisiting polyfill, make sure it is secure. Or it could be used to modify on the fly the external script url returned by document.currentScript and skew the proxy. I don't know if this could happen in real life tho.
This way for protecting JavaScript objects has a very significant issue which should be addressed, otherwise this way will not work properly.
MDN noted on this API that:
It's important to note that this will not reference the <script> element if the code in the script is being called as a callback or event handler; it will only reference the element while it's initially being processed.
Thus, any call to proxy.doStuffWithBigApple(); inside callbacks and event handlers might lead to misbehaving of your framework.
In Node.js, if I load a module which contains code in module-scope like:
this["foo"] = function() { console.log("foo"); }
...then I appear to get a globally available function that I can call just by saying foo() from any code using the module. It can be seen as one of the printed items with Object.getOwnPropertyNames(this).
However, if I put the following in module scope instead:
function foo() { console.log("foo"); }
...then it produces a function which can similarly be called within that module as foo(), but is invisible outside of it (e.g. does not show up as one of the items with Object.getOwnPropertyNames(this)).
I gather this is a change in runtime behavior from what's done in browsers. A browser seems to poke everything into global scope by default (and for years people have had to consciously avoid this by wrapping things up in anonymous functions/etc.)
My question is whether NodeJs has some secret way of interacting with these declarations outside of the module in which they are declared BESIDES using exports.(...) = (...). Can they be enumerated somehow, or are they garbage collected as soon as they are declared if they're not called by a module export? If I knew what the name of such a function was going to be in advance of loading a module...could I tell Node.js to "capture it" when it was defined?
I'm not expecting any such capabilities to be well-documented...but perhaps there's a debugger feature or other system call. One of the best pointers would be to the specific code in the Node.js project where this kind of declaration is handled, to see if there are any loopholes.
Note: In researching a little into V8 I saw that a "function definition" doesn't get added to the context. It's put into an "activation object" of the "execution context", and cannot be programmatically accessed. If you want some "light reading" I found:
http://coachwei.sys-con.com/node/676031/mobile
http://perfectionkills.com/understanding-delete/
if you fill in exports.foo = foo; at the end of your file it will be available in other files in node, assuming that you do var myFile = require('myFile.js') with the file name and you call the function via myFile.foo(); You can even rename the function for outside use in exports and set whatever you want to call the package when you use require.
BTW you can enumerate these functions just like you do on any JSON object (ie for k in ...)
This is impossible in node without more advanced reflection tools like the debugger.
The only way to do this would be to use __parent__ which was removed due to security issues and other things (hard to optimize, not standard to begin with) . When you run the script those variables become closed under the module. You can not access them elsewhere without explicitly exporting them.
This is not a bug, it's by design. It's just how node works. see this closely related question.
If this sort of reflection was available without tools like the debugger it would have been extremely hard to optimize the source code (at least the way v8 works) , meaning the answer to your question is no. Sorry.
I've been reading up on global namespace pollution when developing an extension for Firefox, and I want to avoid it as much as possible in my extension. There are several solutions, but generally, the solutions seem to center around only declaring one global variable for your extension, and putting everything in that. Thus you only add one extra variable to the global namespace, which isn't too bad.
As a brief aside, I have had a solution proposed to me that avoids putting any extra variables into the global namespace; wrap everything in a function. The problem here is that there's nothing to refer to in your XUL overlays. You have to declare elements in your overlays, and then in JS add a ton of addEventListeners to replace what would've been something like an oncommand="..." in XUL. I don't want to do this; I definitely want my XUL to include events in the XUL itself because I think it looks cleaner, so this isn't a solution for me. I therefore need at least 1 global variable for XUL oncommand="..." attributes to refer to.
So the consensus seems to be to have one (and only one) variable for your extension, and put all your code inside that. Here's the problem: generally, people recommend that that variable be named a nice long, unique name so as to have almost zero chance of colliding with other variables. So if my extension's ID is myextension#mycompany.com, I could name my variable myextensionAtMycompanyDotCom, or com.mycompany.myextension. This is good for avoiding collisions in the global namespace, but there's one problem; that variable name is long and unwieldy. My XUL is going to be littered with references to event handlers along the lines of oncommand="myextensionAtMycompanyDotCom.doSomeEvent". There's no way to avoid having to refer to the global namespace in my XUL overlays, because an overlay just gets added to the browser window's DOM; it doesn't have a namespace of its own, so we can't somehow limit our extension's variable scope only to our own overlays. So, as I see it, there are four solutions:
1. Just use the long variable name in XUL
This results in rather unwieldy, verbose XUL code like:
<statusbarpanel id="myStatusBar" onmousedown="myextensionAtMycompanyDotCom.onMyStatusBarClick();">
2. Add an element of randomness to a short variable name
We come up with a much nicer short variable name for our extension, let's say myExt, and add some random characters on to make it almost certainly unique, such as myExtAX8T9. Then in the XUL, we have:
<statusbarpanel id="myStatusBar" onmousedown="myExtAX8T9.onMyStatusBarClick();">
Clearly, this results in rather ugly and even confusing code as the random characters look odd, and make it look like some kind of temporary variable.
3. Don't declare any global variables at all
You could just wrap up everything in functions. This, of course, means that there is nothing to refer to in your XUL, and so every event must be attached to the XUL elements using addEventListener in your JavaScript code. I don't like this solution because, as mentioned above, I think it's cleaner to have the events referenced in the XUL code rather than having to search a ton of JS code to find which events are attached to which XUL elements.
4. Just use a short variable name in XUL
I could just call my extension's variable myExt, and then I get nice XUL code like:
<statusbarpanel id="myStatusBar" onmousedown="myExt.onMyStatusBarClick();">
Of course, this short name is much more likely to clash with something else in the global namespace and so isn't ideal.
So, have I missed something? Is there any alternative to the 4 solutions I proposed above? If not, what would be the best of the 4 (given that #3 is basically unacceptable to me), and why?
We use the JavaScript module pattern described in this blog post: http://www.adequatelygood.com/2010/3/JavaScript-Module-Pattern-In-Depth. You can export the symbols that you want to use in your XUL handlers as described.
In addition, we use a reversed host name as the module name prefix to ensure that we control the namespace:
/* Set up the global namespace. */
if (typeof(com) == "undefined") var com = {};
if (!com.salsitasoft) com.salsitasoft = {};
/* Main namespace. */
com.salsitasoft.myExtensionGlobalStuffGoesHere = (function (my) {
return my;
})(com.salsitasoft.myExtensionGlobalStuffGoesHere || {});
Update: I changed this to pass com.salsitasoft.myExtensionGlobalStuffGoesHere into the closure if it already exists so that the namespace can be spread across multiple files.
Your functions have to "live" somewhere either way, so you cannot avoid to claim some kind of namespace. I also agree to your point that defining the event in the XUL is better than attaching them. So, I propose a hybrid between 3+4:
Find a namespace that is unique for your plugin yet as catchy as possible, for example "catchyseo".
Place all the code of your plugin and all variables inside this namespace. Use the anonymous function wrapper pattern like (have a look at some jQuery plugins as code examples):
window.catchyseo = (function(){var private = x; [...] })();
In your namespace, expose some event handlers which you can reference in your XUL.
This approach gives you the best of two worlds: you can define your events in XUL and you have a closed namespace without any global namespace pollution - except your one namespace variable.
JavaScript: The Good Parts defines these kinds of declarations as bad:
foo = value;
The book says "JavaScript’s policy of making forgotten variables global creates
bugs that can be very difficult to find."
What are some of the problems of these implied global variables other than the usual dangers of typical global variables?
As discussed in the comments on this answer, setting certain values can have unexpected consequences.
In Javascript, this is more likely because setting a global variable actually means setting a property of the window object. For instance:
function foo (input) {
top = 45;
return top * input;
}
foo(5);
This returns NaN because you can't set window.top and multiplying a window object doesn't work. Changing it to var top = 45 works.
Other values that you can't change include document. Furthermore, there are other global variables that, when set, do exciting things. For instance, setting window.status updates the browser's status bar value and window.location goes to a new location.
Finally, if you update some values, you may lose some functionality. If, for instance, you set window.frames to a string, for instance, you can't use window.frames[0] to access a frame.
Global variable make it very difficult to isolate your code, and to reuse it in new contexts.
Point #1:
If you have a Javascript object that relies on a global var. you will not be able to create several instances of this object within your app because each instance will change the value of the global thereby overwriting data the was previously written by the another instance.
(Unless of course this variable holds a value that is common to all instances - but more often than not you'll discover that such an assumption is wrong).
Point #2:
Globals make it hard to take existing pieces of code and reuse them in new apps. Suppose you have a set of functions defined in one file and you want to use them in some other file (in another app). So you extract them to a new file and have that file included in the new app. If these function rely on a global your 2nd app will fail at runtime because the global variable is not there. The dependency on globals is not visible in the code so forgetting these variables (when moving functions to new files) is a likely danger.
They're global variables, so yes, all of the "usual dangers" apply. The main thing that distinguishes them from global variables in other languages is that:
You don't explicitly declare them in a global scope. If you mistakenly omit var in a variable declaration, you've accidentally declared a global variable. JavaScript makes it a little too easy to unintentionally declare global variables; contrast this with Scheme, which raises an error if a variable is not defined in the global scope.
Global variables, at least in the browser, are aliased by window[variable_name]. This is potentially worrisome. For example, some of your code might access window['foo'] (with the intention of accessing a global variable). Then, if you accidentally type foo instead of var foo elsewhere in the program, you have declared a reference to window['foo'], which you meant to keep separate.
One issue is that you may be trampling on already defined variables and not know it, causing weird side effects in other parts of the code that can be a bear to track down.
Another is that it is just sloppy code. You should not be creating variable with more scope than they need since at the very least it keeps more variables in memory and at worst it can create data scenarios you didn't intend.
The bottom line is that when you do that you don't know for sure that you are not messing up other functions that use a global variable of the same name. Sometimes it isn't even your fault, a lazy programmer of another plugin left something global that was meant to have scope inside of a function. So it is a very practical safeguard for writing better and less buggy code.
The problems of typical global variables is that they are, well, global - there is no scope to enclose them, and any code that you are executing / interacting with (such as a library that you call down the road) could modify the variable without a warning.
However, these problems are compounded in Javascript by two things:
You can define a global variable anywhere - the only requirement for that is to forget the var keyword.
It is extremely easy to define a global variable when you had no intent to do so. That is the problem that "implied" globals have over "typical" globals - you will create them without even knowing you did.
In a reasonably-designed language that includes truly global variables (ok, so not that reasonably-designed), you would have a limited handful of places to define globals, and it would require a special keyword to do so.