Skip to content

Commit 23d6383

Browse files
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
1 parent e1ec21f commit 23d6383

File tree

5 files changed

+22
-55
lines changed

5 files changed

+22
-55
lines changed

RELEASE.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@
1515
`if x.shape.rank == 1: x = tf.expand_dims(x, axis=-1)`.
1616
Functional models as well as Sequential models built with an explicit
1717
input shape are not affected.
18+
* The methods `Model.to_yaml()` and `keras.models.model_from_yaml` have been
19+
replaced to raise a `RuntimeError` as they can be abused to cause arbitrary
20+
code execution. It is recommended to use JSON serialization instead of YAML,
21+
or, a better alternative, serialize to H5.
1822

1923
* `tf.lite`:
2024
* Rename fields `SignatureDef` table in schema to maximize the parity with

tensorflow/python/keras/engine/functional.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ class Functional(training_lib.Model):
5353
than with subclassed `Model`s, specifically:
5454
5555
- Model cloning (`keras.models.clone`)
56-
- Serialization (`model.get_config()/from_config`, `model.to_json()/to_yaml()`
56+
- Serialization (`model.get_config()/from_config`, `model.to_json()`
5757
- Whole-model saving (`model.save()`)
5858
5959
A `Functional` model can be instantiated by passing two arguments to

tensorflow/python/keras/engine/functional_test.py

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -47,11 +47,6 @@
4747
from tensorflow.python.platform import test
4848
from tensorflow.python.training.tracking.util import Checkpoint
4949

50-
try:
51-
import yaml # pylint:disable=g-import-not-at-top
52-
except ImportError:
53-
yaml = None
54-
5550

5651
class NetworkConstructionTest(keras_parameterized.TestCase):
5752

@@ -627,10 +622,6 @@ def test_multi_input_multi_output_recursion(self):
627622
json_str = model.to_json()
628623
models.model_from_json(json_str)
629624

630-
if yaml is not None:
631-
yaml_str = model.to_yaml()
632-
models.model_from_yaml(yaml_str)
633-
634625
@combinations.generate(combinations.combine(mode=['graph', 'eager']))
635626
def test_invalid_graphs(self):
636627
a = layers.Input(shape=(32,), name='input_a')
@@ -1361,10 +1352,6 @@ def test_constant_initializer_with_numpy(self):
13611352
json_str = model.to_json()
13621353
models.model_from_json(json_str)
13631354

1364-
if yaml is not None:
1365-
yaml_str = model.to_yaml()
1366-
models.model_from_yaml(yaml_str)
1367-
13681355
def test_subclassed_error_if_init_not_called(self):
13691356

13701357
class MyNetwork(training_lib.Model):

tensorflow/python/keras/engine/training.py

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -87,11 +87,6 @@
8787
import h5py
8888
except ImportError:
8989
h5py = None
90-
91-
try:
92-
import yaml
93-
except ImportError:
94-
yaml = None
9590
# pylint: enable=g-import-not-at-top
9691

9792

@@ -2416,6 +2411,9 @@ def to_json(self, **kwargs):
24162411
def to_yaml(self, **kwargs):
24172412
"""Returns a yaml string containing the network configuration.
24182413
2414+
Note: Since TF 2.6, this method is no longer supported and will raise a
2415+
RuntimeError.
2416+
24192417
To load a network from a yaml save file, use
24202418
`keras.models.model_from_yaml(yaml_string, custom_objects={})`.
24212419
@@ -2431,12 +2429,12 @@ def to_yaml(self, **kwargs):
24312429
A YAML string.
24322430
24332431
Raises:
2434-
ImportError: if yaml module is not found.
2432+
RuntimeError: announces that the method poses a security risk
24352433
"""
2436-
if yaml is None:
2437-
raise ImportError(
2438-
'Requires yaml module installed (`pip install pyyaml`).')
2439-
return yaml.dump(self._updated_config(), **kwargs)
2434+
raise RuntimeError(
2435+
'Method `model.to_yaml()` has been removed due to security risk of '
2436+
'arbitrary code execution. Please use `model.to_json()` instead.'
2437+
)
24402438

24412439
def reset_states(self):
24422440
for layer in self.layers:

tensorflow/python/keras/saving/model_config.py

Lines changed: 9 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -18,18 +18,11 @@
1818
from tensorflow.python.keras.saving.saved_model import json_utils
1919
from tensorflow.python.util.tf_export import keras_export
2020

21-
# pylint: disable=g-import-not-at-top
22-
try:
23-
import yaml
24-
except ImportError:
25-
yaml = None
26-
# pylint: enable=g-import-not-at-top
27-
2821

2922
@keras_export('keras.models.model_from_config')
3023
def model_from_config(config, custom_objects=None):
3124
"""Instantiates a Keras model from its config.
32-
25+
3326
Usage:
3427
```
3528
# for a Functional API model
@@ -63,17 +56,8 @@ def model_from_config(config, custom_objects=None):
6356
def model_from_yaml(yaml_string, custom_objects=None):
6457
"""Parses a yaml model configuration file and returns a model instance.
6558
66-
Usage:
67-
68-
>>> model = tf.keras.Sequential([
69-
... tf.keras.layers.Dense(5, input_shape=(3,)),
70-
... tf.keras.layers.Softmax()])
71-
>>> try:
72-
... import yaml
73-
... config = model.to_yaml()
74-
... loaded_model = tf.keras.models.model_from_yaml(config)
75-
... except ImportError:
76-
... pass
59+
Note: Since TF 2.6, this method is no longer supported and will raise a
60+
RuntimeError.
7761
7862
Args:
7963
yaml_string: YAML string or open file encoding a model configuration.
@@ -85,19 +69,13 @@ def model_from_yaml(yaml_string, custom_objects=None):
8569
A Keras model instance (uncompiled).
8670
8771
Raises:
88-
ImportError: if yaml module is not found.
72+
RuntimeError: announces that the method poses a security risk
8973
"""
90-
if yaml is None:
91-
raise ImportError('Requires yaml module installed (`pip install pyyaml`).')
92-
# The method unsafe_load only exists in PyYAML 5.x+, so which branch of the
93-
# try block is covered by tests depends on the installed version of PyYAML.
94-
try:
95-
# PyYAML 5.x+
96-
config = yaml.unsafe_load(yaml_string)
97-
except AttributeError:
98-
config = yaml.load(yaml_string)
99-
from tensorflow.python.keras.layers import deserialize # pylint: disable=g-import-not-at-top
100-
return deserialize(config, custom_objects=custom_objects)
74+
raise RuntimeError(
75+
'Method `model_from_yaml()` has been removed due to security risk of '
76+
'arbitrary code execution. Please use `Model.to_json()` and '
77+
'`model_from_json()` instead.'
78+
)
10179

10280

10381
@keras_export('keras.models.model_from_json')

0 commit comments

Comments
 (0)