Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

java.lang.IllegalArgumentException: Not supported: http://javax.xml.XMLConstants/property/accessExternalDTD

Ask Question

I got vulnerabilities flaws from the scan report for Java code, did some research, and found this recommendation to resolve such issues:

Improper Restriction of XML External Entity Reference (CWE ID 611)

This is the code including the fix for the XXE Attack issue:

    public static String convertNodeToString(Node node) {
        TransformerFactory tf = TransformerFactory.newInstance();
        Transformer transformer;
        try {
            tf.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
            tf.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "");
            transformer = tf.newTransformer();
            // below code to remove XML declaration
            // transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
            StringWriter writer = new StringWriter();
            transformer.transform(new DOMSource(node), new StreamResult(writer));
            String output = writer.getBuffer().toString();
            return output;
        } catch (TransformerException e) {
            e.printStackTrace();
        return null;

The good thing is that JUnit testing was a success, but, when I deployed the code on a running instance, I got this error:

java.lang.IllegalArgumentException: Not supported: http://javax.xml.XMLConstants/property/accessExternalDTD

As per my experience, this is because the running instance uses some dependencies which caused such a conflict and resulted in this error.

Following is part of the stack trace form the console:

java.lang.IllegalArgumentException: Not supported: http://javax.xml.XMLConstants/property/accessExternalDTD at org.apache.xalan.processor.TransformerFactoryImpl.setAttribute(TransformerFactoryImpl.java:571)

How I can find which dependency is causing the such error? Is there anything I can do to resolve such an error? I am also suspecting that I missed including a dependency. Please help me solve this issue.

Edit 1:

I did further research and I think this happens because of this reference in the java.exe command used to launch the actual instance:

java.exe -Xbootclasspath/p:../lib/xalan.jar;../lib/xercesImpl.jar;...

Now, I need to find out how I can overcome this issue. I came across some articles proposing to ensure the creation of the factory instance using the correct package. I think the above code ends up using the wrong package.

The question now is how to use java code to ensure using the correct package to create the TransformerFactory instance.

Edit 2:

The first answer helped me make some progress. I found that the classpath of the deployed instance has a reference to org.apache.xalan.processor.TransformerFactoryImpl in xalan.jar which seems it is used by TransformerFactory.newInstance() to create the transformer factory. I think the question is how I can make the needed changes to ensure using the proper class to create the transformer.

Edit 3:

I followed the recommendation here and added this code:

TransformerFactory factory = TransformerFactory.newInstance();
factory.setFeature(javax.xml.XMLConstants.FEATURE_SECURE_PROCESSING, true);

The error was resolved in the running instance, but, the scan tool is still reporting this vulnerability flaw XXE Attack. According to this article, this happens because an outdated XML processor is present on the classpath (e.g. Xerces, Xalan) which is exactly my case.

I think I came across an article recommending changing some system properties that will indicate the factory to create the transformer instance using the correct class. I am trying to find this article now.

I appreciate your help.

Yes, I just added it. I truly appreciate it if you could help me out with this. I came across a post suggesting using system properties to ensure using the correct instance of the factory, but I cannot find it now. – tarekahf Mar 22 at 19:11

I had the same problem,this another implementation worked for me:

import com.sun.org.apache.xalan.internal.xsltc.trax.TranformerFactoryImpl;
TranformerFactoryImpl tf = new TranformerFactoryImpl();
tf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
tf.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
tf.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "");

Edit 1: You also can try to force it:

import javax.xml.transform.TransformerFactory;
TransformFactory tf = new TransformFactory.newInstance(“com.sun.org.apache.xalan.internal.xsltc.trax.TranformerFactoryImpl”, null);
                I am using JDK jdk1.8.0_351. I added the statement import com.sun.org.apache.xalan.internal.trax.TranformerFactoryImpl; and got the error The import com.sun.org.apache.xalan.internal.trax cannot be resolved. This means I need to add a specific dependency, correct? Which one? I search all my JARs in the deployed instance for TranformerFactoryImpl.class using cmd>for /R "." %G in (*.jar) do @jar -tvf "%G" | find "TranformerFactoryImpl" > NUL && echo %G and didn't find it. Please help.
– tarekahf
                Mar 22 at 22:53
                I update de answer with another way to force it, and I noticed I forgot a name on the import on the first try, sorry.
– Gabriel S. S.
                Mar 23 at 15:08

Thanks to @Gabriel who helped me find the answer. This is another way to resolve the issue using system properties. The other method is to specify the name of the correct class using the TransformerFactory.newInstance(); method. The correct class is com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl:

tf = TransformerFactory.newInstance("com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl", NameOfContainerClass.class.getClassLoader());

Below is the final answer which worked for me and the scan report is clean.

private final static String JAVAX_TRANSFORMER_PROP = "javax.xml.transform.TransformerFactory";
private final static String JAVAX_TRANSFORMER_PROP_VAL = "com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl";
public static String convertNodeToString(Node node) throws Exception  {
        TransformerFactory tf=null;
        Transformer transformer;
        String errMsg=null;
        String output=null;
        //Prevent XXE Attack: Ensure using the correct factory class to create TrasformerFactory instance
        //  This will instruct Java to use to version which supports using ACCESS_EXTERNAL_DTD argument.
        // Use:
        //   - com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl
        //  instead of:
        //   - org.apache.xalan.processor.TransformerFactoryImpl
        if (System.getProperty(JAVAX_TRANSFORMER_PROP) == null || 
            !System.getProperty(JAVAX_TRANSFORMER_PROP).equals(JAVAX_TRANSFORMER_PROP_VAL))
            System.setProperty(JAVAX_TRANSFORMER_PROP, JAVAX_TRANSFORMER_PROP_VAL);
        try {
            tf = TransformerFactory.newInstance();
        } catch (TransformerFactoryConfigurationError  e) {
            e.printStackTrace();
            errMsg="Error 'TransformerFactoryConfigurationError' in convertNodeToString() while creating 'TransformerFactory' instance: " + e.toString();
        } catch (Exception  e) {
            e.printStackTrace();
            errMsg="Error in convertNodeToString() while creating 'TransformerFactory' instance:: " + e.toString();
        if (errMsg != null)
            throw new Exception(errMsg);
        //Prevent XXE Attack: Set attributes to prevent XXE Attack vulnerabilities.
        try {
            tf.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
            tf.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "");
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
            errMsg = "Error 'IllegalArgumentException' in convertNodeToString() while attempting to prevent XXE Attack: " + e.toString();
        } catch (Exception e) {
            e.printStackTrace();
            errMsg = "Error in convertNodeToString() while attempting to prevent XXE Attack: " + e.toString();
        if (errMsg != null)
            throw new Exception(errMsg);
        //tf.setFeature(javax.xml.XMLConstants.FEATURE_SECURE_PROCESSING, true);
        try {
            transformer = tf.newTransformer();
            // below code to remove XML declaration
            // transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
            StringWriter writer = new StringWriter();
            transformer.transform(new DOMSource(node), new StreamResult(writer));
            output = writer.getBuffer().toString();
        } catch (TransformerException e) {
            e.printStackTrace();
            errMsg = "Error 'TransformerException' in convertNodeToString() while converting the node to string: " + e.toString();
        } catch (Exception e) {
            e.printStackTrace();
            errMsg = "Error 'TransformerException' in convertNodeToString() while converting the node to string: " + e.toString();
        if (errMsg != null)
            throw new Exception(errMsg);
        return output;

Reference: https://stackoverflow.com/a/50219550/4180447

Thanks for contributing an answer to Stack Overflow!

  • Please be sure to answer the question. Provide details and share your research!

But avoid

  • Asking for help, clarification, or responding to other answers.
  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.