CVE-2021-41228 (Python, published 2021-11-05T23:15Z)
Description: value: TensorFlow is an open source platform for machine learning. In affected versions TensorFlow's `saved_model_cli` tool is vulnerable to a code injection as it calls `eval` on user supplied strings. This can be used by attackers to run arbitrary code on the plaform where the CLI tool runs. However, given that the tool is always run manually, the impact of this is not severe. We have patched this by adding a `safe` flag which defaults to `True` and an explicit warning for users. The fix will be included in TensorFlow 2.7.0. We will also cherrypick this commit on TensorFlow 2.6.1, TensorFlow 2.5.2, and TensorFlow 2.4.4, as these are also affected and still in supported range.
Severity: MEDIUM (CVSS v3 base score: 7.8)
Weakness: CWE-94 \u2014 Improper Control of Generation of Code ('Code Injection')
The product constructs all or part of a code segment using externally-influenced input from an upstream component, but it does not neutralize or incorrectly neutralizes special elements that could modify the syntax or behavior of the intended code segment.
Repository: https://github.com/tensorflow/tensorflow
Files changed:
RELEASE.md
tensorflow/python/tools/saved_model_cli.py
tensorflow/python/tools/saved_model_cli_test.py
Commit message: Remove use of `eval` when evaluating the input example.

Use `ast.eval_literal` instead which safely evaluates the expression.

PiperOrigin-RevId: 400012249
Change-Id: I5ff98608ea2d736d093aa488af723ff4f6707e02


Vulnerable code:
def preprocess_input_exprs_arg_string(input_exprs_str):
    Each input is separated by semicolon. For each input key:
    # ast.literal_eval does not work with numpy expressions
    input_dict[input_key] = eval(expr)  # pylint: disable=eval-used
  input_exprs = preprocess_input_exprs_arg_string(input_exprs_str)
         'numpy module is available as \'np\'. '
         'Will override duplicate input keys from --inputs option.')
        input_expr_str)
    with self.assertRaises(RuntimeError):
      saved_model_cli.preprocess_input_exprs_arg_string(input_str)

Fixed code:
    *   The saved_model_cli's `--input_examples` inputs are now restricted to
        python literals to avoid code injection.
import ast
def preprocess_input_exprs_arg_string(input_exprs_str, safe=True):
      Each input is separated by semicolon. For each input key:
    safe: Whether to evaluate the python expression as literals or allow
      arbitrary calls (e.g. numpy usage).
    if safe:
      try:
        input_dict[input_key] = ast.literal_eval(expr)
      except:
        raise RuntimeError(
            f'Expression "{expr}" is not a valid python literal.')
    else:
      # ast.literal_eval does not work with numpy expressions
      input_dict[input_key] = eval(expr)  # pylint: disable=eval-used
  input_exprs = preprocess_input_exprs_arg_string(input_exprs_str, safe=False)
         'numpy module is available as \'np\'. Please note that the expression '
         'will be evaluated as-is, and is susceptible to code injection. '
         'When this is set, the value will override duplicate input keys from '
         '--inputs option.')
        input_expr_str, safe=False)
  def testInputPreprocessExampleWithCodeInjection(self):
    input_examples_str = 'inputs=os.system("echo hacked")'
    with self.assertRaisesRegex(RuntimeError, 'not a valid python literal.'):
      saved_model_cli.preprocess_input_examples_arg_string(input_examples_str)

    with self.assertRaisesRegex(RuntimeError, 'format is incorrect'):
      saved_model_cli.preprocess_input_exprs_arg_string(input_str, safe=False)