Index: mysql-connector-java-8.0.25/src/main/user-impl/java/com/mysql/cj/jdbc/MysqlSQLXML.java
===================================================================
--- mysql-connector-java-8.0.25.orig/src/main/user-impl/java/com/mysql/cj/jdbc/MysqlSQLXML.java
+++ mysql-connector-java-8.0.25/src/main/user-impl/java/com/mysql/cj/jdbc/MysqlSQLXML.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2020, Oracle and/or its affiliates.
+ * Copyright (c) 2002, 2021, Oracle and/or its affiliates.
  *
  * This program is free software; you can redistribute it and/or modify it under
  * the terms of the GNU General Public License, version 2.0, as published by the
@@ -42,6 +42,7 @@ import java.io.Writer;
 import java.sql.SQLException;
 import java.sql.SQLXML;
 
+import javax.xml.XMLConstants;
 import javax.xml.parsers.DocumentBuilder;
 import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.stream.XMLInputFactory;
@@ -65,7 +66,9 @@ import javax.xml.transform.stream.Stream
 import org.xml.sax.Attributes;
 import org.xml.sax.InputSource;
 import org.xml.sax.SAXException;
+import org.xml.sax.XMLReader;
 import org.xml.sax.helpers.DefaultHandler;
+import org.xml.sax.helpers.XMLReaderFactory;
 
 import com.mysql.cj.Messages;
 import com.mysql.cj.exceptions.ExceptionInterceptor;
@@ -199,56 +202,54 @@ public class MysqlSQLXML implements SQLX
 
         if (clazz == null || clazz.equals(SAXSource.class)) {
 
-            InputSource inputSource = null;
-
-            if (this.fromResultSet) {
-                inputSource = new InputSource(this.owningResultSet.getCharacterStream(this.columnIndexOfXml));
-            } else {
-                inputSource = new InputSource(new StringReader(this.stringRep));
+            try {
+                XMLReader reader = XMLReaderFactory.createXMLReader();
+                // According to https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html
+                reader.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
+                setFeature(reader, "http://apache.org/xml/features/disallow-doctype-decl", true);
+                setFeature(reader, "http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
+                setFeature(reader, "http://xml.org/sax/features/external-general-entities", false);
+                setFeature(reader, "http://xml.org/sax/features/external-parameter-entities", false);
+
+                return (T) new SAXSource(reader, this.fromResultSet ? new InputSource(this.owningResultSet.getCharacterStream(this.columnIndexOfXml))
+                        : new InputSource(new StringReader(this.stringRep)));
+            } catch (SAXException ex) {
+                SQLException sqlEx = SQLError.createSQLException(ex.getMessage(), MysqlErrorNumbers.SQL_STATE_ILLEGAL_ARGUMENT, ex, this.exceptionInterceptor);
+                throw sqlEx;
             }
 
-            return (T) new SAXSource(inputSource);
         } else if (clazz.equals(DOMSource.class)) {
             try {
                 DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
                 builderFactory.setNamespaceAware(true);
-                DocumentBuilder builder = builderFactory.newDocumentBuilder();
 
-                InputSource inputSource = null;
+                // According to https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html
+                setFeature(builderFactory, XMLConstants.FEATURE_SECURE_PROCESSING, true);
+                setFeature(builderFactory, "http://apache.org/xml/features/disallow-doctype-decl", true);
+                setFeature(builderFactory, "http://xml.org/sax/features/external-general-entities", false);
+                setFeature(builderFactory, "http://xml.org/sax/features/external-parameter-entities", false);
+                setFeature(builderFactory, "http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
+                builderFactory.setXIncludeAware(false);
+                builderFactory.setExpandEntityReferences(false);
 
-                if (this.fromResultSet) {
-                    inputSource = new InputSource(this.owningResultSet.getCharacterStream(this.columnIndexOfXml));
-                } else {
-                    inputSource = new InputSource(new StringReader(this.stringRep));
-                }
+                builderFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "");
+
+                DocumentBuilder builder = builderFactory.newDocumentBuilder();
 
-                return (T) new DOMSource(builder.parse(inputSource));
+                return (T) new DOMSource(builder.parse(this.fromResultSet ? new InputSource(this.owningResultSet.getCharacterStream(this.columnIndexOfXml))
+                        : new InputSource(new StringReader(this.stringRep))));
             } catch (Throwable t) {
                 SQLException sqlEx = SQLError.createSQLException(t.getMessage(), MysqlErrorNumbers.SQL_STATE_ILLEGAL_ARGUMENT, t, this.exceptionInterceptor);
                 throw sqlEx;
             }
 
         } else if (clazz.equals(StreamSource.class)) {
-            Reader reader = null;
-
-            if (this.fromResultSet) {
-                reader = this.owningResultSet.getCharacterStream(this.columnIndexOfXml);
-            } else {
-                reader = new StringReader(this.stringRep);
-            }
+            return (T) new StreamSource(this.fromResultSet ? this.owningResultSet.getCharacterStream(this.columnIndexOfXml) : new StringReader(this.stringRep));
 
-            return (T) new StreamSource(reader);
         } else if (clazz.equals(StAXSource.class)) {
             try {
-                Reader reader = null;
-
-                if (this.fromResultSet) {
-                    reader = this.owningResultSet.getCharacterStream(this.columnIndexOfXml);
-                } else {
-                    reader = new StringReader(this.stringRep);
-                }
-
-                return (T) new StAXSource(this.inputFactory.createXMLStreamReader(reader));
+                return (T) new StAXSource(this.inputFactory.createXMLStreamReader(
+                        this.fromResultSet ? this.owningResultSet.getCharacterStream(this.columnIndexOfXml) : new StringReader(this.stringRep)));
             } catch (XMLStreamException ex) {
                 SQLException sqlEx = SQLError.createSQLException(ex.getMessage(), MysqlErrorNumbers.SQL_STATE_ILLEGAL_ARGUMENT, ex, this.exceptionInterceptor);
                 throw sqlEx;
@@ -259,6 +260,18 @@ public class MysqlSQLXML implements SQLX
         }
     }
 
+    private static void setFeature(Object factory, String name, boolean value) {
+        try {
+            if (factory instanceof DocumentBuilderFactory) {
+                ((DocumentBuilderFactory) factory).setFeature(name, value);
+            } else if (factory instanceof XMLReader) {
+                ((XMLReader) factory).setFeature(name, value);
+            }
+        } catch (Exception ignore) {
+            // no-op
+        }
+    }
+
     @Override
     public synchronized OutputStream setBinaryStream() throws SQLException {
         checkClosed();
@@ -391,7 +404,7 @@ public class MysqlSQLXML implements SQLX
 
     protected synchronized Reader serializeAsCharacterStream() throws SQLException {
         checkClosed();
-        if (this.workingWithResult) {
+        if (this.workingWithResult || this.owningResultSet == null) {
             // figure out what kind of result
             if (this.stringRep != null) {
                 return new StringReader(this.stringRep);
