2

I'm creating a website where I'm doing ajax requests to load some dynamic content AFTER I load a static container page. Basically, I need to pass an array of integers to the page from the server, and I'm using jQuery to load data. I am writing the ints inside a tag with a know name, and using eval to read data from it. Here's a sample tag (returned from ajax):

<span runat="server" class="hidden" id="PhotoList" /> with the codebehind list.ForEach(p => { sb.Append(p.ID.ToString() + ","); } ); where sb is a StringBuilder, so the server as a result returns something like:

<span runat="server" class="hidden" id="PhotoList">1,4,5,42,9</span>

I have a variable photoList declared in the javascript, and I call var scriptToEval = "photoList = [" + $("#PhotoList").html() + "];";

eval(scriptToEval);

I am not a master of Javascript and I just want to be sure that this is safe, as there's lots of discussion on whether eval is safe or not. I THINK this is safe (the ones I've pasted is all the code I'm using with eval), but I may have missed a point, so a professional's opinion is important for me. I know why they say eval is dangerous, as it is capable for interpreting any code, malicious or not, but here, I think this way cannot be compromised at all, as the response from the server is completely under my control. Another option would be making ANOTHER ajax call for the variables and load them directly without ajax from the returned array, but thay would sum to two calls, (I already make the load call anyway as it really loads some HTML content from the server) but this way, even though a bit hacky (putting variables into a hidden HTML tag), seems convenient (and ASP.NET also does this for viewstate too after all!).

My focus is on eval anyway, is this perfectly safe, or should I have some security considerations? Javascript experts please.

Can Poyrazoğlu
  • 33,241
  • 48
  • 191
  • 389

5 Answers5

5

If you can be sure that the data is secure, then eval() will be harmless enough.

If you're not so sure, you can use JSON.parse() to take care of it:

var arr = JSON.parse( "[" + $("#PhotoList").html() + "]" );

For browsers that don't support JSON, you can include the json2 library.


Another possibility is to do a split() the loop the items, converting them to numbers from strings.

var arr = $("#PhotoList").html().split(',');

for( var i = 0, len = arr.length; i < len; i++ ) {
    arr[i] = parseInt( arr[i], 10 );
}

EDIT: Since you're using jQuery, if for some reason you really don't want .eval(), then use the jQuery.parseJSON()[docs] method.

var arr = jQuery.parseJSON("[" + $("#PhotoList").html() + "]");

EDIT 2: Another way to do it would be to use .replace(), passing a function as the replace value. This will take care of the iteration for you.

var arr = [];

$("#PhotoList").html().replace(/\d+/g, function( s ) { arr.push( parseInt(s,10) ); });

...so many ways to do it.

user113716
  • 318,772
  • 63
  • 451
  • 440
  • Nice, but I'm trying to avoid extra libraries as much as possible. (using jQuery, and that's it. I wouldn't have used it too but I do lots of ajax and animations so it's practically a-must). Splitting into strings and looping over isn't really necessary, as I trust the data source and guarantee that it will be a comma-seperated integer strings (I am coding the server myself). JSON parse seems to be nice, but browser support is important for me with including least number of libraries possible. – Can Poyrazoğlu Jul 17 '11 at 23:32
  • 1
    I wouldn't suggest using eval at all, it's unnecessary and over time this may create a security risk (if not right now). jquery has jQuery.parseJSON() method which parses a string to json. – Yossi Ben Haim Jul 17 '11 at 23:33
  • 1
    @can poyrazoğlu: If you're using jQuery, then just use the [`jQuery.parseJSON()`](http://api.jquery.com/jQuery.parseJSON/) method. – user113716 Jul 17 '11 at 23:35
  • Ok, didn't know jQuery's that function. Will be looking into it. – Can Poyrazoğlu Jul 17 '11 at 23:42
2

Of course it's not safe. It's quite easy to stop the code using a debugger and change the content of the element or the variables that script uses.

What you have to consider is what you use the data for. If someone changes the data, can it be used to access something that should not be available, or can it be used to corrupt any data on the server?

If changing the data only affects what's shown on the page, then it's not a problem that the data can be changed.

Guffa
  • 687,336
  • 108
  • 737
  • 1,005
  • But how would that be unique to `eval()`? They could do that anyway, right? – user113716 Jul 17 '11 at 23:16
  • @patrick dw: Yes, that is correct. You can't assume that anything that happens in the browser is ever completely safe. – Guffa Jul 17 '11 at 23:22
  • Data is not anything sensitive (as I'm not that dumb to send something sensitive to a client anyway :)), I of course know that anything can be altered on the client side, I am building a photo gallery and the numbers are just the IDs of the photos (which individually are checked for access rights when being sent to client on the server side), so it cannot be used to access sensitive data or anything. In other words, it's just 'user experience' data. – Can Poyrazoğlu Jul 17 '11 at 23:25
1

Safe, yes, assuming your server is secure. Generally the only time you want to truly avoid using eval() is when users are able to add code which other users can see. Like you'd never ever want to use eval() when displaying a forum post, etc. If the code is coming from your server, or if the user's input is only being displayed back to himself/herself, eval() is fine. This is essentially what jsfiddle does.

AlienWebguy
  • 76,997
  • 17
  • 122
  • 145
0

Code

var result = eval(code);

May change with

var result = new Function('return '+code+');
  • just for curiosity, (I really don't know), what does that really change? (i'm using the eval just once for one assignment, it's not re-used) – Can Poyrazoğlu Jul 18 '11 at 12:05
0

While you can use eval in this case, I'd still not recommend it, due to the many subtle bugs and performance issues it can generate. It is almost never a good idea to use eval!

Also, it is just as possible to do what you want without eval:

1 - For setting a global variable, instead of using eval you can use the global scope object. All the following are equivalent if myList is a global variable:

myList = [1,2,3];
window.myList = [1,2,3];
window['myList'] = [1,2,3];

2 - For obtaining the array elements you can use the .split() method from strings:

node.innerHTML.split(',')

3 - If you want to convert a string to a number one of the simple ways is to use the unary + operator:

+"3" // is the number 3
hugomg
  • 68,213
  • 24
  • 160
  • 246