Use safe constructor in yaml deserialization
diff --git a/heron/common/src/java/org/apache/heron/common/config/ConfigReader.java b/heron/common/src/java/org/apache/heron/common/config/ConfigReader.java
index cb0a3ca..a17c72f 100644
--- a/heron/common/src/java/org/apache/heron/common/config/ConfigReader.java
+++ b/heron/common/src/java/org/apache/heron/common/config/ConfigReader.java
@@ -32,6 +32,7 @@
 import java.util.logging.Logger;
 
 import org.yaml.snakeyaml.Yaml;
+import org.yaml.snakeyaml.constructor.SafeConstructor;
 
 /**
  * Loads config file in Yaml file format.
@@ -79,7 +80,7 @@
       try {
         FileInputStream fin = new FileInputStream(new File(fileName));
         try {
-          Yaml yaml = new Yaml();
+          Yaml yaml = new Yaml(new SafeConstructor());
           propsYaml = (Map<String, Object>) yaml.load(fin);
           LOG.log(Level.FINE, "Successfully read config file {0}", fileName);
         } finally {
@@ -104,7 +105,7 @@
   public static Map<String, Object> loadStream(InputStream inputStream) {
     LOG.fine("Reading config stream");
 
-    Yaml yaml = new Yaml();
+    Yaml yaml = new Yaml(new SafeConstructor());
     Map<Object, Object> propsYaml = (Map<Object, Object>) yaml.load(inputStream);
     LOG.fine("Successfully read config");
 
diff --git a/heron/metricsmgr/src/java/org/apache/heron/metricsmgr/MetricsSinksConfig.java b/heron/metricsmgr/src/java/org/apache/heron/metricsmgr/MetricsSinksConfig.java
index ff989cd..f0655bb 100644
--- a/heron/metricsmgr/src/java/org/apache/heron/metricsmgr/MetricsSinksConfig.java
+++ b/heron/metricsmgr/src/java/org/apache/heron/metricsmgr/MetricsSinksConfig.java
@@ -29,6 +29,7 @@
 import java.util.Map;
 
 import org.yaml.snakeyaml.Yaml;
+import org.yaml.snakeyaml.constructor.SafeConstructor;
 
 import org.apache.heron.common.basics.TypeUtils;
 
@@ -62,7 +63,7 @@
       return Collections.emptyMap();
     }
 
-    Yaml yaml = new Yaml();
+    Yaml yaml = new Yaml(new SafeConstructor());
     try (InputStream inputStream = new FileInputStream(configFile)) {
       return (Map<Object, Object>) yaml.load(inputStream);
     }
diff --git a/heron/tools/apiserver/src/java/org/apache/heron/apiserver/utils/ConfigUtils.java b/heron/tools/apiserver/src/java/org/apache/heron/apiserver/utils/ConfigUtils.java
index 8a8269b..e6aa022 100644
--- a/heron/tools/apiserver/src/java/org/apache/heron/apiserver/utils/ConfigUtils.java
+++ b/heron/tools/apiserver/src/java/org/apache/heron/apiserver/utils/ConfigUtils.java
@@ -30,6 +30,7 @@
 
 import org.yaml.snakeyaml.DumperOptions;
 import org.yaml.snakeyaml.Yaml;
+import org.yaml.snakeyaml.constructor.SafeConstructor;
 
 import org.apache.heron.api.exception.InvalidTopologyException;
 import org.apache.heron.api.generated.TopologyAPI;
@@ -110,7 +111,7 @@
     try (Writer writer = Files.newBufferedWriter(tempOverridesPath)) {
       overrideReader = Files.newBufferedReader(overridesPath);
       final Map<String, Object> currentOverrides =
-          (Map<String, Object>) new Yaml().load(overrideReader);
+          (Map<String, Object>) new Yaml(new SafeConstructor()).load(overrideReader);
       currentOverrides.putAll(overrides);
 
       // write updated overrides
@@ -138,9 +139,9 @@
     ) {
       stateManagerReader = Files.newBufferedReader(stateManagerPath);
 
-      final Map<String, Object> overrides = (Map<String, Object>) new Yaml().load(overrideReader);
+      final Map<String, Object> overrides = (Map<String, Object>) new Yaml(new SafeConstructor()).load(overrideReader);
       final Map<String, Object> stateMangerConfig =
-          (Map<String, Object>) new Yaml().load(stateManagerReader);
+          (Map<String, Object>) new Yaml(new SafeConstructor()).load(stateManagerReader);
       // update the state manager config with the overrides
       for (Map.Entry<String, Object> entry : overrides.entrySet()) {
         // does this key have an override?
diff --git a/heron/tools/apiserver/tests/java/org/apache/heron/apiserver/utils/ConfigUtilsTests.java b/heron/tools/apiserver/tests/java/org/apache/heron/apiserver/utils/ConfigUtilsTests.java
index 7fd110c..2fbbc15 100644
--- a/heron/tools/apiserver/tests/java/org/apache/heron/apiserver/utils/ConfigUtilsTests.java
+++ b/heron/tools/apiserver/tests/java/org/apache/heron/apiserver/utils/ConfigUtilsTests.java
@@ -31,6 +31,7 @@
 
 import org.junit.Test;
 import org.yaml.snakeyaml.Yaml;
+import org.yaml.snakeyaml.constructor.SafeConstructor;
 
 import org.apache.heron.common.basics.Pair;
 
@@ -49,7 +50,7 @@
     final String overridesPath = ConfigUtils.createOverrideConfiguration(overrideProperties);
     try (Reader reader = Files.newBufferedReader(Paths.get(overridesPath))) {
       final Map<String, Object> overrides =
-          (Map<String, Object>) new Yaml().loadAs(reader, Map.class);
+          (Map<String, Object>) new Yaml(new SafeConstructor()).loadAs(reader, Map.class);
       assertEquals(overrides.size(), overrideProperties.size());
       for (String key : overrides.keySet()) {
         assertEquals(overrides.get(key), overrideProperties.getProperty(key));
@@ -73,7 +74,7 @@
     try (Writer writer = Files.newBufferedWriter(stateManagerPath)) {
       final Map<String, String> config = new HashMap<>();
       config.put("heron.statemgr.connection.string", "<host>:<port>");
-      new Yaml().dump(config, writer);
+      new Yaml(new SafeConstructor()).dump(config, writer);
     }
 
     // apply the overrides
@@ -81,7 +82,7 @@
 
     try (Reader reader = Files.newBufferedReader(stateManagerPath)) {
       final Map<String, Object> stateManagerWithOverrides =
-          (Map<String, Object>) new Yaml().loadAs(reader, Map.class);
+          (Map<String, Object>) new Yaml(new SafeConstructor()).loadAs(reader, Map.class);
       assertEquals(stateManagerWithOverrides.size(), 1);
       assertEquals(stateManagerWithOverrides.get("heron.statemgr.connection.string"),
           "zookeeper:2181");
@@ -103,7 +104,7 @@
     try (Writer writer = Files.newBufferedWriter(stateManagerPath)) {
       final Map<String, String> config = new HashMap<>();
       config.put("heron.statemgr.connection.string", "<host>:<port>");
-      new Yaml().dump(config, writer);
+      new Yaml(new SafeConstructor()).dump(config, writer);
     }
 
     // apply the overrides
@@ -111,7 +112,7 @@
 
     try (Reader reader = Files.newBufferedReader(stateManagerPath)) {
       final Map<String, Object> stateManagerWithOverrides =
-          (Map<String, Object>) new Yaml().loadAs(reader, Map.class);
+          (Map<String, Object>) new Yaml(new SafeConstructor()).loadAs(reader, Map.class);
       assertEquals(stateManagerWithOverrides.size(), 1);
       assertEquals(stateManagerWithOverrides.get("heron.statemgr.connection.string"),
           "<host>:<port>");
@@ -142,7 +143,7 @@
 
     try (Reader reader = Files.newBufferedReader(Paths.get(overridesPath))) {
       final Map<String, Object> newOverrides =
-          (Map<String, Object>) new Yaml().loadAs(reader, Map.class);
+          (Map<String, Object>) new Yaml(new SafeConstructor()).loadAs(reader, Map.class);
       assertEquals(newOverrides, combinedOverrides);
     }
   }
@@ -166,7 +167,7 @@
 
     try (Reader reader = Files.newBufferedReader(Paths.get(overridesPath))) {
       final Map<String, Object> newOverrides =
-          (Map<String, Object>) new Yaml().loadAs(reader, Map.class);
+          (Map<String, Object>) new Yaml(new SafeConstructor()).loadAs(reader, Map.class);
       assertEquals(newOverrides, overrides);
     }
   }