Affected Versions
| Affected | not applicable (first-party code) |
| Fixed in | not applicable (first-party code) — see associated commit |
| Ecosystem | maven |
| CVE / GHSA | not assigned |
| CWE | CWE-611: Improper Restriction of XML External Entity Reference |
The Vulnerability Explained
The ConversionFacade.createRepresentations() method in OSM2World contained a compatibility shim for JOSM-generated OpenStreetMap files. When OsmosisReader failed to parse a file, the code would invoke JOSMFileHack.createTempOSMFile() to produce a cleaned temporary copy. This utility used TransformerFactory for XML transformation without disabling external entity resolution.
The vulnerable pattern looked like this:
// JOSMFileHack.createTempOSMFile() path
if (useJOSMHack) {
File tempFile;
try {
tempFile = JOSMFileHack.createTempOSMFile(osmFile);
} catch (Exception e2) {
throw new IOException("could not read OSM file", e2);
}
osmData = new OsmosisReader(tempFile).getData();
}
The JOSMFileHack class processed untrusted XML with a TransformerFactory that had accessExternalDTD and accessExternalStylesheet enabled by default. An attacker could craft a malicious OSM file with an external entity declaration:
<!DOCTYPE osm [
<!ENTITY xxe SYSTEM "file:///etc/passwd">
]>
<osm>
<node id="1" lat="0" lon="0">
<tag k="name" v="&xxe;"/>
</node>
</osm>
When JOSMFileHack transformed this document, the XML parser would resolve the external entity, potentially exposing server-side files or making outbound HTTP requests.
The real-world impact was significant for OSM2World deployments that accept user-uploaded OSM files. A user could exfiltrate sensitive configuration files, access internal network resources via SSRF, or trigger denial-of-service through billion laughs attacks.
The Fix
Rather than hardening the TransformerFactory configuration, the maintainers chose to eliminate the vulnerable code path entirely. The fix removes the JOSMFileHack import and all associated logic from ConversionFacade:
Before:
import org.osm2world.core.osm.creation.JOSMFileHack;
public Results createRepresentations(File osmFile, ...) {
OSMData osmData = null;
boolean useJOSMHack = false;
if (JOSMFileHack.isJOSMGenerated(osmFile)) {
useJOSMHack = true;
} else {
try {
osmData = new OsmosisReader(osmFile).getData();
} catch (IOException e) {
useJOSMHack = true;
}
}
if (useJOSMHack) {
File tempFile = JOSMFileHack.createTempOSMFile(osmFile);
osmData = new OsmosisReader(tempFile).getData();
}
// ...
}
After:
// JOSMFileHack import removed entirely
public Results createRepresentations(File osmFile, ...) {
// Direct OsmosisReader usage, no JOSM fallback
// ...
}
This defense-in-depth approach removes the attack surface rather than attempting to secure complex XML processing code. The OsmosisReader path now handles all OSM files, simplifying the code and eliminating the XXE vector.
Key Takeaways
-
Untrusted XML requires explicit hardening: Default
TransformerFactoryconfigurations permit external entity resolution. Any XML processing of untrusted input must explicitly setaccessExternalDTD=""andaccessExternalStylesheet="", or better, disable DOCTYPE declarations entirely withXMLConstants.FEATURE_SECURE_PROCESSING. -
Compatibility workarounds accumulate risk: The
JOSMFileHackutility existed to handle edge cases in JOSM-generated files. Such compatibility layers often receive less security scrutiny than primary code paths and become vulnerability hiding spots. -
Removal beats hardening for non-essential code: When a vulnerable code path serves a narrow compatibility purpose, eliminating it entirely may be preferable to maintaining hardened alternatives. This reduces long-term maintenance burden and attack surface.
-
File detection based on content is fragile: The
isJOSMGenerated()check attempted to identify problematic files before parsing, but the fallback path onIOExceptionmeant any parse failure could trigger the vulnerable JOSM handling.
How Orbis AppSec Detected This
Source: The osmFile parameter passed to ConversionFacade.createRepresentations(), which accepts arbitrary user-provided File objects.
Sink: JOSMFileHack.createTempOSMFile() invoking TransformerFactory with default external entity resolution settings.
Missing control: The TransformerFactory lacked explicit setAttribute("accessExternalDTD", "") and setAttribute("accessExternalStylesheet", "") calls, or alternatively setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true).
CWE: CWE-611 — Improper Restriction of XML External Entity Reference.
Fix: The vulnerable JOSMFileHack class and all its invocations were removed from ConversionFacade, eliminating the insecure XML transformation path.
Orbis AppSec automatically detected this vulnerability and opened a pull request with the fix. Try Orbis AppSec on your repositories to find and fix issues like this automatically.
Conclusion
The OSM2World JOSMFileHack XXE demonstrates how compatibility code paths—added to handle edge cases in third-party tool output—can become critical vulnerabilities when they process untrusted XML with insecure defaults. The fix shows that sometimes the most secure code is code that doesn't exist: by removing the JOSMFileHack workaround entirely, the maintainers eliminated the vulnerability without the ongoing risk of configuration drift or incomplete hardening.