I'm trying to take the result of an Eloquent request and print its results as a JSON response. My application uses Slim and Twig to generate HTML responses, however I'm not sure if I should use Twig to generate JSON.
I know that I can use the built-in PHP function echo json_encode(...) , but this creates a potential XSS vulnerability if my database contains HTML objects. Twig is supposed to be responsible for avoiding my exit accordingly.
I know this question , however, it does not seem to give a corresponding answer. I also know the json_encode filter, but when I do this:
/api/users-json.twig
{ "rows" : {{rows | json_encode}} }
/ api / users:
// Simulate database query results $result = [ "rows" => [ [ "user_name" => "alex", "message" => "grawr!" ], [ "user_name" => "h4xx0r", "message" => "<script>alert('hello, I can execute JS on your website!');</script>" ] ] ]; $app->response->headers->set('Content-Type', 'application/json; charset=utf-8'); $app->render("api/users-json.twig", $result);
The answer looks like this:
{ "rows" : [{"user_name":"alex","message":"grawr!"},{"user_name":"h4xx0r","message":"<script>alert(&
This is not interpreted on the client side without further processing. According to my browser, the content type is correctly set to application/json .
Of course I can: / api / users -json.twig
{ "rows" : {{rows | json_encode | raw}} }
Which gives me the answer:
{ "rows" : [{"user_name":"alex","message":"grawr!"},{"user_name":"h4xx0r","message":"<script>alert('hello, I can execute JS on your website!');<\/script>"}] }
But if I had to display the h4xx0r message in client code, I am open to an XSS attack.
The result, which I think will be βcorrect,β will be:
{ "rows" : [{"user_name":"alex","message":"grawr!"},{"user_name":"h4xx0r","message":"<script>alert('hello, I can execute JS on your website!');<\/script>"}] }
Note that h4xx0r "message" is now escaped, but the response structure as a whole is saved as valid JSON.
I could, of course, skip each line and manually htmlspecialchars each value, and then either echo json_encode or pass it to Twig. But it looks like it should be Twig's responsibility!
Edit: It would seem that PHP filter_var_array , combined with json_encode , is a reasonable alternative to using Twig:
$app->response->headers->set('Content-Type', 'application/json; charset=utf-8'); echo json_encode(filter_var_array($result, FILTER_SANITIZE_SPECIAL_CHARS));
It produces:
{"rows":[{"user_name":"alex","message":"grawr!"},{"user_name":"h4xx0r","message":"<script>alert('hello, I can execute JS on your website!');<\/script>"}]}
But I'm still not sure if this is what βshouldβ do with Twig.
Is there a way to do this with Slim and Twig? Or am I on a completely wrong path, and should I be responsible for my client code (JS) in order to properly avoid the content before rendering?