How to disable DTD fetching using JAXB2.0
Asked Answered
D

6

22

I'm trying to use JAXB to unmashall some XML which I used xjc to create in the first place. I don't want to do any validation on the unmarshalling, but even though I have disabled the validation according to the JAXB documentation with u.setSchema(null);, but this hasn't prevented a FileNotFoundException being thrown when it tries to run and can't find the schema.

JAXBContext jc = JAXBContext.newInstance("blast");
Unmarshaller u = jc.createUnmarshaller();
u.setSchema(null);
return u.unmarshal(blast)

I've seen similar questions for disabling SAX parsing from validation by setting the apache property http://apache.org/xml/features/validation/schema to false, but I can't get the Unmarshaller to use my own sax parser.

Denham answered 28/3, 2012 at 14:19 Comment(0)
T
8

Below is sample code that demonstrates how to get a JAXB (JSR-222) implementation to use your SAX parser:

import java.io.FileReader;
import javax.xml.XMLConstants;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.transform.sax.SAXSource;

import org.xml.sax.InputSource;
import org.xml.sax.XMLReader;

public class Demo {

    public static void main(String[] args) throws Exception {
        JAXBContext jc = JAXBContext.newInstance(Foo.class);

        SAXParserFactory spf = SAXParserFactory.newInstance();
        spf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
        XMLReader xmlReader = spf.newSAXParser().getXMLReader();
        InputSource inputSource = new InputSource(new FileReader("input.xml"));
        SAXSource source = new SAXSource(xmlReader, inputSource);

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        Foo foo = (Foo) unmarshaller.unmarshal(source);
        System.out.println(foo.getValue());
    }

}
Teenybopper answered 28/3, 2012 at 14:48 Comment(4)
That didn't work for me but these did: parser.setFeature("apache.org/xml/features/nonvalidating/load-external-dtd", false); parser.setFeature("xml.org/sax/features/validation", false);Prussian
This website explains how it can be blocked on any of the major Java frameworks.Modesta
Seems that FEATURE_SECURE_PROCESSING is about entityExpansionLimit. Check the last part of the documentation docs.oracle.com/javase/1.5.0/docs/guide/xml/jaxp/…Reba
This answers the question "how do I get the Unmarshaller to use my own sax parser", but does not answer the question "How to disable DTD fetching using JAXB2.0".Speos
T
22

Building on the answers from @blaise-doughan and @aerobiotic, here is a solution that worked for me:

import java.io.FileReader;
import javax.xml.XMLConstants;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.transform.sax.SAXSource;

import org.xml.sax.InputSource;
import org.xml.sax.XMLReader;

public class Demo2 {

    public static void main(String[] args) throws Exception {

        JAXBContext jc = JAXBContext.newInstance(MyBean.class);

        SAXParserFactory spf = SAXParserFactory.newInstance();
        spf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
        spf.setFeature("http://xml.org/sax/features/validation", false);

        XMLReader xmlReader = spf.newSAXParser().getXMLReader();
        InputSource inputSource = new InputSource(
                new FileReader("myfile.xml"));
        SAXSource source = new SAXSource(xmlReader, inputSource);

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        MyBean foo = (MyBean) unmarshaller.unmarshal(source);
    }
}
Tonguelash answered 3/2, 2014 at 10:40 Comment(1)
This worked for me.Also additionally added spf.setValidating(false); ThanksCoppery
T
8

Below is sample code that demonstrates how to get a JAXB (JSR-222) implementation to use your SAX parser:

import java.io.FileReader;
import javax.xml.XMLConstants;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.transform.sax.SAXSource;

import org.xml.sax.InputSource;
import org.xml.sax.XMLReader;

public class Demo {

    public static void main(String[] args) throws Exception {
        JAXBContext jc = JAXBContext.newInstance(Foo.class);

        SAXParserFactory spf = SAXParserFactory.newInstance();
        spf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
        XMLReader xmlReader = spf.newSAXParser().getXMLReader();
        InputSource inputSource = new InputSource(new FileReader("input.xml"));
        SAXSource source = new SAXSource(xmlReader, inputSource);

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        Foo foo = (Foo) unmarshaller.unmarshal(source);
        System.out.println(foo.getValue());
    }

}
Teenybopper answered 28/3, 2012 at 14:48 Comment(4)
That didn't work for me but these did: parser.setFeature("apache.org/xml/features/nonvalidating/load-external-dtd", false); parser.setFeature("xml.org/sax/features/validation", false);Prussian
This website explains how it can be blocked on any of the major Java frameworks.Modesta
Seems that FEATURE_SECURE_PROCESSING is about entityExpansionLimit. Check the last part of the documentation docs.oracle.com/javase/1.5.0/docs/guide/xml/jaxp/…Reba
This answers the question "how do I get the Unmarshaller to use my own sax parser", but does not answer the question "How to disable DTD fetching using JAXB2.0".Speos
S
2

In answer to the question "How to disable DTD fetching using JAXB2.0".

@sameer-puri links to https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#SAXTransformerFactory which answers the question as follows:

JAXB Unmarshaller

Since a javax.xml.bind.Unmarshaller parses XML and does not support any flags for disabling XXE, it's imperative to parse the untrusted XML through a configurable secure parser first, generate a source object as a result, and pass the source object to the Unmarshaller. For example:

//Disable XXE
SAXParserFactory spf = SAXParserFactory.newInstance();
spf.setFeature("http://xml.org/sax/features/external-general-entities", false);
spf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
spf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);

//Do unmarshall operation
Source xmlSource = new SAXSource(spf.newSAXParser().getXMLReader(),
                                new InputSource(new StringReader(xml)));
JAXBContext jc = JAXBContext.newInstance(Object.class);
Unmarshaller um = jc.createUnmarshaller();
um.unmarshal(xmlSource);
Speos answered 20/11, 2020 at 14:49 Comment(0)
I
0

You can create the Unmarshaller directly from a javax.xml.transform.sax.SAXSource.

See the example on this page: http://docs.oracle.com/cd/E17802_01/webservices/webservices/docs/1.6/api/javax/xml/bind/Unmarshaller.html

Than you "only" need to provide your own URIResolver to that SAXSource

Ichthyic answered 28/3, 2012 at 14:42 Comment(0)
B
0

The above suggestions Nothing worked out for me... Im suggesting this code which worked for me☺️ To remove Dtd from xml ...Used regex String str = event.getData(); str= str.replaceAll("<!DOCTYPE[^<>](?:<![^<>]>[^<>])>","");

Borstal answered 7/11, 2020 at 22:10 Comment(0)
K
0

The SAXParserFactory solutions from @doughan and @Renaud didn't work for me. Due to error

External DTD: Failed to read external DTD 'cXML.dtd', because 'http' access is not allowed due to restriction set by the accessExternalDTD property.

If you are behind a corporate proxy , the following solution works. It is based on XMLInputFactory

import java.io.FileReader;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamReader;
import org.junit.Assert;

public class Demo3 {

  public static void main(String[] args) throws Exception {

    JAXBContext jc = JAXBContext.newInstance(CXMLResponse.class);

    XMLInputFactory xif = XMLInputFactory.newFactory();
    xif.setProperty(XMLInputFactory.SUPPORT_DTD, false);
    XMLStreamReader xsr = xif.createXMLStreamReader(new FileReader("input.xml"));

    Unmarshaller unmarshaller = jc.createUnmarshaller();
    CXMLResponse parsedResponse = (CXMLResponse) unmarshaller.unmarshal(xsr);

    System.out.println(parsedResponse.toString());
  }
}

Inspired by https://mcmap.net/q/588595/-ignoring-dtds-when-unmarshalling-with-eclipselink-moxy . Thanks again @bdoughan

Kraigkrait answered 29/7, 2021 at 9:40 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.