CVE-2021-47621: Insufficient Information (NVD-CWE-noinfo)
value: ClassGraph before 4.8.112 was not resistant to XML eXternal Entity (XXE) attacks.
CWE description: There is insufficient information about the issue to classify it; details are unkown or unspecified.
Published: 2024-06-21T06:15Z
Repository: https://github.com/classgraph/classgraph
Language: Java
Files changed: src/main/java/nonapi/io/github/classgraph/utils/VersionFinder.java
Commit date: 2021-08-05 14:05:06 +0530
Commit message: Adding SecureDocumentBuilderFactory & SecureXPATHFactory to prevent XXE( XML External Entity) attack

Diff: diff --git a/src/main/java/nonapi/io/github/classgraph/utils/VersionFinder.java b/src/main/java/nonapi/io/github/classgraph/utils/VersionFinder.java
index cef6e695..848c8199 100644
--- a/src/main/java/nonapi/io/github/classgraph/utils/VersionFinder.java
+++ b/src/main/java/nonapi/io/github/classgraph/utils/VersionFinder.java
@@ -37,14 +37,17 @@ import java.nio.file.Paths;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Locale;
 import java.util.Properties;
 
+import javax.xml.XMLConstants;
 import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
 import javax.xml.xpath.XPathConstants;
 import javax.xml.xpath.XPathFactory;
 
+import javax.xml.xpath.XPathFactoryConfigurationException;
 import org.w3c.dom.Document;
 
 import io.github.classgraph.ClassGraph;
 
 /** Finds the version number of ClassGraph, and the version of the JDK. */
@@ -219,13 +222,13 @@ public final class VersionFinder {
                 }
                 // Remove up to two more levels for "bin" or "target/classes"
                 for (int i = 0; i < 3 && path != null; i++, path = path.getParent()) {
                     final Path pom = path.resolve("pom.xml");
                     try (InputStream is = Files.newInputStream(pom)) {
-                        final Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(is);
+                        final Document doc = getSecureDocumentBuilderFactory().newDocumentBuilder().parse(is);
                         doc.getDocumentElement().normalize();
-                        String version = (String) XPathFactory.newInstance().newXPath().compile("/project/version")
+                        String version = (String) getSecureXPathFactory().newXPath().compile("/project/version")
                                 .evaluate(doc, XPathConstants.STRING);
                         if (version != null) {
                             version = version.trim();
                             if (!version.isEmpty()) {
                                 return version;
@@ -274,6 +277,42 @@ public final class VersionFinder {
                 return version;
             }
         }
         return "unknown";
     }
+
+    /**
+     * Helper method to provide a XXE secured DocumentBuilder Factory.
+     *
+     * reference - https://gist.github.com/AlainODea/1779a7c6a26a5c135280bc9b3b71868f
+     * reference - https://rules.sonarsource.com/java/tag/owasp/RSPEC-2755
+     * @return DocumentBuilderFactory
+     * @throws ParserConfigurationException
+     */
+    private static DocumentBuilderFactory getSecureDocumentBuilderFactory() throws ParserConfigurationException {
+        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+        dbf.setXIncludeAware(false);
+        dbf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
+        dbf.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
+        dbf.setAttribute(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "");
+        dbf.setExpandEntityReferences(false);
+        dbf.setNamespaceAware(true);
+        dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
+        dbf.setFeature("http://xml.org/sax/features/external-general-entities", false);
+        dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
+        dbf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
+        return dbf;
+    }
+
+    /**
+     * Helper method to provide a XXE secured XPathFactory Factory.
+     *
+     * reference - reference - https://rules.sonarsource.com/java/tag/owasp/RSPEC-2755
+     * @return XPathFactory
+     * @throws XPathFactoryConfigurationException
+     */
+    private static XPathFactory getSecureXPathFactory() throws XPathFactoryConfigurationException {
+        XPathFactory xPathFactory = XPathFactory.newInstance();
+        xPathFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
+        return xPathFactory;
+    }
 }

Vulnerable code:                         final Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(is);
                        String version = (String) XPathFactory.newInstance().newXPath().compile("/project/version")
Fixed code: import javax.xml.XMLConstants;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPathFactoryConfigurationException;
                        final Document doc = getSecureDocumentBuilderFactory().newDocumentBuilder().parse(is);
                        String version = (String) getSecureXPathFactory().newXPath().compile("/project/version")

    /**
     * Helper method to provide a XXE secured DocumentBuilder Factory.
     *
     * reference - https://gist.github.com/AlainODea/1779a7c6a26a5c135280bc9b3b71868f
     * reference - https://rules.sonarsource.com/java/tag/owasp/RSPEC-2755
     * @return DocumentBuilderFactory
     * @throws ParserConfigurationException
     */
    private static DocumentBuilderFactory getSecureDocumentBuilderFactory() throws ParserConfigurationException {
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        dbf.setXIncludeAware(false);
        dbf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
        dbf.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
        dbf.setAttribute(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "");
        dbf.setExpandEntityReferences(false);
        dbf.setNamespaceAware(true);
        dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
        dbf.setFeature("http://xml.org/sax/features/external-general-entities", false);
        dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
        dbf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
        return dbf;
    }

    /**
     * Helper method to provide a XXE secured XPathFactory Factory.
     *
     * reference - reference - https://rules.sonarsource.com/java/tag/owasp/RSPEC-2755
     * @return XPathFactory
     * @throws XPathFactoryConfigurationException
     */
    private static XPathFactory getSecureXPathFactory() throws XPathFactoryConfigurationException {
        XPathFactory xPathFactory = XPathFactory.newInstance();
        xPathFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
        return xPathFactory;
    }