Native function [.sort()] not recognized inside event handler - javascript

Environment: SeaMonkey (FireFox 20.0)
I'm trying to do a simple sort: Either inside a worker itself OR inside its postMessage handler.
(All code samples from inside the top level (.html) file).
works:
function a() {
var xyzzy = [40, 1, 5, 200];
xyzzy.sort();
};
fails: (Error: TypeError: xyzzy.sort is not a function)
var lrw0 = new Worker('lrw0.js');
lrw0.onmessage = function (event) {
var xyzzy = [40, 1, 5, 200];
xyzzy.sort();
};
After the postMessage event the handler has the same context and scope as did the worker. Fair enough. Needless to say the sort fails inside the worker itself. Seems as if a utility library cannot be accessed?
Utterly defeated. I have spent days on this - no doubt reading the solution somewhere without having understood it. Any contributions (including 'rude but informative') gratefully accepted. I fully appreciate the necessity of mercilessly punishing newbies.

Neither of those examples will work until you fix the call to the Array.sort method
Syntax
array.sort([compareFunction])
Javascript
function a() {
var xyzzy = [40, 1, 5, 200];
xyzzy.sort(); // notice the difference
console.log(xyzzy);
};
a();
On jsfiddle

Related

How to bind console.log to another function call so I can see line number of the script in console where it is called?

My code works but with additional parenthesis like myfunction()();. It should execute with single parenthesis just like normal e.g myfunction();.
I'm building console.time(); console.timeEnd(); polyfill for browsers (e.g <IE10) which do not have native built-in. Note: I have bind() polyfill in-case you think <IE10 does not have it.
Here is my code in "polyfill.js file".
(function() {
'use strict';
var console=window.console, timers={};
if (!console.time) {
console.time = function(name) {
var datenow = Date.now();
name = name? name: 'default';
if (timers[name]) {
console.warn('Timer "'+name+'" already exists.');
}
else timers[name] = datenow;
};
console.timeEnd = function(name) {
var datenow = Date.now();
name = name? name: 'default';
if (!timers[name]) {
console.warn('Timer "'+name+'" does not exists.');
}
else {
var endt = datenow - timers[name];
delete timers[name];
//below is the line where some changes are needed, But I don't know how.
return window.console.log.bind(window.console, name+ ': ' +endt+ 'ms');
}
};
}
}());
Now in another file "main.js file", when I use console.time(); console.timeEnd();, it should log code-line-number of this file in browser console (not the line-number of polyfill.js file). Of-course it works but notice additional parenthesis "()()" below which is not cool.
console.time();
//any code for performance test goes here.
console.timeEnd()(); //Note here "()()". It should be single "()"
I have consulted these 2 stackoverflow questions, but couldn't come up with the right answer.
Wrapping a wrapper of console log with correct file/line number?
A proper wrapper for console.log with correct line number?
I also checked new Error().stack; as an option, but it is also not supported in those browser for which I'm building my polyfill.
Note: If anyone can suggest a solution with eval();, you can. It is also acceptable for me.
There is in fact a function for that called console.trace, which you can read more about in the MDN page.
What it does is print the entire stack trace to the line where it has been called from.
So, for example, running the next code:
function firstFunc() {
secondFunc();
}
function secondFunc() {
console.trace('I was called here!');
}
console.log('Calling firstFunc:');
firstFunc();
will print out this output in the console:
Calling firstFunc:
I was called here!
secondFunc # VM141:6
firstFunc # VM141:2
(anonymous) # VM141:10 // Internal browser trace
Notice that in the given output, all functions are being called and defined in the Chrome console, hence the # VM141:. Generally, it prints the file instead of VM. So, had it been located in an index.js file, it would look like this:
Calling firstFunc:
I was called here!
secondFunc # index.js:8
Compatibility Note
The above method works for any sane browser, and IE11+. That is due to the implementation of console.trace only in IE11.
However, per OP's request, I can think of a creative way to support IE10, and that is by using the Error.prototype.stack property.
Now, of course, as MDN itself mentions it, it's a non-standard feature that should not be used in production, but neither is supporting IE6.
By creating an Error instance and then printing its stack, you can achieve a similar result.
const sumWithTrace = (num1, num2) => {
console.log(new Error().stack); // Creating a new error for its stack property
return num1 + num2;
};
sumWithTrace(1, 5); // returns 6 and prints trace in console

require.js for non-browser platform or the right way to use Function constructor

I am trying to use requirejs in an Apple TV project. We have a lot of requirejs modules written for web, would be cool if we could re-use them.
Apple TV platform has certain limitations and it's sorta impossible to use requirejs "as is". There's no DOM in common sense.
One possible way I found to overcome the problem is: first to load require.js itself and then override its .load() method, so whenever require('foo') gets called it would load foo.js via a simple XHR call:
requirejs.load = (context, moduleName, moduleUrl) ->
reqModule = new XMLHttpRequest()
reqModule.open('GET', appRoot+moduleUrl, true)
reqModule.send(null)
reqModule.onreadystatechange = ->
if reqModule.readyState is 4 and reqModule.status is 200
fn = (new Function(reqModule.responseText))() # parse module
context[moduleName] = fn
context.completeLoad(moduleName)
So this works for normally defined modules like this:
define [], ->
someField: 'empty field'
Even works for self executing functions like this (with shim configured):
(myFoo = ->
someField:"empty field"
)()
for example Undercore.js contains itself in a self executing wrapper
However, that doesn't work with modules defined like this:
myFoo = ->
someField:"empty field"
Question: how can I make it work for all 3 cases? When used in browser, requirejs successfully loads all of them.
One solution I found is to wrap the function in define block for non-wrapped modules like in the last example, so instead of doing fn = (new Function(reqModule.responseText))() I would do:
fn = define [], (new Function("return "+reqModule.responseText))()
But then that would break load for both first and second cases. Is there a way to find out if a function wrapped in a self-executing block or not? How can I distinguish first two cases from the last one?
Using the code in the question as a starting point, I was able to get the following code to work. I don't have Apple TV so I cannot test it on Apple TV. I've tested it in a browser. It is able to load all 3 types of modules you've shown in your question, provided that the 2nd and 3rd modules have appropriate shims. So the logic is sound. The missing piece is what needs to stand in for window in eval.call(window, ...). In Node.js, it would be global. I don't know the equivalent in Apple TV.
requirejs.load = function(context, moduleName, moduleUrl) {
var reqModule = new XMLHttpRequest();
reqModule.open('GET', moduleUrl, true);
reqModule.send(null);
return reqModule.onreadystatechange = function() {
if (reqModule.readyState === 4 && reqModule.status === 200) {
eval.call(window, reqModule.responseText);
return context.completeLoad(moduleName);
}
};
};
If I were you, I would use Browserify
Write your browser code with node.js-style requires.

Disable editing of javascript from chrome console?

So, I just noticed today that you can apparently run javascript in the chrome console. I had no idea you could do this. It's actually really cool.
In my rails app, I have an external javascript page. Some of the variables on that page I would like to be global so that all the functions in the JS file can access them. for example I have a map, and I would like the map object to be global in the javascript file because that way all my functions access the one map variable instead of creating their own, and I can break complex operations down into smaller functions.
This is all well and good I know how to do that and it's working perfectly. My problem now, can I protect the variables from outside? For example you can change the values of all the javascript class variables from the chrome console.. as well methods from for example the map are accessible and excecutable.. I have locked the map settings on one of the pages so it is not zoomable or movable, however from the console I can simply say map.setZoom(11) and the map will zoom to 11.. I can type map.dragable = true and bam u can drag the map.. I don't like this really..
It's not too terribly bad yet like the user enabling map drag and zoom isnt the worst thing in the world.. but still I'd like to disable this. Any ideas?
EDIT
Thanks all for the answers and comments. I guess I will just resort to not putting anything that can be turned malicious into my javascript, and do thing like pass my map variable to functions where necessary to slow people down.
You can use an immediately-invoked function (IIFE) expression to prevent your variables and functions from being exposed in the global scope:
var a = 10;
(function() {
var b = 20;
})();
window.a lets you view and modify a, but you cannot do that with b:
Try it out here
I'm more than sure that there's a way to edit b with Inspector, but I haven't taken the time to figure it out. Don't waste your time trying to prevent your users from modifying code that they can view.
You can't. Even if you wrap them into anonymous functions, user can get to them through debugger. As last resort he can simply intercept your traffic to his own machine and replace your JavaScript with something else.
Bottom line: JavaScript in browser is client-side. Client can do whatever he pleases with it.
Try doing something like this:
(function(){
//All of your current code
})();
One thing to still be aware of - Chrome developer tools also lets you edit the javascript (not the javascript file on the server, just currently running copy.) Go to Chrome Dev Tools->Sources and you can edit the javascript files.
You can't. Your saying you need to define your map globally, this means it's accessible for everyone.
You could define your map in a different scope and then only define the "public" things:
(function() {
var map = new Map();
window.myMap = {
goTo: function(lat, lng) {
map.goTo(lat, lng);
}
};
})();
Depending on your architecture, there are a few ways to accomplish this. Use this method to create a reusable component that has public and private properties:
var protectedScope = function () {
var protected_var = 'protected';
this.showProtected = function () {
return protected_var;
}
this.public = 'public';
};
var myObject = new protectedScope();
console.log('Public var: '+myObject.public); // outputs "public"
console.log('Protected via accessor: '+myObject.showProtected ()); // outputs "private"
console.log('Protected var: '+myObject.protected); // outputs undefined
Any variable or function declared with a var keyword will be, in effect, private. Any variable or function that uses the this.name mechanism will be "public".
Understand that this structure is not truly public or private, such concepts are not a part of the language. There are still ways to get at those variables, and one can always view source. Just be clear; this is a code organization concept rather than a security concept. Chrome has had this developer console for a while, and other major user agents are moving to include similar tools (or already have done so). There are also tools like Firebug which allow a user full access to your javascript runtime environment. This isn't a realm that the developer can control at all.
Try it here: http://jsfiddle.net/cf2kS/
More Reading
"Private Members in JavaScript" by Douglas Crockford* - http://www.crockford.com/javascript/private.html
"OOP in JS, Part 1 : Public/Private Variables and Methods" on http://phrogz.net - http://phrogz.net/JS/classes/OOPinJS.html
Javascript Object Management on MDN - https://developer.mozilla.org/en-US/docs/XUL_School/JavaScript_Object_Management
Closures on MDN - https://developer.mozilla.org/en-US/docs/JavaScript/Guide/Closures
Object.defineProperty(map, 'zoom', {value:1});
or
Object.defineProperty(map, 'zoom',{
set: function(){console.warn('Access denied!');},
get: function(){return 1;}
});
demo
or
Object.defineProperty(Object.prototype, 'protect', {
value: function(ignore){
var childObjects = [], ignore = ignore || [];
ignore.push(this);
if(this instanceof MimeType)return; //Chrome Fix //window.clientInformation.mimeTypes[0].enabledPlugin[0] !== window.clientInformation.mimeTypes[0]
for(var prop in this){
if(typeof this[prop] === "unknown")continue; //IE fix
if(this[prop] instanceof Object){
var skip = false;
for(var i in ignore)
if(ignore[i]===this[prop]){
skip = true;
break;
}
if(!skip)childObjects.push(prop);
}
var d = Object.getOwnPropertyDescriptor(this, prop);
if(!d || !d.configurable || !d.writable)continue;
var that = this;
(function(){
var temp = that[prop];
delete that[prop];
Object.defineProperty(that, prop,{
set: function(){console.warn('Access denied!');},
get: function(){return temp;}
});
})();
}
for(var i = 0;i<childObjects.length;i++)
this[childObjects[i]].protect(ignore);
}
});
this.onload=function(){this.protect();} //example
demo

How to pass an argument to a Javascript Module?

I want to use a Javascript Module (JSM) in a single window of my Xul application, so I can load the resource as I need it.
But, I need to pass the window to the JSM, and I don't know how to do it. Follows my attempt:
In my resource.jsm:
var EXPORTED_SYMBOLS = ["hello"];
function hello(win) {
win.alert("ALERT FROM JSM!");
}
calling in my window with:
Components.utils.import("resource://module/resource.jsm");
hello(window);
but I get:
win is undefined
in the resource.jsm.
Any idea how to make it work?
It might be causing problems that you named the parameter for your hello function to be window. While window isn't a reserved word, most browser environments treat it as an unassignable constant of sorts. Try:
function hello( obj ) {
obj.alert("ALERT FROM JSM!");
}
in your module and then invoke it with hello(window), hello(document.window), or hello(this)
After reading the Javascript Module documentation, it looks like you'll need to create an object within the module and then change it's property by reference. So in your JSM:
var EXPORTED_SYMBOLS = ["params", "hello"];
params = {
win: this
};
function hello() {
params.win.alert("ALERT FROM JSM!");
}
Then you'd invoke by first assigning the window to that parameter and then calling the function:
Components.utils.import("resource://module/resource.jsm");
params.win = window;
hello();
Note: I am not familiar enough with JSMs to know if there's a better way to do this, but this should work.

Is it possible to sandbox JavaScript running in the browser?

I'm wondering if it's possible to sandbox JavaScript running in the browser to prevent access to features that are normally available to JavaScript code running in an HTML page.
For example, let's say I want to provide a JavaScript API for end users to let them define event handlers to be run when "interesting events" happen, but I don't want those users to access the properties and functions of the window object. Am I able to do this?
In the simplest case, let's say I want to prevent users calling alert. A couple of approaches I can think of are:
Redefine window.alert globally. I don't think this would be a valid approach because other code running in the page (i.e., stuff not authored by users in their event handlers) might want to use alert.
Send the event handler code to the server to process. I'm not sure that sending the code to the server to process is the right approach, because the event handlers need to run in the context of the page.
Perhaps a solution where the server processes the user defined function and then generates a callback to be executed on the client would work? Even if that approach works, are there better ways to solve this problem?
Google Caja is a source-to-source translator that "allows you to put untrusted third-party HTML and JavaScript inline in your page and still be secure."
Have a look at Douglas Crockford's ADsafe:
ADsafe makes it safe to put guest code (such as third party scripted advertising or widgets) on any web page. ADsafe defines a subset of JavaScript that is powerful enough to allow guest code to perform valuable interactions, while at the same time preventing malicious or accidental damage or intrusion. The ADsafe subset can be verified mechanically by tools like JSLint so that no human inspection is necessary to review guest code for safety. The ADsafe subset also enforces good coding practices, increasing the likelihood that guest code will run correctly.
You can see an example of how to use ADsafe by looking at the template.html and template.js files in the project's GitHub repository.
I created a sandboxing library called jsandbox that uses web workers to sandbox evaluated code. It also has an input method for explicitly giving sandboxed code data it wouldn't otherwise be able to get.
The following is an example of the API:
jsandbox
.eval({
code : "x=1;Math.round(Math.pow(input, ++x))",
input : 36.565010597564445,
callback: function(n) {
console.log("number: ", n); // number: 1337
}
}).eval({
code : "][];.]\\ (*# ($(! ~",
onerror: function(ex) {
console.log("syntax error: ", ex); // syntax error: [error object]
}
}).eval({
code : '"foo"+input',
input : "bar",
callback: function(str) {
console.log("string: ", str); // string: foobar
}
}).eval({
code : "({q:1, w:2})",
callback: function(obj) {
console.log("object: ", obj); // object: object q=1 w=2
}
}).eval({
code : "[1, 2, 3].concat(input)",
input : [4, 5, 6],
callback: function(arr) {
console.log("array: ", arr); // array: [1, 2, 3, 4, 5, 6]
}
}).eval({
code : "function x(z){this.y=z;};new x(input)",
input : 4,
callback: function(x) {
console.log("new x: ", x); // new x: object y=4
}
});
An improved version of RyanOHara's web workers sandbox code, in a single file (no extra eval.js file is necessary).
function safeEval(untrustedCode)
{
return new Promise(function (resolve, reject)
{
var blobURL = URL.createObjectURL(new Blob([
"(",
function ()
{
var _postMessage = postMessage;
var _addEventListener = addEventListener;
(function (obj)
{
"use strict";
var current = obj;
var keepProperties =
[
// Required
'Object', 'Function', 'Infinity', 'NaN', 'undefined', 'caches', 'TEMPORARY', 'PERSISTENT',
// Optional, but trivial to get back
'Array', 'Boolean', 'Number', 'String', 'Symbol',
// Optional
'Map', 'Math', 'Set',
];
do
{
Object.getOwnPropertyNames(current).forEach(function (name)
{
if (keepProperties.indexOf(name) === -1)
{
delete current[name];
}
});
current = Object.getPrototypeOf(current);
}
while (current !== Object.prototype)
;
})(this);
_addEventListener("message", function (e)
{
var f = new Function("", "return (" + e.data + "\n);");
_postMessage(f());
});
}.toString(),
")()"],
{type: "application/javascript"}));
var worker = new Worker(blobURL);
URL.revokeObjectURL(blobURL);
worker.onmessage = function (evt)
{
worker.terminate();
resolve(evt.data);
};
worker.onerror = function (evt)
{
reject(new Error(evt.message));
};
worker.postMessage(untrustedCode);
setTimeout(function ()
{
worker.terminate();
reject(new Error('The worker timed out.'));
}, 1000);
});
}
Test it:
https://jsfiddle.net/kp0cq6yw/
var promise = safeEval("1+2+3");
promise.then(function (result) {
alert(result);
});
It should output 6 (tested in Chrome and Firefox).
As mentioned in other responces, it's enough to jail the code in a sandboxed iframe (without sending it to the server-side) and communicate with messages.
I would suggest to take a look at a small library I created mostly because of the need to providing some API to the untrusted code, just like as described in the question: there's an opportunity to export the particular set of functions right into the sandbox where the untrusted code runs. And there's also a demo which executes the code submitted by a user in a sandbox:
http://asvd.github.io/jailed/demos/web/console/
I think that js.js is worth mentioning here. It's a JavaScript interpreter written in JavaScript.
It's about 200 times slower than native JavaScript, but its nature makes it a perfect sandbox environment. Another drawback is its size – almost 600 KB, which may be acceptable for desktops in some cases, but not for mobile devices.
All the browser vendors and the HTML5 specification are working towards an actual sandbox property to allow sandboxed iframes -- but it's still limited to iframe granularity.
In general, no degree of regular expressions, etc. can safely sanitise arbitrary user provided JavaScript as it degenerates to the halting problem :-/
An ugly way, but maybe this works for you:
I took all the globals and redefined them in the sandbox scope, as well I added the strict mode so they can't get the global object using an anonymous function.
function construct(constructor, args) {
function F() {
return constructor.apply(this, args);
}
F.prototype = constructor.prototype;
return new F();
}
// Sanboxer
function sandboxcode(string, inject) {
"use strict";
var globals = [];
for (var i in window) {
// <--REMOVE THIS CONDITION
if (i != "console")
// REMOVE THIS CONDITION -->
globals.push(i);
}
globals.push('"use strict";\n'+string);
return construct(Function, globals).apply(inject ? inject : {});
}
sandboxcode('console.log( this, window, top , self, parent, this["jQuery"], (function(){return this;}()));');
// => Object {} undefined undefined undefined undefined undefined undefined
console.log("return of this", sandboxcode('return this;', {window:"sanboxed code"}));
// => Object {window: "sanboxed code"}
https://gist.github.com/alejandrolechuga/9381781
An independent JavaScript interpreter is more likely to yield a robust sandbox than a caged version of the built-in browser implementation.
Ryan has already mentioned js.js, but a more up-to-date project is JS-Interpreter. The documentation covers how to expose various functions to the interpreter, but its scope is otherwise very limited.
As of 2019, vm2 looks like the most popular and most regularly-updated solution to running JavaScript in Node.js. I'm not aware of a front-end solution.
With NISP you'll be able to do sandboxed evaluation.
Though the expression you write is not exactly JavaScript code, instead you'll write S-expressions. It is ideal for simple DSLs that doesn't demand extensive programming.
Suppose you have code to execute:
var sCode = "alert(document)";
Now, suppose you want to execute it in a sandbox:
new Function("window", "with(window){" + sCode + "}")({});
These two lines when executed will fail, because "alert" function is not available from the "sandbox"
And now you want to expose a member of window object with your functionality:
new Function("window", "with(window){" + sCode + "}")({
'alert':function(sString){document.title = sString}
});
Indeed you can add quotes escaping and make other polishing, but I guess the idea is clear.
Where is this user JavaScript code coming from?
There is not much you can do about a user embedding code into your page and then calling it from their browser (see Greasemonkey). It's just something browsers do.
However, if you store the script in a database, then retrieve it and eval() it, then you can clean up the script before it is run.
Examples of code that removes all window. and document. references:
eval(
unsafeUserScript
.replace(/\/\/.+\n|\/\*.*\*\/, '') // Clear all comments
.replace(/\s(window|document)\s*[\;\)\.]/, '') // Removes window. Or window; or window)
)
This tries to prevent the following from being executed (not tested):
window.location = 'http://example.com';
var w = window;
There are a lot of limitations you would have to apply to the unsafe user script. Unfortunately, there isn't any 'sandbox container' available for JavaScript.
I've been working on a simplistic JavaScript sandbox for letting users build applets for my site. Although I still face some challenges with allowing DOM access (parentNode just won't let me keep things secure =/), my approach was just to redefine the window object with some of its useful/harmless members, and then eval() the user code with this redefined window as the default scope.
My "core" code goes like this... (I'm not showing it entirely ;)
function Sandbox(parent){
this.scope = {
window: {
alert: function(str){
alert("Overriden Alert: " + str);
},
prompt: function(message, defaultValue){
return prompt("Overriden Prompt:" + message, defaultValue);
},
document: null,
.
.
.
.
}
};
this.execute = function(codestring){
// Here some code sanitizing, please
with (this.scope) {
with (window) {
eval(codestring);
}
}
};
}
So, I can instantiate a Sandbox and use its execute() function to get code running. Also, all new declared variables within eval'd code will ultimately bound to the execute() scope, so there will not be clashing names or messing with existing code.
Although global objects will still be accessible, those which should remain unknown to the sandboxed code must be defined as proxies in the Sandbox::scope object.
You can wrap the user's code in a function that redefines forbidden objects as parameters -- these would then be undefined when called:
(function (alert) {
alert ("uh oh!"); // User code
}) ();
Of course, clever attackers can get around this by inspecting the JavaScript DOM and finding a non-overridden object that contains a reference to the window.
Another idea is scanning the user's code using a tool like JSLint. Make sure it's set to have no preset variables (or: only variables you want), and then if any globals are set or accessed do not let the user's script be used. Again, it might be vulnerable to walking the DOM -- objects that the user can construct using literals might have implicit references to the window object that could be accessed to escape the sandbox.

Categories

Resources