Bug 1469999 - Use yaml.safe_load() in taskgraph; r=dustin
authorGregory Szorc <gps@mozilla.com>
Mon, 25 Jun 2018 21:34:30 +0000
changeset 423636 2bfffe75c2784f615e1c578cd4b8a9436e7938e4
parent 423635 987d0ed1d6f9102e0eacde4eba5da592010887d9
child 423637 ccf6afcc59fb11df48974537da7b792266629da8
push id104625
push userebalazs@mozilla.com
push dateTue, 26 Jun 2018 09:25:00 +0000
treeherdermozilla-inbound@f2c0891d9c26 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdustin
bugs1469999
milestone63.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1469999 - Use yaml.safe_load() in taskgraph; r=dustin yaml.load() can evaluate arbitrary Python code via syntax such as `!!python/object/apply:os.system`. Seriously. Let's switch taskgraph to yaml.safe_load(), which is reasonable about limiting magic. Differential Revision: https://phabricator.services.mozilla.com/D1736
taskcluster/taskgraph/config.py
taskcluster/taskgraph/cron/__init__.py
taskcluster/taskgraph/cron/decision.py
taskcluster/taskgraph/generator.py
taskcluster/taskgraph/morph.py
taskcluster/taskgraph/util/docker.py
taskcluster/taskgraph/util/taskcluster.py
taskcluster/taskgraph/util/yaml.py
--- a/taskcluster/taskgraph/config.py
+++ b/taskcluster/taskgraph/config.py
@@ -91,12 +91,12 @@ def validate_graph_config(config):
 
 def load_graph_config(root_dir):
     config_yml = os.path.join(root_dir, "config.yml")
     if not os.path.exists(config_yml):
         raise Exception("Couldn't find taskgraph configuration: {}".format(config_yml))
 
     logger.debug("loading config from `{}`".format(config_yml))
     with open(config_yml) as f:
-        config = yaml.load(f)
+        config = yaml.safe_load(f)
 
     validate_graph_config(config)
     return GraphConfig(config=config, root_dir=root_dir)
--- a/taskcluster/taskgraph/cron/__init__.py
+++ b/taskcluster/taskgraph/cron/__init__.py
@@ -33,17 +33,17 @@ JOB_TYPES = {
     'decision-task': decision.run_decision_task,
 }
 
 logger = logging.getLogger(__name__)
 
 
 def load_jobs(params, root):
     with open(os.path.join(root, '.cron.yml'), 'rb') as f:
-        cron_yml = yaml.load(f)
+        cron_yml = yaml.safe_load(f)
     schema.validate(cron_yml)
 
     # resolve keyed_by fields in each job
     jobs = cron_yml['jobs']
 
     return {j['name']: j for j in jobs}
 
 
--- a/taskcluster/taskgraph/cron/decision.py
+++ b/taskcluster/taskgraph/cron/decision.py
@@ -27,17 +27,17 @@ def run_decision_task(job, params, root)
             arguments=arguments,
             root=root),
     ]
 
 
 def make_decision_task(params, root, symbol, arguments=[], head_rev=None):
     """Generate a basic decision task, based on the root .taskcluster.yml"""
     with open(os.path.join(root, '.taskcluster.yml'), 'rb') as f:
-        taskcluster_yml = yaml.load(f)
+        taskcluster_yml = yaml.safe_load(f)
 
     if not head_rev:
         head_rev = params['head_rev']
 
     slugids = {}
 
     def as_slugid(name):
         # https://github.com/taskcluster/json-e/issues/164
--- a/taskcluster/taskgraph/generator.py
+++ b/taskcluster/taskgraph/generator.py
@@ -77,17 +77,17 @@ class Kind(object):
     def load(cls, root_dir, graph_config, kind_name):
         path = os.path.join(root_dir, kind_name)
         kind_yml = os.path.join(path, 'kind.yml')
         if not os.path.exists(kind_yml):
             raise KindNotFound(kind_yml)
 
         logger.debug("loading kind `{}` from `{}`".format(kind_name, path))
         with open(kind_yml) as f:
-            config = yaml.load(f)
+            config = yaml.safe_load(f)
 
         return cls(kind_name, path, config, graph_config)
 
 
 class TaskGraphGenerator(object):
     """
     The central controller for taskgraph.  This handles all phases of graph
     generation.  The task is generated from all of the kinds defined in
--- a/taskcluster/taskgraph/morph.py
+++ b/taskcluster/taskgraph/morph.py
@@ -186,17 +186,17 @@ class apply_jsone_templates(object):
                     # The following context differs from action tasks
                     'attributes': task.attributes,
                     'label': task.label,
                     'target_tasks': self.target_tasks,
                 }
 
                 template_path = os.path.join(self.template_dir, template + '.yml')
                 with open(template_path) as f:
-                    template = yaml.load(f)
+                    template = yaml.safe_load(f)
                 result = jsone.render(template, context) or {}
                 for attr in ('task', 'attributes'):
                     if attr in result:
                         setattr(task, attr, result[attr])
 
         return taskgraph, label_to_taskid
 
 
--- a/taskcluster/taskgraph/util/docker.py
+++ b/taskcluster/taskgraph/util/docker.py
@@ -258,17 +258,17 @@ def stream_context_tar(topsrcdir, contex
 
 
 @memoize
 def image_paths():
     """Return a map of image name to paths containing their Dockerfile.
     """
     with open(os.path.join(GECKO, 'taskcluster', 'ci', 'docker-image',
                            'kind.yml')) as fh:
-        config = yaml.load(fh)
+        config = yaml.safe_load(fh)
         return {
             k: os.path.join(IMAGE_DIR, v.get('definition', k))
             for k, v in config['jobs'].items()
         }
 
 
 def image_path(name):
     paths = image_paths()
--- a/taskcluster/taskgraph/util/taskcluster.py
+++ b/taskcluster/taskgraph/util/taskcluster.py
@@ -51,17 +51,17 @@ def _do_request(url, **kwargs):
     response.raise_for_status()
     return response
 
 
 def _handle_artifact(path, response):
     if path.endswith('.json'):
         return response.json()
     if path.endswith('.yml'):
-        return yaml.load(response.text)
+        return yaml.safe_load(response.text)
     response.raw.read = functools.partial(response.raw.read,
                                           decode_content=True)
     return response.raw
 
 
 def get_artifact_url(task_id, path, use_proxy=False):
     ARTIFACT_URL = 'https://queue.taskcluster.net/v1/task/{}/artifacts/{}'
     if use_proxy:
--- a/taskcluster/taskgraph/util/yaml.py
+++ b/taskcluster/taskgraph/util/yaml.py
@@ -21,9 +21,9 @@ def load_yaml(path, name, enforce_order=
         with open(filename, "rb") as f:
             for line in f:
                 mo = key_re.match(line)
                 if mo:
                     keys.append(mo.group(1))
             if keys != list(sorted(keys)):
                 raise Exception("keys in {} are not sorted".format(filename))
     with open(filename, "rb") as f:
-        return yaml.load(f)
+        return yaml.safe_load(f)