CVE-2021-37678 (Python, published 2021-08-12T23:15Z)
Description: value: TensorFlow is an end-to-end open source platform for machine learning. In affected versions TensorFlow and Keras can be tricked to perform arbitrary code execution when deserializing a Keras model from YAML format. The [implementation](https://github.com/tensorflow/tensorflow/blob/460e000de3a83278fb00b61a16d161b1964f15f4/tensorflow/python/keras/saving/model_config.py#L66-L104) uses `yaml.unsafe_load` which can perform arbitrary code execution on the input. Given that YAML format support requires a significant amount of work, we have removed it for now. We have patched the issue in GitHub commit 23d6383eb6c14084a8fc3bdf164043b974818012. The fix will be included in TensorFlow 2.6.0. We will also cherrypick this commit on TensorFlow 2.5.1, TensorFlow 2.4.3, and TensorFlow 2.3.4, as these are also affected and still in supported range.
Severity: MEDIUM (CVSS v3 base score: 8.8)
Weakness: CWE-502 \u2014 Deserialization of Untrusted Data
The product deserializes untrusted data without sufficiently verifying that the resulting data will be valid.
Repository: https://github.com/tensorflow/tensorflow
Files changed:
RELEASE.md
tensorflow/python/keras/engine/functional.py
tensorflow/python/keras/engine/functional_test.py
tensorflow/python/keras/engine/training.py
tensorflow/python/keras/saving/model_config.py
Commit message: Use the safer `safe_load` function instead of `unsafe_load` when possible

There is no need to open ourselves up to arbitrary code execution, especially since this is not in a performance critical loop, so we can take the slowdown due to safety.

PiperOrigin-RevId: 388501098
Change-Id: I3434318a5e07a798490533b554f46752397837e5


Vulnerable code:
  - Serialization (`model.get_config()/from_config`, `model.to_json()/to_yaml()`
try:
  import yaml  # pylint:disable=g-import-not-at-top
except ImportError:
  yaml = None

      if yaml is not None:
        yaml_str = model.to_yaml()
        models.model_from_yaml(yaml_str)

    if yaml is not None:
      yaml_str = model.to_yaml()
      models.model_from_yaml(yaml_str)


try:
  import yaml
except ImportError:
  yaml = None
        ImportError: if yaml module is not found.
    if yaml is None:
      raise ImportError(
          'Requires yaml module installed (`pip install pyyaml`).')
    return yaml.dump(self._updated_config(), **kwargs)
# pylint: disable=g-import-not-at-top
try:
  import yaml
except ImportError:
  yaml = None
# pylint: enable=g-import-not-at-top

 
  Usage:

  >>> model = tf.keras.Sequential([
  ...     tf.keras.layers.Dense(5, input_shape=(3,)),
  ...     tf.keras.layers.Softmax()])
  >>> try:
  ...   import yaml
  ...   config = model.to_yaml()
  ...   loaded_model = tf.keras.models.model_from_yaml(config)
  ... except ImportError:
  ...   pass
      ImportError: if yaml module is not found.
  if yaml is None:
    raise ImportError('Requires yaml module installed (`pip install pyyaml`).')
  # The method unsafe_load only exists in PyYAML 5.x+, so which branch of the
  # try block is covered by tests depends on the installed version of PyYAML.
  try:
    # PyYAML 5.x+
    config = yaml.unsafe_load(yaml_string)
  except AttributeError:
    config = yaml.load(yaml_string)
  from tensorflow.python.keras.layers import deserialize  # pylint: disable=g-import-not-at-top
  return deserialize(config, custom_objects=custom_objects)

Fixed code:
  * The methods `Model.to_yaml()` and `keras.models.model_from_yaml` have been
    replaced to raise a `RuntimeError` as they can be abused to cause arbitrary
    code execution. It is recommended to use JSON serialization instead of YAML,
    or, a better alternative, serialize to H5.
  - Serialization (`model.get_config()/from_config`, `model.to_json()`
    Note: Since TF 2.6, this method is no longer supported and will raise a
    RuntimeError.

        RuntimeError: announces that the method poses a security risk
    raise RuntimeError(
        'Method `model.to_yaml()` has been removed due to security risk of '
        'arbitrary code execution. Please use `model.to_json()` instead.'
    )

  Note: Since TF 2.6, this method is no longer supported and will raise a
  RuntimeError.
      RuntimeError: announces that the method poses a security risk
  raise RuntimeError(
      'Method `model_from_yaml()` has been removed due to security risk of '
      'arbitrary code execution. Please use `Model.to_json()` and '
      '`model_from_json()` instead.'
  )