Is it appropriate to use Twig to generate pure JSON responses?

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" : [{&quot;user_name&quot;:&quot;alex&quot;,&quot;message&quot;:&quot;grawr!&quot;},{&quot;user_name&quot;:&quot;h4xx0r&quot;,&quot;message&quot;:&quot;&lt;script&gt;alert(&#039;hello, I can execute JS on your website!&#039;);&lt;\/script&gt;&quot;}] } 

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":"&lt;script&gt;alert(&#039;hello, I can execute JS on your website!&#039;);&lt;\/script&gt;"}] } 

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":"&#60;script&#62;alert(&#39;hello, I can execute JS on your website!&#39;);&#60;\/script&#62;"}]} 

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?

+6
source share
1 answer

Twig will display any given variable as html code. However, since you want json to encode the result, you need to iterate the data yourself, since Twig does not delve into the array for you.

0
source

All Articles