Uh oh!
There was an error while loading. Please reload this page.
Harden GMLReader against XXE (use Commons Secure XML) - #1230
Draft
ppkarwasz wants to merge 1 commit into
Draft
Conversation
GMLReader created its SAX parser through a stock SAXParserFactory with only namespace awareness and validation switched off, so a document could declare external entities and have the parser fetch them. Create the factory through Apache Commons Secure XML instead, which guarantees on every JAXP implementation that external DTDs and entities are never resolved and that entity expansion is bounded. Enforce the choice with a forbidden-apis check that rejects the raw SAX factory methods in `jts-core`, and link the Javadoc to the library's documentation. Commons Secure XML 1.0.0 is under vote: the POM temporarily adds the Apache staging repository after Central; remove it once the release reaches Maven Central. Assisted-By: Claude Fable 5.1 <noreply@anthropic.com> Signed-off-by: Piotr P. Karwasz <piotr@eclipse.copernik.eu>
ppkarwasz
commented
Sep 3, 2026
Author
One more design choice worth considering: Commons Secure XML also backports |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for freeto join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Note
Draft until Apache Commons Secure XML 1.0.0 reaches Maven Central. The release is currently under vote, so the POM temporarily adds the Apache staging repository (after Central). That block will be removed from this PR once the release is published.
Alternative to #1221, same problem, different fix.
Problem
GMLReader.read()builds itsSAXParserFactorywith onlysetNamespaceAware(false)andsetValidating(false), so DOCTYPE processing and external entity resolution stay enabled. GML is routinely read from untrusted input, so a crafted document can disclose local files or trigger SSRF through an external entity (XXE):KMLReaderreceived the equivalent hardening in #1204.Fix
Create the factory through
SecureSAXParserFactory.newInstance()from Apache Commons Secure XML instead ofSAXParserFactory.newInstance(). Every factory the library returns makes the same three guarantees regardless of which JAXP implementation is on the classpath:Compared with #1221, which sets Xerces-specific feature names by hand and logs a warning when the parser does not recognize them, the library either secures the factory or fails closed; there is no silent fallback to an unhardened parser. The reader keeps
setNamespaceAware(false)/setValidating(false)(it deliberately accepts unboundgml:prefixes), keeps its signatures, and parses valid GML exactly as before.The class Javadoc now says where the parser comes from and links to the library's package documentation and threat model, so security scanners have something to point at instead of flagging the reader.
Points for the reviewers
jts-core.org.apache.commons:commons-secure-xmlis a ~75 KB OSGi bundle with no transitive dependencies, compatible with Java 8;maven-bundle-pluginimports it asorg.apache.commons.xml.secure;version="[1.0,2)"without any manifest change. If an external dependency is not acceptable, the library is designed to be shaded: withminimizeJar, the SAX entry point adds about 10 kB tojts-core, and JTS still picks up fixes by bumping the version.maven-javadoc-plugin<links>entry to https://javadoc.io (unresolvable until 1.0.0 is published) so that{@link SecureSAXParserFactory}in theGMLReaderJavadoc becomes a hyperlink, and automated tools following it land on the documented guarantees rather than reporting a false positive. I can switch it to the Javadoc on https://commons.apache.org, which always shows the latest version (a plus or a minus depending on the shading decision above), or drop the autolinking entirely.Verification
As noted above, there are no new XXE unit tests: the guarantees belong to the library and are tested there. Instead, a
forbidden-apischeck now fails thejts-corebuild whenever a raw SAX factory method is used (SAXParserFactory.newInstance/newDefaultInstance/newNSInstanceoverloads andXMLReaderFactory.createXMLReader). Running it against the unpatched reader:mvn clean installon Temurin 8 passes (jts-core: 2296 tests, 0 failures).🤖 Generated with Claude Code