Repository: PyCQA/bandit
Pull request #707 (2021-04-15 03:53:27)

add jsonpickle deserialization blacklist
add jsonpickle deserialization blacklist

JeremyVriens: Good addition, but this triggered me to look a bit further ahead. What's the requirement/flow for other 3rd party libraries to be added to this static blacklist?
As an example: Pandas, another pretty big 3rd party lib, also has a pandas.read_pickle (https://github.com/pandas-dev/pandas/blob/9d0517a2f9c17377e8a7823e0af7776d3d9a0679/pandas/io/pickle.py#L217) which uses pickle.load. Currently when using pandas.read_pickle inside your code, Bandit won't complain. Should it be also added to the blacklist?
SugarP1g: > Good addition, but this triggered me to look a bit further ahead. What's the requirement/flow for other 3rd party libraries to be added to this static blacklist?
> As an example: Pandas, another pretty big 3rd party lib, also has a pandas.read_pickle (https://github.com/pandas-dev/pandas/blob/9d0517a2f9c17377e8a7823e0af7776d3d9a0679/pandas/io/pickle.py#L217) which uses pickle.load. Currently when using pandas.read_pickle inside your code, Bandit won't complain. Should it be also added to the blacklist?

It's a question about the purpose of bandit. If bandit is desired to find more vulnerability, this check rule should be added.
sigmavirus24: > Good addition, but this triggered me to look a bit further ahead. What's the requirement/flow for other 3rd party libraries to be added to this static blacklist?

I don't know, but I'm pretty sure 3rd party libraries are already covered (I think we have checks for PyYAML). I think what's already covered is based upon what folks using it have needed thus far.

Patch:
diff --git a/bandit/blacklists/calls.py b/bandit/blacklists/calls.py
index c81e1cd..079da90 100644
--- a/bandit/blacklists/calls.py
+++ b/bandit/blacklists/calls.py
@@ -32,6 +32,9 @@ deserialize untrusted data, possible security issue.
 |      |                     | - dill.Unpickler                   |           |
 |      |                     | - shelve.open                      |           |
 |      |                     | - shelve.DbfilenameShelf           |           |
+|      |                     | - jsonpickle.decode                |           |
+|      |                     | - jsonpickle.unpickler.decode      |           |
+|      |                     | - jsonpickle.unpickler.Unpickler   |           |
 +------+---------------------+------------------------------------+-----------+
 
 B302: marshal
@@ -352,6 +355,9 @@ def gen_blacklist():
                 "dill.Unpickler",
                 "shelve.open",
                 "shelve.DbfilenameShelf",
+                "jsonpickle.decode",
+                "jsonpickle.unpickler.decode",
+                "jsonpickle.unpickler.Unpickler",
             ],
             "Pickle and modules that wrap it can be unsafe when used to "
             "deserialize untrusted data, possible security issue.",
diff --git a/examples/jsonpickle.py b/examples/jsonpickle.py
new file mode 100644
index 0000000..e8aa290
--- /dev/null
+++ b/examples/jsonpickle.py
@@ -0,0 +1,10 @@
+import jsonpickle
+
+
+pick = jsonpickle.encode({'a': 'b', 'c': 'd'})
+
+print(jsonpickle.decode(pick))
+
+print(jsonpickle.unpickler.decode(pick))
+
+print(jsonpickle.unpickler.Unpickler().restore(pick))


Test patch:
diff --git a/tests/functional/test_functional.py b/tests/functional/test_functional.py
index 7b83d79..2005d1e 100644
--- a/tests/functional/test_functional.py
+++ b/tests/functional/test_functional.py
@@ -369,6 +369,14 @@ class FunctionalTests(testtools.TestCase):
         }
         self.check_example("shelve_open.py", expect)
 
+    def test_jsonpickle(self):
+        """Test for the `jsonpickle` module."""
+        expect = {
+            "SEVERITY": {"UNDEFINED": 0, "LOW": 0, "MEDIUM": 3, "HIGH": 0},
+            "CONFIDENCE": {"UNDEFINED": 0, "LOW": 0, "MEDIUM": 0, "HIGH": 3},
+        }
+        self.check_example("jsonpickle.py", expect)
+
     def test_popen_wrappers(self):
         """Test the `popen2` and `commands` modules."""
         expect = {