Back to Blog
high SEVERITY3 min read

JOSMFileHack TransformerFactory XXE: External DTD Processing Enabled

OSM2World's JOSMFileHack utility, which processed OpenStreetMap files generated by the JOSM editor, contained an insecure TransformerFactory configuration that permitted external DTD and stylesheet access. The vulnerability was resolved by completely removing the vulnerable code path rather than hardening it in place.

O
By Orbis AppSec
•Technically reviewed by Anupam Mediratta•Published September 24, 2026•Reviewed September 24, 2026

Answer Summary

OSM2World's first-party JOSMFileHack class in versions prior to the fix commit processed JOSM-generated OSM files using a TransformerFactory with external entity resolution enabled. An attacker could supply a malicious XML file with external entity declarations to read arbitrary files from the server or trigger server-side request forgery. The fix removes the entire JOSMFileHack code path from ConversionFacade.createRepresentations() and its associated import, eliminating the vulnerable XML processing surface. CWE-611: Improper Restriction of XML External Entity Reference.

Vulnerability at a Glance

cweCWE-611
fixComplete removal of vulnerable JOSMFileHack code path
riskArbitrary file disclosure and SSRF via malicious XML input
languageJava
root causeTransformerFactory with accessExternalDTD and accessExternalStylesheet not disabled
vulnerabilityXML External Entity (XXE) Injection

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 TransformerFactory configurations permit external entity resolution. Any XML processing of untrusted input must explicitly set accessExternalDTD="" and accessExternalStylesheet="", or better, disable DOCTYPE declarations entirely with XMLConstants.FEATURE_SECURE_PROCESSING.

  • Compatibility workarounds accumulate risk: The JOSMFileHack utility 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 on IOException meant 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.

Prevention and further reading

Frequently Asked Questions

Why was the entire JOSMFileHack code path removed rather than just hardening the TransformerFactory configuration?

The PR author noted this was "defence-in-depth" to make failure modes explicit and bounded. The code was a workaround for JOSM file compatibility issues that could be handled through other means, so eliminating the vulnerable surface entirely was cleaner than maintaining hardened XML parsing code.

Does the removal of JOSMFileHack affect OSM2World's ability to process JOSM-generated files?

The ConversionFacade.createRepresentations() method previously attempted JOSM file detection via JOSMFileHack.isJOSMGenerated() and fell back to JOSMFileHack.createTempOSMFile() on OsmosisReader failures. After removal, these files must now be processed through the standard OsmosisReader path, which may change behavior for certain JOSM-generated files.

What specific TransformerFactory methods were vulnerable to XXE exploitation in the original code?

The code relied on default TransformerFactory behavior where the ACCESS_EXTERNAL_DTD and ACCESS_EXTERNAL_STYLESHEET attributes were not explicitly set to empty strings, allowing the parser to resolve external entity declarations in DOCTYPE headers.

View the Security Fix

Check out the pull request that fixed this vulnerability

View PR #71

Related Articles

high

picomatch 2.3.1 ReDoS: Extglob Pattern Catastrophic Backtracking

picomatch versions below 2.3.2, 3.0.2, or 4.0.4 contain a Regular Expression Denial of Service vulnerability in extglob pattern parsing. An attacker can cause catastrophic backtracking with patterns containing nested alternations and quantifiers, freezing any Node.js process that evaluates untrusted glob expressions.

critical

pet-window.js Dynamic Code Evaluation: CWE-94 Hardening via Number

The pet-window module constructed dynamic JavaScript by embedding raw configuration values into code strings. An attacker with local access could inject arbitrary JavaScript by modifying stored configuration. The fix replaces string interpolation with explicit Number() coercion and NaN validation for all numeric configuration parameters.

high

sanitizeUnicodeInput(): Fullwidth U+ Bypasses Codepoint Validation

The `sanitizeUnicodeInput()` helper used by the project character-range settings screen rewrote `U+` prefixes to `0x` and called `parseInt()`, but never normalized its argument first. Compatibility-equivalent forms such as fullwidth `U+`, superscript digits, or mathematical alphanumerics never matched the `/U\+/gi` regex, fell through to the `else return inputString` branch, and were handed back to callers verbatim as "sanitized" values. The fix inserts a `String.prototype.normalize('NFKC')` pas

high

brace-expansion Stack Exhaustion: CVE-2026-102276 Patched

A critical stack exhaustion vulnerability in brace-expansion allows attackers to crash Node.js applications by supplying specially crafted brace patterns that trigger unbounded recursion. The fix upgrades the library across all maintained version lines to enforce depth limits on recursive expansion. This vulnerability affects any service that expands user-controlled brace patterns without input validation.

critical

BFF Proxy QR Code Endpoint Prototype Pollution via Unvalidated JSON

A critical prototype pollution vulnerability in a backend-for-frontend (BFF) proxy endpoint allowed attackers to inject malicious properties into the JavaScript Object prototype by crafting JSON requests with forbidden keys. This could compromise application behavior across all objects. The fix adds explicit key validation to reject payloads containing `__proto__`, `constructor`, or `prototype`.

high

smol-toml 1.7.0 DoS: Malformed TOML Documents Crash Parser

A denial-of-service vulnerability in smol-toml 1.7.0 allows attackers to crash the parser by supplying malformed TOML documents. The vulnerability affects any application that parses untrusted TOML input. The fix, available in smol-toml 1.7.1, hardens input validation and error recovery.