[Security] Remove ujson package (CVE-2022-31116, CVE-2022-31117, CVE-2021-45958)#1757
[Security] Remove ujson package (CVE-2022-31116, CVE-2022-31117, CVE-2021-45958)#1757kukgini wants to merge 5 commits into
Conversation
Signed-off-by: pstlouis <patrick.st-louis@opsecid.ca>
Signed-off-by: pstlouis <patrick.st-louis@opsecid.ca>
Signed-off-by: pstlouis <patrick.st-louis@opsecid.ca>
The ujson-removal PR replaced `type(msg) != tuple` with `not isinstance(type(msg), tuple)`, which is always True (a class object is never a tuple instance). This caused already-tuple messages to be wrapped again into a nested tuple, breaking handler routing, and contradicted the adjacent comment explaining why isinstance must not be used (it matches NamedTuple). Restore the original semantics in a lint-clean form (`type(msg) is not tuple`), which preserves NamedTuple wrapping behavior. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: kukgini <kukgini@gmail.com>
c018850 to
9362661
Compare
|
This PR picks up the stalled #1676 (remove It also fixes a logic bug the original PR introduced in
|
Pin the exact byte output of JsonSerializer after dropping ujson, since it feeds signing/hashing and must stay byte-stable: key ordering, compact separators, raw-UTF-8 non-ASCII, float repr, int-key coercion, bool/None, and top-level bytes base64 encoding. Also characterise the one known behavioural difference vs ujson: bytes nested inside a container now raise TypeError (the bytes special-case only fires for a top-level value), whereas ujson silently encoded them as UTF-8. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: kukgini <kukgini@gmail.com>
Summary
Removes the
ujsondependency (which has known vulnerabilities CVE-2022-31116, CVE-2022-31117, CVE-2021-45958) and replaces it with the Python standard libraryjsonmodule across serialization, recorder, and zstack code paths.This continues the stalled work from #1676 by @PatStLouis:
main(the previously requested rebase).Ref: https://security.snyk.io/package/pip/ujson
Changes
ujsonfromsetup.py, build scripts, and dev-setup package lists.common/serializers/json_serializer.py: remove thetry: import ujsonbranch; promote the existingOrderedJsonEncoder(stdlibjsonwithsort_keys=True,separators=(',', ':'),ensure_ascii=False) to be the sole encoder, preserving sorted-key / compact output.try: import ujson as json / except ImportError: import jsonfallbacks inrecorder.py,test_recorder.py,stp_zmq/zstack.py, andscripts/test_zmq/.../zstack.pywith a plainimport json.Bug fix beyond #1676
In
plenum/common/channel.py, thelinting errorscommit of #1676 changed:The intent was to silence flake8 E721 (
do not compare types), which the originaltype(msg) != tupletriggers (E721 is not in this repo's.flake8ignore list). However the replacement is alwaysTrue:type(msg)is a class object, and a class object is never an instance oftuple. As a result, messages that were already tuples got wrapped again into a nested tuple — breaking handler routing in_process_sync— and it directly contradicts the adjacent comment explaining whyisinstancemust not be used here (it also matchesNamedTuple).This PR keeps the lint fix but does it correctly:
E721's own message recommends
is/is notfor exact type checks, so this form silences E721 and preserves the original semantics — it is not a revert of the linting fix. Verified with flake8 (--select=E721reports no violation) and againsttuple,NamedTuple,dict,str, andintinputs, where the result matches the original!=behavior in every case:type(msg) != tuple(pre-#1676)not isinstance(type(msg), tuple)(#1676)type(msg) is not tuple(this PR)Notes
pysha3remains out of scope (per discussion in [Security] remove ujson package (CVE-2022-31116, CVE-2022-31117, CVE-2021-45958) #1676).ujsoninstalled, nestedbytesvalues inside a dict were previously encoded as UTF-8 strings; stdlibjsonraisesTypeErrorfor that case. This matches the pre-existing non-ujson fallback behavior, so it is not a new regression, but reviewers may want a byte-compatibility regression test if any signed/hashed payloads carry nested raw bytes.🤖 Generated with Claude Code