478

The reason for this "escapes" me.

JSON escapes the forward slash, so a hash {a: "a/b/c"} is serialized as {"a":"a\/b\/c"} instead of {"a":"a/b/c"}.

Why?

5
  • 4
    FWIW I've never seen forward slashes escaped in JSON, I just noticed it with the Java library at code.google.com/p/json-simple
    – Jason S
    Commented Oct 16, 2009 at 22:29
  • 37
    PHP's json_encode() escapes forward slashes by default, but has the JSON_UNESCAPED_SLASHES option starting from PHP 5.4.0 (March 2012) Commented Jul 1, 2012 at 19:52
  • 12
    Here's a PHP code that will not escape every slash, only in '</': echo str_replace('</', '<\/', json_encode($obj, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
    – rustyx
    Commented Jan 20, 2013 at 13:52
  • Does the code include the '</': or does it start at echo? Because starting at echo fails for me. I simply dont get anything. Yes I replaced my $obj for my variable :)
    – marciokoko
    Commented Jul 8, 2013 at 14:58
  • 1
    JSON doesn't escape or serialize anything... your JSON serializer does. Which one are you using? Commented May 11, 2017 at 16:31

5 Answers 5

370

JSON doesn't require you to do that, it allows you to do that. It also allows you to use "\u0061" for "A", but it's not required, like Harold L points out:

The JSON spec says you CAN escape forward slash, but you don't have to.

Harold L answered Oct 16 '09 at 21:59

Allowing \/ helps when embedding JSON in a <script> tag, which doesn't allow </ inside strings, like Seb points out:

This is because HTML does not allow a string inside a <script> tag to contain </, so in case that substring's there, you should escape every forward slash.

Seb answered Oct 16 '09 at 22:00

Some of Microsoft's ASP.NET Ajax/JSON API's use this loophole to add extra information, e.g., a datetime will be sent as "\/Date(milliseconds)\/". (Yuck)

23
  • 4
    That would be a good thing, escaping just </. Though JSON is not often embedded in script tags anyway.
    – Ruben
    Commented Oct 16, 2009 at 22:20
  • 8
    See this blog post for the rationale for the ASP.NET JSON date format: weblogs.asp.net/bleroy/archive/2008/01/18/dates-and-json.aspx Commented Dec 18, 2011 at 21:51
  • 35
    JSON needs to be replaced because a particular implementation of a JSON serializer outputs some JSON that (while being entirely valid JSON) has some extra characters so it can also be dropped into an HTML script element as a JS literal?! That isn't so much throwing the baby out with the bathwater as throwing the baby out because someone bought him a set of water wings.
    – Quentin
    Commented Jun 1, 2012 at 22:53
  • 31
    What I don't get, is why a JSON serializer would even care where the JSON ends up. On a web page, in an HTTP request, whatever. Let the final renderer do additional encoding, if it needs it.
    – Dan Ross
    Commented Apr 28, 2016 at 5:11
  • 8
    @DanRoss And it can. Escaping / is not required, it is allowed, to ease the use of JSON. If you don't want to escape /, then don't.
    – Andreas
    Commented May 6, 2016 at 20:56
53

The JSON spec says you CAN escape forward slash, but you don't have to. A reverse solidus must be escaped, but you do not need to escape a solidus. Section 9 says

"All characters may be placed within the quotation marks except for the characters that must be escaped: quotation mark (U+0022), reverse solidus (U+005C), and the control characters U+0000 to U+001F."

0
28

PHP escapes forward slashes by default which is probably why this appears so commonly. I suspect it's because embedding the string "</script>" inside a <script> tag is considered unsafe.

Example:

<script>
var searchData = <?= json_encode(['searchTerm' => $_GET['search'], ...]) ?>;
// Do something else with the data...
</script>

Based on this code, an attacker could append this to the page's URL:

?search=</script> <some attack code here>

Which, if PHP's protection was not in place, would produce the following HTML:

<script>
var searchData = {"searchTerm":"</script> <some attack code here>"};
...
</script>

Even though the closing script tag is inside a string, it will cause many (most?) browsers to exit the script tag and interpret the items following as valid HTML.

With PHP's protection in place, it will appear instead like this, which will NOT break out of the script tag:

<script>
var searchData = {"searchTerm":"<\/script> <some attack code here>"};
...
</script>

This functionality can be disabled by passing in the JSON_UNESCAPED_SLASHES flag but most developers will not use this since the original result is already valid JSON.

4
  • 4
    "is considered unsafe" -> it really is unsafe. Exploit: <script>let the = "bodies </script><script>alert("the floor");</script>";</script> Try it, the bodies will alert the floor rather than getting a variable called 'the' with script tags in its value. You can say "then don't embed it in a page", yeah, that's a possible workaround, but a lot of people do this anyway (so let's just make good escape functions because why not) and frankly I understand their point: it would make sense if it were safe to have JSON data with correctly escaped data values in JavaScript.
    – Luc
    Commented Mar 19, 2021 at 13:44
  • 2
    Thanks @Luc - great example of why PHP has opted to escape slashes by default! Functions should be secure by default, and only insecure when you specifically want it that way.
    – Simon E.
    Commented Mar 20, 2021 at 1:12
  • I beg to differ. PHP shouldn't encode forward slashes by default. If a frontend developer want to echo user inputted value into HTML code, he should realize that it is always very dangerous, whether it is inside <script> or inside a <div>; and he should be the one to take a lot of precautions, by using htmlspecialchars(), for example. On the backend, it is perfectly safe to not escape forward slashes.
    – Daniel Wu
    Commented Aug 23, 2023 at 4:01
  • @DanielWu Unfortunately many developers are lazy, which is why “secure by default” is a good strategy. Developers can disable those additional slashes by adding the extra parameter if they understand the consequences. (Also I don’t think htmlspecialchars() will work in this scenario. The slashes are still required.)
    – Simon E.
    Commented Aug 26, 2023 at 0:56
22

I asked the same question some time ago and had to answer it myself. Here's what I came up with:

It seems, my first thought [that it comes from its JavaScript roots] was correct.

'\/' === '/' in JavaScript, and JSON is valid JavaScript. However, why are the other ignored escapes (like \z) not allowed in JSON?

The key for this was reading http://www.cs.tut.fi/~jkorpela/www/revsol.html, followed by http://www.w3.org/TR/html4/appendix/notes.html#h-B.3.2. The feature of the slash escape allows JSON to be embedded in HTML (as SGML) and XML.

2
  • 7
    A structured data payload delivery mechanism should not be tied to language constructs..as this may change in the future...but this might explain the design decisions if there were any of the JSON creators.
    – user656925
    Commented Jun 1, 2012 at 21:11
  • 2
    '\/' === '/' So I don't need to unescape forward slashes when receiving my jsonp?
    – Timmetje
    Commented Feb 7, 2013 at 9:30
1

Yes, some JSON utiltiy libraries do it for various good but mostly legacy reasons. But then they should also offer something like setEscapeForwardSlashAlways method to set this behaviour OFF.

In Java, org.codehaus.jettison.json.JSONObject does offer a method called

setEscapeForwardSlashAlways(boolean escapeForwardSlashAlways)

to switch this default behaviour off.

Not the answer you're looking for? Browse other questions tagged or ask your own question.