CVE-2022-21797: Insufficient Information (NVD-CWE-noinfo)
value: The package joblib from 0 and before 1.2.0 are vulnerable to Arbitrary Code Execution via the pre_dispatch flag in Parallel() class due to the eval() statement.
CWE description: There is insufficient information about the issue to classify it; details are unkown or unspecified.
CVSS v3 base score: 9.8
Published: 2022-09-26T05:15Z
Repository: https://github.com/joblib/joblib
Language: Python
Files changed: CHANGES.rst, joblib/parallel.py
Commit date: 2022-09-05 15:15:04 +0200
Commit message: FIX make sure pre_dispatch cannot do arbitrary code execution (#1321)


Diff: diff --git a/CHANGES.rst b/CHANGES.rst
index 56c8e76..f74fbde 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -26,10 +26,14 @@ Development version
   buffer of a numpy array, for instance C/C++/Cython code compiled
   with older GCC versions or some old OpenBLAS written in platform
   specific assembly.
   https://github.com/joblib/joblib/pull/1254
 
+- Fix a security issue where ``eval(pre_dispatch)`` could potentially run
+  arbitrary code. Now only basic numerics are supported.
+  https://github.com/joblib/joblib/pull/1321
+
 Release 1.1.0
 --------------
 
 - Fix byte order inconsistency issue during deserialization using joblib.load
   in cross-endian environment: the numpy arrays are now always loaded to
diff --git a/joblib/parallel.py b/joblib/parallel.py
index f9c8454..1c2fe18 100644
--- a/joblib/parallel.py
+++ b/joblib/parallel.py
@@ -502,11 +502,13 @@ class Parallel(Logger):
             Timeout limit for each task to complete.  If any task takes longer
             a TimeOutError will be raised. Only applied when n_jobs != 1
         pre_dispatch: {'all', integer, or expression, as in '3*n_jobs'}
             The number of batches (of tasks) to be pre-dispatched.
             Default is '2*n_jobs'. When batch_size="auto" this is reasonable
-            default and the workers should never starve.
+            default and the workers should never starve. Note that only basic
+            arithmetics are allowed here and no modules can be used in this
+            expression.
         batch_size: int or 'auto', default: 'auto'
             The number of atomic tasks to dispatch at once to each
             worker. When individual evaluations are very fast, dispatching
             calls to workers can be slower than sequential computation because
             of the overhead. Batching fast computations together can mitigate
@@ -1047,11 +1049,15 @@ class Parallel(Logger):
             self._original_iterator = None
             self._pre_dispatch_amount = 0
         else:
             self._original_iterator = iterator
             if hasattr(pre_dispatch, 'endswith'):
-                pre_dispatch = eval(pre_dispatch)
+                pre_dispatch = eval(
+                    pre_dispatch,
+                    {"n_jobs": n_jobs, "__builtins__": {}},  # globals
+                    {}  # locals
+                )
             self._pre_dispatch_amount = pre_dispatch = int(pre_dispatch)
 
             # The main thread will consume the first pre_dispatch items and
             # the remaining items will later be lazily dispatched by async
             # callbacks upon task completions.

Vulnerable code:             default and the workers should never starve.
                pre_dispatch = eval(pre_dispatch)
Fixed code: - Fix a security issue where ``eval(pre_dispatch)`` could potentially run
  arbitrary code. Now only basic numerics are supported.
  https://github.com/joblib/joblib/pull/1321

            default and the workers should never starve. Note that only basic
            arithmetics are allowed here and no modules can be used in this
            expression.
                pre_dispatch = eval(
                    pre_dispatch,
                    {"n_jobs": n_jobs, "__builtins__": {}},  # globals
                    {}  # locals
                )