This question has been asked many times. See here, here and here
Based on the answers in those questions I did some tests and I'm forced to ask the same question again as none of the answers appear to be correct (at-least to me). Please correct me if my understanding of subject is bad.
I'm working on an API for a web app that outputs JSON response. The server side response is handled by json_encode
in PHP. Since, this would be a public API I would want to prevent any XSS due to incorrect client side implementations by a deveopler consuming the API.
For my test I did the following on server side:
header("Content-Type: application/json", true);
$bad = array('bad_key' => 'alert("hi");');
echo json_encode($bad);
On client side I'm using jQuery AJAX that automatically parses the JSON recieved. Initially this did not appear to show any XSS issue. Then I passed response.bad_key
to eval()
.
eval(response.bad_key);
This immediately resulted in execution of string in bad_key
. I'm aware that use of eval
is bad and should be avoided. However, that's something that I know and cannot ensure the other developer follows the same practice. To avoid such scenarios a solution would be to perform server side encoding. For this let's say I use htmlspecialchars
.
header("Content-Type: application/json", true);
$bad = array('bad_key' => htmlspecialchars('alert("hi");'));
echo json_encode($bad);
This, though it does not execute alert("hi");
client-side but breaks the JS code due to presence of &
. json_encode
with the option JSON_HEX_QUOT|JSON_HEX_TAG|JSON_HEX_AMP|JSON_HEX_APOS
as suggested here does not help either.
So how do I prevent XSS in such a scenario?