When outputting JSON content via Javascript, should I HTML escape on the server or client side?

Escape on the client side only.

The reason to escape on the client side is security: the server's output is the client's input, and so the client should not trust it. If you assume that the input is already escaped, then you potentially open yourself to client attacks via, for example, a malicious reverse-proxy. This is not so different from why you should always validate input on the server side, even if you also include client-side validation.

The reason not to escape on the server side is separation of concerns: the server should not assume that the client intends to render the data as HTML. The server's output should be as media-neutral as possible (given the constraints of JSON and the data structure, of course), so that the client can most easily transform it into whatever format is needed.


For escaping on output:

I suggest reading this XSS Filter Evasion Cheat Sheet.

To prevent user correctly you better not only escape, but also before escaping filter it with an appropriate anti XSS library. Like htmLawed, or HTML Purifier, or any from this thread.

IMHO sanitizing should be done on user inputed data whenever you are going to show it back in web project.

should I escape the content on the server side, or the client side? I.e., should my API return the raw content, and then make it the client Javascript code's responsibility to escape the special characters, or should my API return "safe" content:

It's better to return already escaped, and xss purified content, so:

  1. Take raw data and purify if from xss on server
  2. Escape it
  3. Return to JavaScript

And also, you should notice one important thing, like a load of your site and read/write balance: for example if your client enters data once and you are going to show this data to 1M users, what do you prefer: run protection logic once before write (protect on input) on a million time each read(protect on output)?

If you are going to show like 1K posts on a page and escape each on client, how well will it work on the client's mobile phone? This last one will help you to chose where to protect data on client or on server.