-
-
Notifications
You must be signed in to change notification settings - Fork 2.6k
Safe JSON #4196
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Safe JSON #4196
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -57,6 +57,25 @@ def coerce_to_strict(const): | |
return const | ||
|
||
|
||
_swap_json = ( | ||
("<", "\\u003c"), | ||
(">", "\\u003e"), | ||
("/", "\\u002f"), | ||
) | ||
_swap_orjson = _swap_json + ( | ||
("\u2028", "\\u2028"), | ||
("\u2029", "\\u2029"), | ||
) | ||
|
||
|
||
def _safe(json_str, _swap): | ||
out = json_str | ||
for unsafe_char, safe_char in _swap: | ||
if unsafe_char in out: | ||
out = out.replace(unsafe_char, safe_char) | ||
Comment on lines
+74
to
+75
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Testing first whether the character is present in the string is substantially faster than |
||
return out | ||
|
||
|
||
def to_json_plotly(plotly_object, pretty=False, engine=None): | ||
""" | ||
Convert a plotly/Dash object to a JSON string representation | ||
|
@@ -120,7 +139,9 @@ def to_json_plotly(plotly_object, pretty=False, engine=None): | |
|
||
from _plotly_utils.utils import PlotlyJSONEncoder | ||
|
||
return json.dumps(plotly_object, cls=PlotlyJSONEncoder, **opts) | ||
return _safe( | ||
json.dumps(plotly_object, cls=PlotlyJSONEncoder, **opts), _swap_json | ||
) | ||
elif engine == "orjson": | ||
JsonConfig.validate_orjson() | ||
opts = orjson.OPT_NON_STR_KEYS | orjson.OPT_SERIALIZE_NUMPY | ||
|
@@ -136,7 +157,9 @@ def to_json_plotly(plotly_object, pretty=False, engine=None): | |
|
||
# Try without cleaning | ||
try: | ||
return orjson.dumps(plotly_object, option=opts).decode("utf8") | ||
return _safe( | ||
orjson.dumps(plotly_object, option=opts).decode("utf8"), _swap_orjson | ||
) | ||
except TypeError: | ||
pass | ||
|
||
|
@@ -146,7 +169,7 @@ def to_json_plotly(plotly_object, pretty=False, engine=None): | |
datetime_allowed=True, | ||
modules=modules, | ||
) | ||
return orjson.dumps(cleaned, option=opts).decode("utf8") | ||
return _safe(orjson.dumps(cleaned, option=opts).decode("utf8"), _swap_orjson) | ||
|
||
|
||
def to_json(fig, validate=True, pretty=False, remove_uids=True, engine=None): | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,3 +19,4 @@ matplotlib==2.2.3 | |
scikit-image==0.14.4 | ||
psutil==5.7.0 | ||
kaleido | ||
orjson==3.8.12 |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,3 +19,4 @@ matplotlib==2.2.3 | |
scikit-image==0.18.1 | ||
psutil==5.7.0 | ||
kaleido | ||
orjson==3.8.12 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I added |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These are apparently JavaScript line terminator characters. The JS parser will see this end-of-line, see that the data structure is incomplete, and throw an error. AFAICT this isn't in itself a security issue, but it's a bug - if you ever wanted these characters in your figure for real it wouldn't work (when inserted in HTML).
The standard library
json
converts at least these unicode characters into escape sequences anyway, so we don't need to worry about them, butorjson
sends them as unicode characters.