And where does the "huge security hole" come from? I certainly hope you're not saying that you trust requests generated by client code...
And where does the "huge security hole" come from? I certainly hope you're not saying that you trust requests generated by client code...
eval'ing a response from a third party essentially runs their code in your context. JSON.parse does not.
Because eval is executing the data it is using the full JS parser. That means that while '{"name":"bill"}' works as expected '{"name": window.location = "myevildownload.com"}' does too.
JSON.parse is built into the language. It enforces strict JSON conformance so you can't end up accidentally having invalid content that won't be parsed by other JSON libraries, and it does not execute data -- it creates the object graph and nothing else. If there's anything that is not valid JSON it fails and has no side effects. When constructing the object graph it uses the real Object and Array constructors, so nothing can be injected that way. When setting properties on objects it sets them directly and does not call setters.
If you use JSON.parse to parse your JSON data, it is not possible for an attacker to either run or inject code in your site.
And it's faster than eval.
not nesseserily , this attack could be easily mitigated if supposed JSON string is first parsed and validated on server. and only then send back to eval() on browser.
so it is therefore not inherently unsafe to use eval() on JSON.
All so that you can save 6 characters of typing to load the JSON less efficiently on the client side.
Of course because people _do_ do this most engines these days preflight calls to eval to see if they can be parsed as a subset of pseude-JSON. Note: this doesn't make it safe, any inject xss is not valid json so will still be a hole, and these preparsers try to bail out quickly so treat only a minimal subset of JSON. In JavaScriptCore (so all webkit browsers other than chrome) you can't have escaped characters in string literals nor any non-ascii characters anywhere.
(You can call eval on a string but it will just return that same string)