Repository navigation
GMLReader and KMLReader XML parser configuration - #1244
Conversation
f772414 to
a3f4169
Compare
| */ | ||
| public class GMLReader | ||
| { | ||
| private static final Logger LOGGER = Logger.getLogger(GMLReader.class.getName()); |
There was a problem hiding this comment.
@dr-jts I am using standard java logging here, not sure if JTS has a "policy" about logging?
There was a problem hiding this comment.
JTS so far hasn't done any logging internally. I think it's better to continue with the policy of no logging (since that introduces a new mode that is potentially externally visible).
Can't the exceptions just be passed up for clients to handle?
There was a problem hiding this comment.
Yes they can, the wisdom of providing a detailed helpful exception, vs providing a helpful log and generic exception, is one of these annoying tradeoffs.
However in this case I am logging a warning saying "hey your parser does not provde this setting" so outright failure is a bit mean spirited. Different enviornments can be configured with different xml parsers.
Would you prefer something to System.err or System.out, or silient ignore.
There was a problem hiding this comment.
just adding a comment for now, no output
I have adapted those as examples. |
| // GML does not require DOCTYPE | ||
| setFeature(fact, XMLConstants.FEATURE_SECURE_PROCESSING, true); | ||
| setFeature(fact, "http://apache.org/xml/features/disallow-doctype-decl", true); | ||
| setFeature(fact, "http://xml.org/sax/features/external-general-entities", false); | ||
| setFeature(fact, "http://xml.org/sax/features/external-parameter-entities", false); | ||
| setFeature(fact, "http://apache.org/xml/features/nonvalidating/load-external-dtd", false); | ||
| try { | ||
| fact.setXIncludeAware(false); | ||
| } catch (UnsupportedOperationException e) { | ||
| // not supported by this parser | ||
| } | ||
|
|
||
| SAXParser parser = fact.newSAXParser(); | ||
| try { | ||
| parser.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, ""); | ||
| parser.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA, ""); | ||
| } catch (SAXNotRecognizedException | SAXNotSupportedException e) { | ||
| // not supported by this parser | ||
| } |
There was a problem hiding this comment.
Except FEATURE_SECURE_PROCESSING, these setting are not really necessary, because the resolver on line 136 takes care of external resources.
Setting FEATURE_SECURE_PROCESSING should probably fail closed instead of fail open: theoretically this property must be supported by all JAXP implementations, although Android doesn't support it.
There was a problem hiding this comment.
That is fair feedback about failing closed, still if we have all the subsequent other safety measures it should be fine? Do you think ...
There was a problem hiding this comment.
In practice everything will be fine, my remark is mostly a question of style: there are only so many maintained SAX implementations left in 2026 (I am aware of Xerces, its JDK fork, Android's ExpatReader and Oracle's XDK).
You can achieve the same result with far less lines of code:
-
FEATURE_SECURE_PROCESSINGguarantees that XML will be processed in a secure way. It's supported by everything, except Android. This feature in practice prevents entity expansion attacks, so disablingDOCTYPEis no longer necessary. -
Implementing
EntityResolveron line 134 takes care of the rest:jts/modules/core/src/main/java/org/locationtech/jts/io/gml2/GMLReader.java
Lines 134 to 139 in 8b5e408
If a file has a
DOCTYPEwith external references, these lines will block it. If theDOCTYPEonly contains internal entities, FSP will prevent Billion Laughs style attacks.
Keeping the rest is not wrong, it is just not necessary and introduces differences of behavior between SAX implementations. For example disable-doctype-decl is only recognized by parsers from the Xerces lineage. XML files that contain a DOCTYPE with only internal entity definitions will work on some parsers and fail on others.
| setProperty(XMLInputFactory.SUPPORT_DTD, false); | ||
| setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, false); | ||
| setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, ""); | ||
| setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA, ""); |
There was a problem hiding this comment.
The ACCESS_EXTERNAL_* properties are not necessary, since SUPPORT_DTD and IS_SUPPORTING_EXTERNAL_ENTITIES are set to false.
The SUPPORT_DTD and IS_SUPPORTING_EXTERNAL_ENTITIES properties are recognized by all implementations, so similarly to FSP above, they could fail closed.
There was a problem hiding this comment.
After being burned so many times I would prefer to have a belt and suspenders (even if it is just to keep security scans from complaining).
So even if not necessary, it will reasure code reviewers to see it there.
There was a problem hiding this comment.
Reassuring code reviewers (and silencing reporters) is the reason we created Commons Secure XML. 😉 This is especially useful in cases when you don't want to waste time to configure an XML parser securely (e.g. you are parsing a trusted configuration file), but reporters keep reporting a potential XXE injection.
Anyway, you do have a belt and suspenders a couple of lines below:
jts/modules/core/src/main/java/org/locationtech/jts/io/kml/KMLReader.java
Lines 106 to 108 in 8b5e408
There was a problem hiding this comment.
Nice I was not aware of https://commons.apache.org/proper/commons-secure-xml/ - while I do not wish to add a dependency to such a simple library as JTS I am going to recommend it for other projects.
There was a problem hiding this comment.
We did anticipate that some library do not want additional dependencies, which is why we “modularised” Commons Secure XML as much as possible. If shaded its footprint is quite small: JTS with Commons Secure XML shaded adds around 16 KiB to the library, compared to the 2 KiB of the code in this PR.
GML and KML do not require DOCTYPE. Apply recommended parser settings to both readers.
8b5e408 to
d6502cd
Compare
|
Okay updated and squashed down to a single commit, that does not provide a lot of detail (due to security related topic). |
GML and KML do not require DOCTYPE. Apply recommended parser settings to both readers, logging any the parser does not support, so the configuration does not depend on a specific parser.
Follow up to #1204, alternative to #1221 and #1230 with no additional dependencies.
Thanks to @Nexory and @ppkarwasz also!