Browse Source

Add XPath to XmlUtils (#134923)

Joe Gallo 3 weeks ago
parent
commit
1904abbb73

+ 6 - 0
build-tools-internal/src/main/resources/forbidden/jdk-signatures.txt

@@ -128,3 +128,9 @@ javax.xml.validation.SchemaFactory#newInstance(java.lang.String, java.lang.Strin
 
 @defaultMessage Validator should not be used directly. Use XmlUtils#getHardenedValidator() instead
 javax.xml.validation.Schema#newValidator()
+
+@defaultMessage XPathFactory should not be used directly. Use XmlUtils#getHardenedXPath() instead
+javax.xml.xpath.XPathFactory#newDefaultInstance()
+javax.xml.xpath.XPathFactory#newInstance()
+javax.xml.xpath.XPathFactory#newInstance(java.lang.String)
+javax.xml.xpath.XPathFactory#newInstance(java.lang.String, java.lang.String, java.lang.ClassLoader)

+ 13 - 2
libs/core/src/main/java/org/elasticsearch/core/XmlUtils.java

@@ -28,6 +28,9 @@ import javax.xml.transform.TransformerFactory;
 import javax.xml.validation.Schema;
 import javax.xml.validation.SchemaFactory;
 import javax.xml.validation.Validator;
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathFactory;
+import javax.xml.xpath.XPathFactoryConfigurationException;
 
 public class XmlUtils {
 
@@ -126,16 +129,24 @@ public class XmlUtils {
     public static SAXParserFactory getHardenedSaxParserFactory() throws SAXNotSupportedException, SAXNotRecognizedException,
         ParserConfigurationException {
         var saxParserFactory = SAXParserFactory.newInstance();
-
         saxParserFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
         saxParserFactory.setFeature("http://xml.org/sax/features/external-general-entities", false);
         saxParserFactory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
         saxParserFactory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
         saxParserFactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
-
         return saxParserFactory;
     }
 
+    /**
+     * Constructs an XPath configured to be secure
+     */
+    @SuppressForbidden(reason = "This is the only allowed way to construct an XPath")
+    public static XPath getHardenedXPath() throws XPathFactoryConfigurationException {
+        XPathFactory xPathFactory = XPathFactory.newInstance();
+        xPathFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
+        return xPathFactory.newXPath();
+    }
+
     private static class ErrorHandler implements org.xml.sax.ErrorHandler {
         /**
          * Enabling schema validation with `setValidating(true)` in our

+ 1 - 3
x-pack/plugin/identity-provider/qa/idp-rest-tests/src/javaRestTest/java/org/elasticsearch/xpack/idp/IdentityProviderAuthenticationIT.java

@@ -42,7 +42,6 @@ import javax.xml.parsers.DocumentBuilder;
 import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.xpath.XPath;
 import javax.xml.xpath.XPathConstants;
-import javax.xml.xpath.XPathFactory;
 
 import static org.hamcrest.Matchers.containsInAnyOrder;
 import static org.hamcrest.Matchers.containsString;
@@ -170,8 +169,7 @@ public class IdentityProviderAuthenticationIT extends IdpRestTestCase {
         Document document = builder.parse(new InputSource(new StringReader(samlResponse)));
 
         // Create XPath evaluator
-        XPathFactory xPathFactory = XPathFactory.newInstance();
-        XPath xpath = xPathFactory.newXPath();
+        XPath xpath = XmlUtils.getHardenedXPath();
 
         // Validate SAML Response structure
         Element responseElement = (Element) xpath.evaluate("//*[local-name()='Response']", document, XPathConstants.NODE);