Index: src/org/openstreetmap/josm/tools/XmlUtils.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- src/org/openstreetmap/josm/tools/XmlUtils.java	(revision 16473)
+++ src/org/openstreetmap/josm/tools/XmlUtils.java	(date 1590315842517)
@@ -35,6 +35,8 @@
  */
 public final class XmlUtils {
 
+    private static final String FEATURE_DISALLOW_DOCTYPE_DECL = "http://apache.org/xml/features/disallow-doctype-decl";
+
     private XmlUtils() {
         // Hide default constructor for utils classes
     }
@@ -100,6 +102,7 @@
     public static SAXParser newSafeSAXParser() throws ParserConfigurationException, SAXException {
         SAXParserFactory parserFactory = SAXParserFactory.newInstance();
         parserFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
+        parserFactory.setFeature(FEATURE_DISALLOW_DOCTYPE_DECL, true);
         parserFactory.setNamespaceAware(true);
         return parserFactory.newSAXParser();
     }
Index: test/data/dom_external_entity.xml
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- test/data/dom_external_entity.xml	(date 1590315345528)
+++ test/data/dom_external_entity.xml	(date 1590315345528)
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE updateProfile [
+  <!ENTITY file SYSTEM "file:///etc/passwd">
+]>
+<root>
+    &file;
+</root>
Index: test/data/preset_external_entity.xml
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- test/data/preset_external_entity.xml	(date 1590313939162)
+++ test/data/preset_external_entity.xml	(date 1590313939162)
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE updateProfile [
+  <!ENTITY file SYSTEM "file:///etc/passwd">
+]>
+<presets xmlns="http://josm.openstreetmap.de/tagging-preset-1.0">
+    &file;
+</presets>
Index: test/unit/org/openstreetmap/josm/gui/tagging/presets/TaggingPresetReaderTest.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- test/unit/org/openstreetmap/josm/gui/tagging/presets/TaggingPresetReaderTest.java	(revision 16473)
+++ test/unit/org/openstreetmap/josm/gui/tagging/presets/TaggingPresetReaderTest.java	(date 1590317309919)
@@ -5,6 +5,7 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertThat;
 import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
 
 import java.io.IOException;
 import java.util.Collection;
@@ -65,6 +66,20 @@
         assertEquals("[A1, A2, A3, B1, B2, B3, C1, C2, C3]", keys.toString());
     }
 
+    /**
+     * Test external entity resolving.
+     * See #19286
+     */
+    @Test
+    public void testExternalEntityResolving() throws IOException {
+        try {
+            TaggingPresetReader.readAll(TestUtils.getTestDataRoot() + "preset_external_entity.xml", true);
+            fail("Reading a file with external entities should throw an SAXParseException!");
+        } catch (SAXException e) {
+            Assert.assertEquals("DOCTYPE is disallowed when the feature \"http://apache.org/xml/features/disallow-doctype-decl\" set to true.", e.getMessage());
+        }
+    }
+
     /**
      * Validate internal presets
      * See #9027
Index: test/unit/org/openstreetmap/josm/tools/XmlUtilsTest.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- test/unit/org/openstreetmap/josm/tools/XmlUtilsTest.java	(date 1590316209081)
+++ test/unit/org/openstreetmap/josm/tools/XmlUtilsTest.java	(date 1590316209081)
@@ -0,0 +1,73 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.tools;
+
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
+import org.junit.Rule;
+import org.junit.Test;
+import org.openstreetmap.josm.TestUtils;
+import org.openstreetmap.josm.testutils.JOSMTestRules;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.transform.stream.StreamSource;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.StringWriter;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.fail;
+
+/**
+ * Unit tests of {@link XmlUtils} class.
+ */
+public class XmlUtilsTest {
+
+    /**
+     * Use default, basic test rules.
+     */
+    @Rule
+    @SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD")
+    public JOSMTestRules rules = new JOSMTestRules();
+
+    @Test
+    public void testExternalEntitiesParsingDom() throws IOException, ParserConfigurationException {
+        try {
+            final String source = TestUtils.getTestDataRoot() + "dom_external_entity.xml";
+            XmlUtils.parseSafeDOM(new FileInputStream(source));
+            fail("Parsing a document with external entities should not be allowed.");
+        } catch (SAXException e) {
+            assertEquals("External Entity: Failed to read external document 'passwd', because 'file' access is not allowed due to restriction set by the accessExternalDTD property.", e.getMessage());
+        }
+    }
+
+    @Test
+    public void testExternalEntitiesSaxParser() throws IOException, ParserConfigurationException {
+        try {
+            final String source = TestUtils.getTestDataRoot() + "dom_external_entity.xml";
+            final DefaultHandler handler = new DefaultHandler();
+            XmlUtils.parseSafeSAX(new InputSource(new FileInputStream(source)), handler);
+            fail("Parsing a document with external entities should not be allowed.");
+        } catch (SAXException e) {
+            assertEquals("External Entity: Failed to read external document 'passwd', because 'file' access is not allowed due to restriction set by the accessExternalDTD property.", e.getMessage());
+        }
+    }
+
+    @Test
+    public void testExternalEntitiesTransformer() throws IOException {
+        try {
+            final String source = TestUtils.getTestDataRoot() + "dom_external_entity.xml";
+            final Transformer transformer = XmlUtils.newSafeTransformerFactory().newTransformer();
+            transformer.transform(new StreamSource(new FileInputStream(source)), new StreamResult(new StringWriter()));
+            fail("Parsing a document with external entities should not be allowed.");
+        } catch (TransformerException e) {
+            assertNotNull(e.getCause());
+            assertEquals("External Entity: Failed to read external document 'passwd', because 'file' access is not allowed due to restriction set by the accessExternalDTD property.", e.getCause().getMessage());
+        }
+    }
+}
\ No newline at end of file
