yaml use safe constructor (#782)

diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/common/util/YamlParser.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/common/util/YamlParser.java
index 7406e47..024097d 100644
--- a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/common/util/YamlParser.java
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/common/util/YamlParser.java
@@ -17,36 +17,40 @@
 
 package org.apache.dubbo.admin.common.util;
 
+import org.apache.dubbo.common.utils.PojoUtils;
 import org.yaml.snakeyaml.Yaml;
+import org.yaml.snakeyaml.constructor.SafeConstructor;
+import org.yaml.snakeyaml.error.YAMLException;
 import org.yaml.snakeyaml.introspector.Property;
 import org.yaml.snakeyaml.nodes.NodeTuple;
 import org.yaml.snakeyaml.nodes.Tag;
 import org.yaml.snakeyaml.representer.Representer;
 
+import java.util.Map;
+
 public class YamlParser {
 
-    private static Yaml yaml;
-
-    static {
-        Representer representer = new Representer() {
-
-            protected NodeTuple representJavaBeanProperty(Object javaBean, Property property, Object propertyValue, Tag customTag) {
-                if (propertyValue == null) {
-                    return null;
-                }
-                else {
-                    return super.representJavaBeanProperty(javaBean, property, propertyValue, customTag);
-                }
-            }
-        };
-        yaml = new Yaml(representer);
-    }
-
     public static String dumpObject(Object object) {
-        return yaml.dumpAsMap(object);
+        return new Yaml(new SafeConstructor(), new CustomRepresenter()).dumpAsMap(object);
     }
 
     public static <T> T loadObject(String content, Class<T> type) {
-        return yaml.loadAs(content, type);
+        Map<String, Object> map = new Yaml(new SafeConstructor(), new CustomRepresenter()).load(content);
+        try {
+            return (T) PojoUtils.mapToPojo(map, type);
+        } catch (Exception e) {
+            throw new YAMLException(e);
+        }
+    }
+
+    public static class CustomRepresenter extends Representer {
+
+        protected NodeTuple representJavaBeanProperty(Object javaBean, Property property, Object propertyValue, Tag customTag) {
+            if (propertyValue == null) {
+                return null;
+            } else {
+                return super.representJavaBeanProperty(javaBean, property, propertyValue, customTag);
+            }
+        }
     }
 }
diff --git a/dubbo-admin-server/src/test/java/org/apache/dubbo/admin/common/util/YamlParserTest.java b/dubbo-admin-server/src/test/java/org/apache/dubbo/admin/common/util/YamlParserTest.java
index 9e36350..f7b3724 100644
--- a/dubbo-admin-server/src/test/java/org/apache/dubbo/admin/common/util/YamlParserTest.java
+++ b/dubbo-admin-server/src/test/java/org/apache/dubbo/admin/common/util/YamlParserTest.java
@@ -19,10 +19,14 @@
 
 import org.apache.dubbo.admin.model.dto.DynamicConfigDTO;
 import org.apache.dubbo.admin.model.store.OverrideConfig;
+
 import org.junit.Test;
+import org.yaml.snakeyaml.Yaml;
+import org.yaml.snakeyaml.constructor.ConstructorException;
 
 import java.io.IOException;
 import java.io.InputStream;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
@@ -62,5 +66,24 @@
         }
     }
 
+    @Test(expected = ConstructorException.class)
+    public void exploitedTest() throws IOException {
+        try (InputStream yamlStream = this.getClass().getResourceAsStream("/exploited.yml")) {
+            YamlParser.loadObject(streamToString(yamlStream), Exploited.class);
+        }
+    }
+
+
+    public static class Exploited {
+        private Map<Object, Object> data;
+
+        public Map<Object, Object> getData() {
+            return data;
+        }
+
+        public void setData(Map<Object, Object> data) {
+            this.data = data;
+        }
+    }
 
 }
diff --git a/dubbo-admin-server/src/test/resources/exploited.yml b/dubbo-admin-server/src/test/resources/exploited.yml
new file mode 100644
index 0000000..d1e50da
--- /dev/null
+++ b/dubbo-admin-server/src/test/resources/exploited.yml
@@ -0,0 +1,24 @@
+#
+#
+#   Licensed to the Apache Software Foundation (ASF) under one or more
+#   contributor license agreements.  See the NOTICE file distributed with
+#   this work for additional information regarding copyright ownership.
+#   The ASF licenses this file to You under the Apache License, Version 2.0
+#   (the "License"); you may not use this file except in compliance with
+#   the License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#   Unless required by applicable law or agreed to in writing, software
+#   distributed under the License is distributed on an "AS IS" BASIS,
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#   See the License for the specific language governing permissions and
+#   limitations under the License.
+#
+#
+data:
+  url: !!javax.script.ScriptEngineManager [
+  !!java.net.URLClassLoader [[
+                             !!java.net.URL ["http://localhost/"]
+                             ]]
+  ]
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index ef79177..f832147 100644
--- a/pom.xml
+++ b/pom.xml
@@ -56,7 +56,7 @@
 		<revision>0.3.0-SNAPSHOT</revision>
 		<main.basedir>${project.basedir}</main.basedir>
 		<commons-lang3-version>3.7</commons-lang3-version>
-		<dubbo-version>2.7.8</dubbo-version>
+		<dubbo-version>2.7.12</dubbo-version>
 		<curator-version>2.12.0</curator-version>
 		<curator-test-version>4.1.0</curator-test-version>
 		<fastjson-version>1.2.67</fastjson-version>