Is using eval() for data from ONLY server-side safe? (and if not, alternatives please)
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 开发者_StackOverflow中文版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.
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.
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.
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.
Code
var result = eval(code);
May change with
var result = new Function('return '+code+');
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
精彩评论