Rename escape_slash in script_safe and also escape E+2028 and E+2029

It is rather common to directly interpolate JSON string inside
<script> tags in HTML as to provide configuration or parameters to a
script.

However this may lead to XSS vulnerabilities, to prevent that 3
characters need to be escaped:

  - `/` (forward slash)
  - `U+2028` (LINE SEPARATOR)
  - `U+2029` (PARAGRAPH SEPARATOR)

The forward slash need to be escaped to prevent closing the script
tag early, and the other two are valid JSON but invalid Javascript
and can be used to break JS parsing.

Given that the intent of escaping forward slash is the same than escaping
U+2028 and U+2029, I chos to rename and repurpose the existing `escape_slash`
option.
This commit is contained in:
Jean Boussier 2023-04-13 19:22:29 +02:00 committed by Hiroshi SHIBATA
parent 698cb84062
commit 0dfeb17296
No known key found for this signature in database
GPG key ID: F9CF13417264FAC2
5 changed files with 74 additions and 29 deletions

View file

@ -149,7 +149,7 @@ EOT
:ascii_only => false,
:buffer_initial_length => 1024,
:depth => 0,
:escape_slash => false,
:script_safe => false,
:indent => " ",
:max_nesting => 100,
:object_nl => "\n",
@ -166,7 +166,7 @@ EOT
:ascii_only => false,
:buffer_initial_length => 1024,
:depth => 0,
:escape_slash => false,
:script_safe => false,
:indent => "",
:max_nesting => 100,
:object_nl => "",
@ -183,7 +183,7 @@ EOT
:ascii_only => false,
:buffer_initial_length => 1024,
:depth => 0,
:escape_slash => false,
:script_safe => false,
:indent => "",
:max_nesting => 0,
:object_nl => "",
@ -370,6 +370,18 @@ EOT
#
data = [ '/' ]
json = '["\/"]'
assert_equal json, generate(data, :script_safe => true)
#
data = [ "\u2028\u2029" ]
json = '["\u2028\u2029"]'
assert_equal json, generate(data, :script_safe => true)
#
data = [ "ABC \u2028 DEF \u2029 GHI" ]
json = '["ABC \u2028 DEF \u2029 GHI"]'
assert_equal json, generate(data, :script_safe => true)
#
data = [ "/\u2028\u2029" ]
json = '["\/\u2028\u2029"]'
assert_equal json, generate(data, :escape_slash => true)
#
data = ['"']