Json access from different domain - clarification? - javascript

(I already know that ajax calls has to be from the same origin , and already read the relevant answers)
But I have a problem understanding something :
Facebook (among others) use the for(;;) || while(1) thing in their json responses :
And - obviously - if I want to use the data I have to remove the for(;;) string and then parse it myself.
I was also told (by #esailija) that :
You can't remove the for loop unless you are from same origin that's the point
Ok great - this is because of the same origin policy.
But I ask this :
Lets say John is doing this on his site (john.com):
bla bla...
<script src="facebook.com/ajax/recent" type="text/javascript"></script>
bla bla...
Notice its the same url as facebook's ( my left most red arrow) -
Assumption
If he get the response via <scrip>...</script> and the response was without for(;;) , - he still can't do nothing with {"__ar:1,....} !
it will has to be padded (like jsonp) with myCallBack({"__ar:1,....});
I mean : It's just like this :
var a=1;
{"__ar:1,....} <--- john can't do nothing with this.
var b=1;
Question :
What am I missing and does my assumptions are correct ?

The problem at the time was that it was not safe to have a noop-looking array literal. E.g. executing code like this:
[1,2,3]
Would actually call the array constructor with those values. Which will be far from harmless as the following example shows:
<script>
Array = function() {
//Steal the values etc
};
</script>
<script src="facebook.com/yourtimeline.json"></script>
//above has code like [{profile_id}, {},...] which calls the array constructor
//with those values and I have access to them.
If you visited my page on older browser (and I do mean old, as in firefox 2) while logged in on facebook, I could get your data silently in the array constructor if there was no for(;;). But because there is, my page will just loop indefinitely.

If he got the response and (as you said) it didn't have for(;;); at the beginning, then it would be a valid segment of JavaScript code (an object initializer) whose result wasn't stored anywhere. It would run harmlessly. But people protecting their JSON feeds this way don't want them to run harmlessly when being misused like this, so they add this intentional pollution at the beginning so that attempting to misuse them is painful, because it triggers an endless loop.
The typical way to consume a feed with that kind of intentional-pollution at the beginning relies on being on the same origin (or at least, an origin allowed by their CORS policy): You load the feed via ajax as text, strip off the leading for(;;);, and then parse the remainder as JSON.

Your first assumption is wrong, but the second is right.
Eventhough you can't do an AJAX request to a different origin, you can load a script from a different origin. This is how JSONP does a request to a different origin.
The JSONP format is different from JSON just for this reason. It's JSON wrapped in a function call, so that you can use the response. Just as you assume, a JSON response is useless when loaded as a script, as it will just be evaluated and then discarded.
Edit
To keep up with the edits; the first assumption (that the request wouldn't work at all) was removed from the question.

Related

Remove last 3 letters of div (hidde also in browser page source)

this is my HTML
<div id="remove">Username</div>
and this is my JS code
function slice() {
var t = document.getElementById("remove");
t.textContent = t.textContent.slice(0, -3);
}
slice();
Username load from foreach
{foreach from=$last_user item=s}
{$s.date}
{$s.username}
{/foreach}
This code working and remove 3 letter but when right click on browser and look at page sources i can see "Username" !
I need remove three letter because of privacy and security .
something like
*** name or usern ***
Thank for help me !
The only secure way to make sure the client can't see a particular piece of information is to never send it to the client in the first place. Otherwise, there will always be a way for the client to examine the raw payloads of the network requests and figure out the information they aren't supposed to know.
You'll need to fix this on your backend - either hard-code in
<div id="remove">Usern</div>
or, for a more dynamic approach, use a template engine (or whatever's generating the HTML) and look up how to change strings with it. For example, in EJS, if user is an object with a username property, you could do
<div id="remove"><%= user.username.slice(0, -3) %></div>
Changing the content only with client-side JavaScript will not be sufficient, if you wish to keep some things truly private.
With Smarty, you can define a modifier that takes a string and returns all but the last three characters of it.
function smarty_modifier_truncate_three($string)
{
return substr($string, 0, -3);
}
and then in your template, replace
{$s.username}
with
{$s.username|truncate_three}
If you want only the first three characters, it's easier because you can use the built-in truncate.
{$s.username|truncate:3}
JS doesn't change the source, it can only change the DOM, so what you can do is to keep the element empty and add a value to it using js, but don't forget that js runs on the client's side so its better here to send the string from the server without the last 3 characters.

How to prevent script injection attacks

Intro
This topic has been the bane of many questions and answers on StackOverflow -and in many other tech-forums; however, most of them are specific to exact conditions and even worse: "over-all" security in script-injection prevention via dev-tools-console, or dev-tools-elements or even address-bar is said to be "impossible" to protect. This question is to address these issues and serve as current and historical reference as technology improves -or new/better methods are discovered to address browser security issues -specifically related to script-injection attacks.
Concerns
There are many ways to either extract -or manipulate information "on the fly"; specifically, it's very easy to intercept information gathered from input -to be transmitted to the server - regardless of SSL/TLS.
intercept example
Have a look here
Regardless of how "crude" it is, one can easily use the principle to fabricate a template to just copy+paste into an eval() in the browser console to do all kinds of nasty things such as:
console.log() intercepted information in transit via XHR
manipulate POST-data, changing user-references such as UUIDs
feed the target-server alternative GET (& post) request information to either relay (or gain) info by inspecting the JS-code, cookies and headers
This kind of attack "seems" trivial to the untrained eye, but when highly dynamic interfaces are in concern, then this quickly becomes a nightmare -waiting to be exploited.
We all know "you can't trust the front-end" and the server should be responsible for security; however - what about the privacy/security of our beloved visitors? Many people create "some quick app" in JavaScript and either do not know (or care) about the back-end security.
Securing the front-end as well as the back-end would prove formidable against an average attacker, and also lighten the server-load (in many cases).
Efforts
Both Google and Facebook have implemented some ways of mitigating these issues, and they work; so it is NOT "impossible", however, they are very specific to their respective platforms and to implement requires the use of entire frameworks plus a lot of work -only to cover the basics.
Regardless of how "ugly" some of these protection mechanisms may appear; the goal is to help (mitigate/prevent) security issues to some degree, making it difficult for an attacker. As everybody knows by now: "you cannot keep a hacker out, you can only discourage their efforts".
Tools & Requirements
The goal is to have a simple set of tools (functions):
these MUST be in plain (vanilla) javascript
together they should NOT exceed a few lines of code (at most 200)
they have to be immutable, preventing "re-capture" by an attacker
these MUST NOT clash with any (popular) JS frameworks, such as React, Angular, etc
does NOT have to be "pretty", but readable at least, "one-liners" welcome
cross-browser compatible, at least to a good percentile
Runtime Reflection / Introspection
This is a way to address some of these concerns, and I don't claim it's "the best" way (at all), it's an attempt.
If one could intercept some "exploitable" functions and methods and see if "the call" (per call) was made from the server that spawned it, or not, then this could prove useful as then we can see if the call came "from thin air" (dev-tools).
If this approach is to be taken, then first we need a function that grabs the call-stack and discard that which is not FUBU (for us by us). If the result of this function is empty, hazaa! - we did not make the call and we can proceed accordingly.
a word or two
In order to make this as short & simple as possible, the following code examples follow DRYKIS principles, which are:
don't repeat yourself, keep it simple
"less code" welcomes the adept
"too much code & comments" scare away everybody
if you can read code - go ahead and make it pretty
With that said, pardon my "short-hand", explanation will follow
first we need some constants and our stack-getter
const MAIN = window;
const VOID = (function(){}()); // paranoid
const HOST = `https://${location.host}`; // if not `https` then ... ?
const stak = function(x,a, e,s,r,h,o)
{
a=(a||''); e=(new Error('.')); s=e.stack.split('\n'); s.shift(); r=[]; h=HOSTPURL; o=['_fake_']; s.forEach((i)=>
{
if(i.indexOf(h)<0){return}; let p,c,f,l,q; q=1; p=i.trim().split(h); c=p[0].split('#').join('').split('at ').join('').trim();
c=c.split(' ')[0];if(!c){c='anon'}; o.forEach((y)=>{if(((c.indexOf(y)==0)||(c.indexOf('.'+y)>0))&&(a.indexOf(y)<0)){q=0}}); if(!q){return};
p=p[1].split(' '); f=p[0]; if(f.indexOf(':')>0){p=f.split(':'); f=p[0]}else{p=p.pop().split(':')}; if(f=='/'){return};
l=p[1]; r[r.length]=([c,f,l]).join(' ');
});
if(!isNaN(x*1)){return r[x]}; return r;
};
After cringing, bare in mind this was written "on the fly" as "proof of concept", yet tested and it works. Edit as you whish.
stak() - short explanation
the only 2 relevant arguments are the 1st 2, the rest is because .. laziness (short answer)
both arguments are optional
if the 1st arg x is a number then e.g. stack(0) returns the 1st item in the log, or undefined
if the 2nd arg a is either a string -or an array then e.g. stack(undefined, "anonymous") allows "anonymous" even though it was "omitted" in o
the rest of the code just parses the stack quickly, this should work in both webkit & gecko -based browsers (chrome & firefox)
the result is an array of strings, each string is a log-entry separated by a single space as function file line
if the domain-name is not found in a log-entry (part of filename before parsing) then it won't be in the result
by default it ignores filename / (exactly) so if you test this code, putting in a separate .js file will yield better results than in index.html (typically) -or whichever web-root mechanism is used
don't worry about _fake_ for now, it's in the jack function below
now we need some tools
bore() - get/set/rip some value of an object by string reference
const bore = function(o,k,v)
{
if(((typeof k)!='string')||(k.trim().length<1)){return}; // invalid
if(v===VOID){return (new Function("a",`return a.${k}`))(o)}; // get
if(v===null){(new Function("a",`delete a.${k}`))(o); return true}; // rip
(new Function("a","z",`a.${k}=z`))(o,v); return true; // set
};
bake() - shorthand to harden existing object properties (or define new ones)
const bake = function(o,k,v)
{
if(!o||!o.hasOwnProperty){return}; if(v==VOID){v=o[k]};
let c={enumerable:false,configurable:false,writable:false,value:v};
let r=true; try{Object.defineProperty(o,k,c);}catch(e){r=false};
return r;
};
bake & bore - rundown
These are failry self-explanatory, so, some quick examples should suffice
using bore to get a property: console.log(bore(window,"XMLHttpRequest.prototype.open"))
using bore to set a property: bore(window,"XMLHttpRequest.prototype.open",function(){return "foo"})
using bore to rip (destroy carelessly): bore(window,"XMLHttpRequest.prototype.open",null)
using bake to harden an existing property: bake(XMLHttpRequest.prototype,'open')
using bake to define a new (hard) property: bake(XMLHttpRequest.prototype,'bark',function(){return "woof!"})
intercepting functions and constructions
Now we can use all the above to our advantage as we devise a simple yet effective interceptor, by no means "perfect", but it should suffice; explanation follows:
const jack = function(k,v)
{
if(((typeof k)!='string')||!k.trim()){return}; // invalid reference
if(!!v&&((typeof v)!='function')){return}; // invalid callback func
if(!v){return this[k]}; // return existing definition, or undefined
if(k in this){this[k].list[(this[k].list.length)]=v; return}; //add
let h,n; h=k.split('.'); n=h.pop(); h=h.join('.'); // name & holder
this[k]={func:bore(MAIN,k),list:[v]}; // define new callback object
bore(MAIN,k,null); let f={[`_fake_${k}`]:function()
{
let r,j,a,z,q; j='_fake_'; r=stak(0,j); r=(r||'').split(' ')[0];
if(!r.startsWith(j)&&(r.indexOf(`.${j}`)<0)){fail(`:(`);return};
r=jack((r.split(j).pop())); a=([].slice.call(arguments));
for(let p in r.list)
{
if(!r.list.hasOwnProperty(p)||q){continue}; let i,x;
i=r.list[p].toString(); x=(new Function("y",`return {[y]:${i}}[y];`))(j);
q=x.apply(r,a); if(q==VOID){return}; if(!Array.isArray(q)){q=[q]};
z=r.func.apply(this,q);
};
return z;
}}[`_fake_${k}`];
bake(f,'name',`_fake_${k}`); bake((h?bore(MAIN,h):MAIN),n,f);
try{bore(MAIN,k).prototype=Object.create(this[k].func.prototype)}
catch(e){};
}.bind({});
jack() - explanation
it takes 2 arguments, the first as string (used to bore), the second is used as interceptor (function)
the first few comments explain a bit .. the "add" line simply adds another interceptor to the same reference
jack deposes an existing function, stows it away, then use "interceptor-functions" to replay arguments
the interceptors can either return undefined or a value, if no value is returned from any, the original function is not called
the first value returned by an interceptor is used as argument(s) to call the original and return is result to the caller/invoker
that fail(":(") is intentional; an error will be thrown if you don't have that function - only if the jack() failed.
Examples
Let's prevent eval from being used in the console -or address-bar
jack("eval",function(a){if(stak(0)){return a}; alert("having fun?")});
extensibility
If you want a DRY-er way to interface with jack, the following is tested and works well:
const hijack = function(l,f)
{
if(Array.isArray(l)){l.forEach((i)=>{jack(i,f)});return};
};
Now you can intercept in bulk, like this:
hijack(['eval','XMLHttpRequest.prototype.open'],function()
{if(stak(0)){return ([].slice.call(arguments))}; alert("gotcha!")});
A clever attacker may then use the Elements (dev-tool) to modify an attribute of some element, giving it some onclick event, then our interceptor won't catch that; however, we can use a mutation-observer and with that spy on "attribute changes". Upon attribute-change (or new-node) we can check if changes were made FUBU (or not) with our stak() check:
const watchDog=(new MutationObserver(function(l)
{
if(!stak(0)){alert("you again! :D");return};
}));
watchDog.observe(document.documentElement,{childList:true,subtree:true,attributes:true});
Conclusion
These were but a few ways of dealing with a bad problem; though I hope someone finds this useful, and please feel free to edit this answer, or post more (or alternative/better) ways of improving front-end security.

"Fixing" JSON coming out of MySQL

I'm fetching JSON code stored in MySQL and it has extra slashes, which I have to remove in order to parse it in JavaScript, after I print it on the page. Right now I'm doing the following:
$save = str_replace("\n", "<br>", $save); // Replace new line characters with <br>
$save = str_replace('\\"', '"', $save); // top-level JSON
$save = str_replace('\\\\"', '\"', $save); // HTML inside top level JSON
$save = str_replace('\\\\\\\\\\"', '\\\\\"', $save); // HTML inside second level JSON
Here is an example JSON code, as it comes out from MySQL:
{\"id\":2335,\"editor\":{\"selected_shape\":\"spot-7488\"},\"general\":{\"name\":\"HTML Test\",\"shortcode\":\"html-test\",\"width\":1280,\"height\":776},\"spots\":[{\"id\":\"spot-7488\",\"x\":9.9,\"y\":22.6,\"default_style\":{\"use_icon\":1},\"tooltip_content\":{\"content_type\":\"content-builder\",\"plain_text\":\"<p class=\\\"test\\\">Test</p>\",\"squares_json\":\"{\\\"containers\\\":[{\\\"id\\\":\\\"sq-container-293021\\\",\\\"settings\\\":{\\\"elements\\\":[{\\\"settings\\\":{\\\"name\\\":\\\"Paragraph\\\",\\\"iconClass\\\":\\\"fa fa-paragraph\\\"},\\\"options\\\":{\\\"text\\\":{\\\"text\\\":\\\"<p class=\\\\\\\"test\\\\\\\">Test</p>\\\"}}}]}}]}\"}}]}
And here is how it's supposed to look in order to get parsed correctly (using jsonlint.com to test):
{"id":2335,"editor":{"selected_shape":"spot-7488"},"general":{"name":"HTML Test","shortcode":"html-test","width":1280,"height":776},"spots":[{"id":"spot-7488","x":9.9,"y":22.6,"default_style":{"use_icon":1},"tooltip_content":{"content_type":"content-builder","plain_text":"<p class=\"test\">Test</p>","squares_json":"{\"containers\":[{\"id\":\"sq-container-293021\",\"settings\":{\"elements\":[{\"settings\":{\"name\":\"Paragraph\",\"iconClass\":\"fa fa-paragraph\"},\"options\":{\"text\":{\"text\":\"<p class=\\\"test\\\">Test</p>\"}}}]}}]}"}}]}
Please note that I have HTML code inside JSON, which is inside another JSON and this is where it gets a bit messy.
My question - is there a function or library for PHP (for JS will work too) which covers all those corner cases, because I'm sure someone will find a way to break the script.
Thanks!
The short answer, which is woefully inadequate, is for you to use stripslashes. The reason this answer is not adequate is that your JSON string might have been escaped or had addslashes called on it multiple times and you would have to call stripslashes precisely once for each time this had happened.
The proper solution is to find out where the slashes are being added and either a) avoid adding the slashes or b) understand why the slashes are there and respond accordingly. I strongly believe that the process that creates that broken JSON is where the problem lies.
Slashes are typically added in PHP in a few cases:
magic_quotes are turned on. This is an old PHP feature which has been removed. The basic idea is that PHP used to auto-escape quotes in incoming requests to let you just cram incoming strings into a db. Guess what? NOT SAFE.
add_slashes has been called. Why call this? Some folks use it as an incorrect means of escaping data before sticking stuff in a db. Others use it to keep HTML from breaking when echoing variables out (htmlspecialchars should probably be used instead). It can also come in handy in a variety of other meta situations when you are defining code in a string.
When escaping data input. The most common escaping function is mysqli_real_escape_string. It's very important to escape values before inserting them in a db to prevent sql injection and other exploits but you should never escape things twice.
So there's a possibility that your code is double-escaping things or that addslashes is getting called or something like magic_quotes is causing the problem, but I suspect it is another problem: some JS code might be supplying this JSON not as a proper JSON string, but one that has been escaped so to define a string within javascript.
If you take your example JSON string above, and slap some quotes around it:
var myJSON = "<put your string here>";
then SURPRISE your javascript is not broken and the var myJSON contains a string that is actually valid JSON and can be parsed into an a valid JSON object:
var myJSON = "{\"id\":2335,\"editor\":{\"selected_shape\":\"spot-7488\"},\"general\":{\"name\":\"HTML Test\",\"shortcode\":\"html-test\",\"width\":1280,\"height\":776},\"spots\":[{\"id\":\"spot-7488\",\"x\":9.9,\"y\":22.6,\"default_style\":{\"use_icon\":1},\"tooltip_content\":{\"content_type\":\"content-builder\",\"plain_text\":\"<p class=\\\"test\\\">Test</p>\",\"squares_json\":\"{\\\"containers\\\":[{\\\"id\\\":\\\"sq-container-293021\\\",\\\"settings\\\":{\\\"elements\\\":[{\\\"settings\\\":{\\\"name\\\":\\\"Paragraph\\\",\\\"iconClass\\\":\\\"fa fa-paragraph\\\"},\\\"options\\\":{\\\"text\\\":{\\\"text\\\":\\\"<p class=\\\\\\\"test\\\\\\\">Test</p>\\\"}}}]}}]}\"}}]}";
console.log(JSON.parse(myJSON)); // this is an actual object
The key here is to examine the point of entry where this JSON arrives in your system. I suspect some AJAX request has created some object and rather than sending valid JSON Of that object, it is sending instead an escaped string of a JSON object.
EDIT:
Here's a simple example of what happens when you have too many encodings. Try running this JS in your browser and observe the console output:
var myObj = {"key":"here is my value"};
console.log(myObj);
var myJSON = JSON.stringify(myObj);
console.log(myJSON);
var doubleEncoded = JSON.stringify(myJSON);
console.log(doubleEncoded);

POST encodeURIComponent query string Internal Server ERROR 500

UPDATE: 2015-03-18 PARTIALLY RESOLVED see comments below
POSTing HTML to server, via a pure javascript (AJAX)request, NOT USING AJAX library.
Can someone tell me why this fails? even though it is encoded?
xmlhttpObj.open("POST", "apage.aspx?name1=value1&name2=%3Cd", true);
Internal Server Error 500 - Failed to Load resource
WIN 7, IIS7, Chrome, pure javascript [Please, no JQuery or others]
This is a javascript xmlhttpRequest open/POST/send(); async(or sync, both fail)
Have made changes to httpRuntimeValidationMode = 2.0 and pages requestValidate = false both in web.config and page directive, all FRAMEWORKs are installed all the way to 4.0
The only portion encoded is the VALUE(%3Cd) of the second name/value pair (name2=%3Cd) - ...encoding the URL portion is worse...
The special character (%3C) is the < char and the d is the first char of the div tag... POSTing HTML to the server.
If no special chars are in that value, it passes(encoded or not) 2061 chars(even though IIS is set for 4096 and those changes are reflected in the web.config)
An angle-bracket(<) alone, passes!? thus 2 chars(%3Cd) are needed to break it.
if this line is plugged in the Broswer URL bar: (note, the C is missing)
http://localhost/sitename/apage.aspx?name1=value1&name2=%3d
effectively skipping the javascript httpRequest, the ResponseText is: "value1="
thus, the first value succeeds, so does the 2nd as 3D is the '=' sign(nasty coincidence-lol, threw me for a loop).
%3Cd - when the C is not removed... '[lessthan]d' equals trouble(duh!).
Yellow Trace screen: A potentially dangerous Request.QueryString value was detected from the client (name2=[lessthan]d). - no mention of Error 500 on Trace page.
Why does it not cancel the validation mechanism?!
...and I thought encoding alone would be needed?!
...and why does it choke at 2061?
Keep in mind same mechanism is used without a hick-up in countless instances, sync and async... no problems as long as 'dangerous' characters are not passed. The '='(3d) example above and the 2061 SUCCESS shows this instance is no different.
I do not post willy-nilly... I will break my head 40 hours before I beg for help, I have read the entire Internet... (sniff sniff)! (t.y.)
...not sure that is the proper or accepted way to do this, but have resolved the issue TEMPORARILY by doing a 'replace' of '<' with a 'unique 3 chars safe string' that I can decode at will... and I believe I will have to do that for other chars that will fail the process.
I would prefer a solid accepted solution.
...and the other associated questions such as queryString length also are not resolved
t.y.

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 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

Categories

Resources