3434public final class XmlProcessor extends AbstractProcessor {
3535
3636 public static final String TYPE = "xml" ;
37+
38+ private static final XMLInputFactory XML_INPUT_FACTORY = createXmlInputFactory ();
3739
3840 private final String field ;
3941 private final String targetField ;
@@ -157,6 +159,19 @@ private Object filterEmptyValues(Object obj) {
157159 return isEmptyValue (obj ) ? null : obj ;
158160 }
159161
162+ /**
163+ * Creates and configures a secure XMLInputFactory for XML parsing.
164+ * This factory is configured to prevent XXE attacks and optimize parsing.
165+ */
166+ private static XMLInputFactory createXmlInputFactory () {
167+ XMLInputFactory factory = XMLInputFactory .newInstance ();
168+ factory .setProperty (XMLInputFactory .IS_NAMESPACE_AWARE , false );
169+ factory .setProperty (XMLInputFactory .IS_COALESCING , true );
170+ factory .setProperty (XMLInputFactory .SUPPORT_DTD , false );
171+ factory .setProperty (XMLInputFactory .IS_SUPPORTING_EXTERNAL_ENTITIES , false );
172+ return factory ;
173+ }
174+
160175 /**
161176 * Determines if a value should be considered empty for filtering purposes.
162177 */
@@ -181,14 +196,8 @@ private Object parseXml(String xmlString) throws XMLStreamException {
181196 return null ;
182197 }
183198
184- XMLInputFactory factory = XMLInputFactory .newInstance ();
185- factory .setProperty (XMLInputFactory .IS_NAMESPACE_AWARE , false );
186- factory .setProperty (XMLInputFactory .IS_COALESCING , true );
187- factory .setProperty (XMLInputFactory .SUPPORT_DTD , false );
188- factory .setProperty (XMLInputFactory .IS_SUPPORTING_EXTERNAL_ENTITIES , false );
189-
190199 try (StringReader reader = new StringReader (xmlString )) {
191- XMLStreamReader xmlReader = factory .createXMLStreamReader (reader );
200+ XMLStreamReader xmlReader = XML_INPUT_FACTORY .createXMLStreamReader (reader );
192201
193202 // Skip to the first element
194203 while (xmlReader .hasNext () && xmlReader .getEventType () != XMLStreamConstants .START_ELEMENT ) {
0 commit comments