Skip to content

Commit 3a33d53

Browse files
mihaimaruseacfchollet
authored andcommitted
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
1 parent 433eaa0 commit 3a33d53

File tree

4 files changed

+19
-55
lines changed

4 files changed

+19
-55
lines changed

keras/engine/functional.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ class Functional(training_lib.Model):
4747
than with subclassed `Model`s, specifically:
4848
4949
- Model cloning (`keras.models.clone`)
50-
- Serialization (`model.get_config()/from_config`, `model.to_json()/to_yaml()`
50+
- Serialization (`model.get_config()/from_config`, `model.to_json()`
5151
- Whole-model saving (`model.save()`)
5252
5353
A `Functional` model can be instantiated by passing two arguments to

keras/engine/functional_test.py

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,6 @@
3636
from keras.utils import tf_utils
3737
from tensorflow.python.training.tracking.util import Checkpoint
3838

39-
try:
40-
import yaml # pylint:disable=g-import-not-at-top
41-
except ImportError:
42-
yaml = None
43-
4439

4540
class NetworkConstructionTest(keras_parameterized.TestCase):
4641

@@ -616,10 +611,6 @@ def test_multi_input_multi_output_recursion(self):
616611
json_str = model.to_json()
617612
models.model_from_json(json_str)
618613

619-
if yaml is not None:
620-
yaml_str = model.to_yaml()
621-
models.model_from_yaml(yaml_str)
622-
623614
@combinations.generate(combinations.combine(mode=['graph', 'eager']))
624615
def test_invalid_graphs(self):
625616
a = layers.Input(shape=(32,), name='input_a')
@@ -1350,10 +1341,6 @@ def test_constant_initializer_with_numpy(self):
13501341
json_str = model.to_json()
13511342
models.model_from_json(json_str)
13521343

1353-
if yaml is not None:
1354-
yaml_str = model.to_yaml()
1355-
models.model_from_yaml(yaml_str)
1356-
13571344
def test_subclassed_error_if_init_not_called(self):
13581345

13591346
class MyNetwork(training_lib.Model):

keras/engine/training.py

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -57,11 +57,6 @@
5757
import h5py
5858
except ImportError:
5959
h5py = None
60-
61-
try:
62-
import yaml
63-
except ImportError:
64-
yaml = None
6560
# pylint: enable=g-import-not-at-top
6661

6762

@@ -2427,6 +2422,9 @@ def to_json(self, **kwargs):
24272422
def to_yaml(self, **kwargs):
24282423
"""Returns a yaml string containing the network configuration.
24292424
2425+
Note: Since TF 2.6, this method is no longer supported and will raise a
2426+
RuntimeError.
2427+
24302428
To load a network from a yaml save file, use
24312429
`keras.models.model_from_yaml(yaml_string, custom_objects={})`.
24322430
@@ -2442,12 +2440,13 @@ def to_yaml(self, **kwargs):
24422440
A YAML string.
24432441
24442442
Raises:
2445-
ImportError: if yaml module is not found.
2443+
RuntimeError: announces that the method poses a security risk
2444+
(Use the safer `safe_load` function instead of `unsafe_load` when possible)
24462445
"""
2447-
if yaml is None:
2448-
raise ImportError(
2449-
'Requires yaml module installed (`pip install pyyaml`).')
2450-
return yaml.dump(self._updated_config(), **kwargs)
2446+
raise RuntimeError(
2447+
'Method `model.to_yaml()` has been removed due to security risk of '
2448+
'arbitrary code execution. Please use `model.to_json()` instead.'
2449+
)
24512450

24522451
def reset_states(self):
24532452
for layer in self.layers:

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 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 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)