Apache XMLSchema Security Threat Model

§1 Header

  • Project: Apache XMLSchema — “a lightweight schema object model that can be used to manipulate and generate XML schema representations” (documented: README.txt).
  • Repository: apache/ws-xmlschema.
  • Version / commit: this model is based on the default branch at clone time. A report against project release N should be triaged against the model as it stood at N, not at HEAD. Latest release documented in RELEASE-NOTE.txt: 2.3.0.
  • Date: 2026-08-26.
  • Authors: ASF Security team, awaiting XMLSchema / Webservices PMC review.
  • Status: under maintainer review.
  • Reporting: vulnerabilities that fall under §8 (claimed properties) should be reported per SECURITY.md and the Apache Security Team disclosure channel (https://www.apache.org/security/); reports that fall under §3 (out of scope) or §9 (properties not provided) will be closed by XMLSchema triagers citing this document.
  • Provenance legend(documented) = drawn from in-repo docs / source comments / project website with citation; (maintainer) = stated by an XMLSchema maintainer in response to this threat model; (inferred) = synthesized by the producer from code structure or domain knowledge, awaiting PMC ratification (every (inferred) tag has a matching §14 question).
  • Model confidence: 22 documented / 0 maintainer / 24 inferred.

XMLSchema is a Java library that parses, models, walks, and serializes W3C XML Schema documents (.xsd files). It is not a document validator at its core (despite the xmlschema-walker providing some validation helpers): the primary product is the in-memory object model of a schema, and the schema-imports / schema-includes resolver that lets a <xs:include> or <xs:import> pull in additional schemas from a URI. XMLSchema is consumed primarily by SOAP stacks (Apache CXF, Apache Axis) and other code-generation / data-binding tooling. It is bundled into runtimes that ingest WSDLs and policy documents.

§2 Scope and intended use

Intended use

  • In-process parsing and manipulation of W3C XML Schema documents in Java, primarily as part of a tooling pipeline (WSDL import, code generation, data-binding) or as part of a SOAP stack at runtime (documented: README.txt).
  • Three modules ship: xmlschema-core (the object model + parser + serializer + URI resolver), xmlschema-walker (visitor-style schema walking + a XmlSchemaElementValidator used for tooling), and xmlschema-bundle-test (an OSGi bundle integration test). The w3c-testcases directory holds the W3C test suite for regression testing only.

Deployment shape

XMLSchema is an in-process Java library. There is no daemon, no network listener, no CLI. The threat model is therefore that of an XML-parsing library that performs caller-directed network or filesystem IO when it follows <xs:include> / <xs:import> / schemaLocation references (inferred — §14 Q2).

Caller roles

RoleTrust levelNotes
Embedding Java applicationtrustedCalls XmlSchemaCollection.read(...), decides whether the input stream came from disk, classpath, or wire; decides which URIResolver to plug in.
URIResolver implementationtrustedEither the bundled DefaultURIResolver (which constructs a URL from the parent schema's base URI + the schemaLocation and returns an InputSource pointing at it) or a caller-supplied resolver (documented: xmlschema-core/src/main/java/.../resolver/DefaultURIResolver.java). A hostile resolver is out of model.
ExtensionRegistry implementationtrustedPluggable via system property org.apache.ws.commons.schema.extension_registry (documented: xmlschema-core/src/main/java/org/apache/ws/commons/schema/XmlSchemaCollection.java line 361).
Producer of the schema bytes (Reader, InputStream, InputSource, Source, Document, Element)variable — see §6 trust tableThe only attacker-controllable input position; in many embeddings the schema bytes come from a WSDL fetched off the wire.
Producer of imported / included schemas (resolved by the URIResolver)variable — typically as untrusted as the parent schema, but can be a different origin if the parent's <xs:import schemaLocation="http://attacker/evil.xsd"> points elsewhereFollowing an xs:import is a second, possibly cross-origin, fetch. This is the principal SSRF surface.
JDK XML platform (DocumentBuilderFactory, TransformerFactory, SchemaFactory)trusted upstreamXMLSchema sets FEATURE_SECURE_PROCESSING=true on the factories it constructs. Its internal schema parser also rejects DOCTYPE declarations by default and disables external DTD and external entity resolution; org.apache.ws.commons.schema.allowDTD=true accepts DOCTYPE-bearing schema documents while keeping external resolution disabled.

Component-family table

FamilyRepresentative entry pointTouches outside the process?In-model?
xmlschema-core object model — XmlSchema* types, XmlSchemaCollection, SchemaBuilderXmlSchemaCollection.read(InputSource, ...) and overloadsno for in-memory model; yes when the URI resolver follows xs:import/xs:includeyes
xmlschema-core URI resolver — DefaultURIResolver, CollectionURIResolver, URIResolverXmlSchemaCollection.setSchemaResolver()yes — by design, fetches imported schemasyes
xmlschema-core serializer — XmlSchemaSerializerXmlSchema.write(OutputStream)noyes
xmlschema-core resource loader (internal) — hardened DocumentBuilderFactory and TransformerFactory instancesinvoked by XmlSchemaCollection.read(InputSource, ...), recursive schema reparses, and XmlSchema.write(...)no except where the URI resolver fetches imported schemas before parsingyes
xmlschema-walker visitor — XmlSchemaWalker, XmlSchemaVisitor, XmlSchemaScopewalked by a caller-supplied XmlSchemaVisitornoyes
xmlschema-walker element validator — XmlSchemaElementValidatorwalked at SAX-event time; consults the schema modelno (operates on caller-supplied SAX events)yes
xmlschema-walker document path finder — XmlSchemaPathFinderwalked at SAX-event time; matches events against the schema modelno (operates on caller-supplied SAX events)yes
xmlschema-walker DOM-from-SAX helper — DomBuilderFromSaxbuilds a DOM out of SAX events for validator inspectionnoyes
xmlschema-bundle-testOSGi packaging regression testn/aout of model (§3)
w3c-testcases/W3C schema test datan/aout of model (§3)

A finding is in-model only if it reaches a row marked yes.

§3 Out of scope (explicit non-goals)

  1. XML document validation against a schema. XMLSchema is a schema model; the only validation-like artifact is xmlschema-walker‘s XmlSchemaElementValidator used in tooling contexts. Findings that depend on the JDK Validator / SchemaFactory behavior or on third-party validators built on XMLSchema’s model are out of model (inferred — §14 Q3). → OUT-OF-MODEL: out-of-layer.
  2. A SOAP / WSDL parser. XMLSchema parses the embedded <schema> element of a WSDL, but the WSDL parser itself is upstream (e.g. Apache WSDL4J, Apache CXF). → OUT-OF-MODEL: out-of-layer.
  3. SchemaFactory of the JDK. XMLSchema does not wrap or replace the JDK's javax.xml.validation.SchemaFactory. The two are different abstractions (inferred — §14 Q3). → OUT-OF-MODEL: out-of-layer.
  4. xmlschema-bundle-test and w3c-testcases/. Integration test harness and W3C regression data. → OUT-OF-MODEL: unsupported-component.
  5. The XML parser bytes-to-DOM step when the caller provides a pre-parsed Document / Element. XmlSchemaCollection.read(Document) and .read(Element) accept a caller-parsed DOM; if the caller's DocumentBuilderFactory is not hardened, XMLSchema does not retroactively secure it (inferred — §14 Q4). → OUT-OF-MODEL: trusted-input.
  6. The remote host reached when following an xs:include / xs:import. The URI is in the input schema; XMLSchema follows it. What the remote host returns is data XMLSchema then parses, but the integrity of the remote host is not WSS4J's concern (inferred — §14 Q5). → OUT-OF-MODEL: adversary-not-in-scope for malicious remote peer; VALID if XMLSchema is tricked into the fetch in the first place by a path the §7 model permits.
  7. Replacement URIResolver / ExtensionRegistry implementations. Caller-pluggable; a hostile resolver is out of model.
  8. Code shipped in w3c-testcases/, */src/test/, etc/, xmlschema-bundle-test/. Test data and supporting fixtures. → OUT-OF-MODEL: unsupported-component.

§4 Trust boundaries and data flow

#TransitionAuthenticationAuthorization
B1Caller → `XmlSchemaCollection.read(InputSourceReaderSource
B2XmlSchemaCollection.read(InputSource, ...) → hardened JDK DocumentBuildernoneDOCTYPE rejected by default; external DTD/entity resolution disabled
B3Schema parser → URIResolver.resolveEntity(namespace, schemaLocation, baseUri)nonebundled DefaultURIResolver does no host filtering: it constructs new URL(new URL(baseUri), schemaLocation) and hands back an InputSource pointing at it
B4Resolved InputSourceXmlSchemaCollection.read(InputSource, ...) (recursive)nonenone
B5XmlSchema.write(...) → JDK TransformerFactory (with FEATURE_SECURE_PROCESSING=true and external DTD/stylesheet access disabled where supported)nonenone
B6XmlSchemaCollection ctor → System.getProperty("org.apache.ws.commons.schema.extension_registry")Class.forName()nonetrusts system properties to be operator-controlled

Reachability preconditions per family

  • xmlschema-core parser (XmlSchemaCollection.read(InputSource), .read(Reader), .read(Source) for non-DOMSource sources): in-model when the bytes are attacker-controllable. XMLSchema sets FEATURE_SECURE_PROCESSING=true on its internal DocumentBuilderFactory, rejects DOCTYPE declarations by default, disables external general entities, external parameter entities, and external DTD loading, and installs a no-op SAX EntityResolver. Setting org.apache.ws.commons.schema.allowDTD=true accepts DOCTYPE-bearing schema documents but keeps external DTD and external entity resolution disabled.
  • xmlschema-core URI resolver (DefaultURIResolver): in-model for SSRF / cross-origin fetch when the input schema is attacker- controlled and contains an xs:import schemaLocation="…". The bundled resolver constructs new URL(...) and returns an InputSource; the JDK then fetches it on parse().
  • xmlschema-core parser fed a pre-parsed DOM (read(Document), read(Element)): out of model for XXE; the caller's DocumentBuilderFactory decided that. In-model for whatever the schema-model semantics imply about the DOM contents.
  • xmlschema-walker: in-model when the visitor walks an attacker-controlled schema. The walker is purely in-memory. Before cycle detection, malformed but parseable schemas could create cycles in type derivation, substitution groups, model groups, or attribute groups and recurse until StackOverflowError. The walker now tracks these expansion paths and rejects cyclic re-entry with XmlSchemaException; recursion that crosses an element declaration remains supported.
  • XmlSchemaPathFinder: in-model when caller-supplied SAX events are matched against an attacker-controlled schema. Its backtracking work is bounded per document by configurable decision-point and replay-event limits.
  • XmlSchemaElementValidator / DomBuilderFromSax: in-model only insofar as they parse SAX events the caller hands in. DomBuilderFromSax sets FEATURE_SECURE_PROCESSING=true on its DocumentBuilderFactory (documented: xmlschema-walker/src/main/java/.../docpath/DomBuilderFromSax.java line 81).

§5 Assumptions about the environment

  • JDK: minimum Java 17 in the 2.3.0 release; earlier releases supported Java 7 (documented: RELEASE-NOTE.txt).
  • JDK XML platform: assumes a conformant DocumentBuilderFactory, TransformerFactory, and SAX parser. XMLSchema applies explicit DTD and external access controls to its internal schema parser and transformer, while unsupported optional JAXP features are ignored so the remaining controls still apply.
  • Network: the bundled DefaultURIResolver will issue HTTP / HTTPS / file:// / jar: fetches via the JDK URL handlers when an xs:include / xs:import schemaLocation is followed. Whether the JVM has a proxy configured, a SecurityManager, or any URL-scheme restriction is out of XMLSchema's control (documented: DefaultURIResolver.java).
  • Filesystem: caller-supplied paths; XMLSchema does no path sanitization of schemaLocation values that begin with file:// (inferred — §14 Q7).
  • Memory: schemas are held in memory; XMLSchema has no built-in ceiling on schema-document size, imported bytes, or fetch rate. Import and include resolution is bounded per read by a default maximum depth of 64 and maximum of 1000 resolved schema documents, and schema-model construction is bounded by a default structural nesting depth of 512; these limits are configurable with JVM system properties. The walker has active-path cycle detection for the schema expansion graphs it traverses, but large acyclic schemas may still consume substantial memory and CPU (documented: README.txt).
  • System properties: org.apache.ws.commons.schema.extension_registry is consulted at XmlSchemaCollection construction time, and the named class is loaded via Class.forName() (documented: XmlSchemaCollection.java line 361). This is a startup-time privilege escalation surface if the system property can be set by an untrusted actor (inferred — §14 Q9).
  • Wrap in AccessController.doPrivileged: XMLSchema brackets the schema parse and the system-property read in AccessController.doPrivileged to be JDK-SecurityManager-compatible on pre-17 JDKs (documented: XmlSchemaCollection.java lines 376, 745). On JDK 17+ the SecurityManager is deprecated.

What XMLSchema does not do to its host (negative claims, awaiting maintainer ratification)

  • Opens no listening sockets (inferred — §14 Q10).
  • Spawns no child processes (inferred — §14 Q10).
  • Installs no signal handlers (inferred — §14 Q10).
  • Reads only the documented system property org.apache.ws.commons.schema.extension_registry for security-relevant decisions; does not consume LD_*-style envvars (inferred — §14 Q10).
  • Writes nothing to the filesystem of its own initiative; the XmlSchemaSerializer writes to the OutputStream the caller hands in (inferred — §14 Q10).

§5a Build-time and configuration variants

XMLSchema is a single Maven artifact set (xmlschema-core, xmlschema-walker, xmlschema-bundle-test). There are no compile-time feature toggles (inferred — §14 Q11). The runtime security envelope is shaped by a small set of runtime extension points:

KnobDefaultMaintainer stanceEffect
org.apache.ws.commons.schema.extension_registry system propertyunset (documented: XmlSchemaCollection.java line 361)dev-time customization; if set by an untrusted actor the named class is loaded into the JVMextension-registry class is Class.forName-loaded at XmlSchemaCollection ctor time
XmlSchemaCollection.setSchemaResolver(URIResolver)DefaultURIResolver (documented: DefaultURIResolver.java)maintainer ruling required — is the documented expectation that production deployments install a restricted resolver that refuses untrusted hosts (proposed: yes, §10), or is the default resolver supported as production-safe? (inferred — §14 Q12)controls whether xs:include/xs:import may reach the network
XmlSchemaCollection.setBaseUri(String)unset (documented)caller-suppliedbase URI against which relative schemaLocation values resolve
org.apache.ws.commons.schema.walker.maxDecisionPoints system property10000 (documented: XmlSchemaPathFinder.java)operator-tunable per-process limitmaximum decision points created while matching one document
org.apache.ws.commons.schema.walker.maxReplayedEvents system property1000000 (documented: XmlSchemaPathFinder.java)operator-tunable per-process limitmaximum previously traversed events replayed while backtracking through one document
org.apache.ws.commons.schema.maxImportDepth system property64 (documented: README.txt)operator-tunable per-process limitmaximum import/include resolution depth for one schema read
org.apache.ws.commons.schema.maxSchemaResolutions system property1000 (documented: README.txt)operator-tunable per-process limitmaximum schema documents resolved during one top-level read
org.apache.ws.commons.schema.maxNestingDepth system property512 (documented: README.txt)operator-tunable per-process limitmaximum structural nesting depth while building the schema model, including nested include/import/redefine document resolutions
org.apache.ws.commons.schema.allowDTD system propertyfalse (documented: README.txt)compatibility toggle for operator-controlled deploymentsallows DOCTYPE declarations in schema documents; external DTD and external entity resolution remain disabled
DocumentBuilderFactory providerJDK default (typically Xerces fork) (inferred — §14 Q6)depends on the JDKshape of XML parsing for read(InputSource) / stream-shaped read(Source) paths

The insecure-default case

The bundled DefaultURIResolver does follow remote URLs by default. The maintainer ruling captured in §14 Q12 will determine whether “a schema with <xs:import schemaLocation='http://attacker/'/> fetched the URL during parse” is a VALID report (production deployments should be protected by the default) or an OUT-OF-MODEL: non-default-build report (production deployments are documented as required to install a restricting resolver per §10).

XMLSchema's internal schema parser rejects DOCTYPE declarations by default and disables external DTD and external entity resolution. This applies both to top-level read(InputSource | Reader | Source) non-DOMSource paths parses and to recursive import/include/redefine reparses. Operators may set org.apache.ws.commons.schema.allowDTD=true to accept DOCTYPE-bearing schemas for compatibility; external DTD and external entity resolution remain disabled in that mode.

§6 Assumptions about inputs

Per-entry-point trust table

Entry pointParameterAttacker-controllable?Caller must enforce
XmlSchemaCollection.read(InputSource is)is bytesyesXMLSchema rejects DOCTYPE by default and disables external DTD/entity resolution; caller may need to install a restricting URIResolver if the source contains untrusted xs:include/xs:import
XmlSchemaCollection.read(Reader r)r charactersyessame as above
XmlSchemaCollection.read(Source src)srcyesSAXSource/StreamSource/other route through the internal hardened factory (same as read(InputSource)); a DOMSource routes to the pre-parsed read(Document)/read(Element) path, so the upstream parser's XXE/DTD posture applies
XmlSchemaCollection.read(Document doc)docyes if doc was parsed from untrusted bytescaller's DocumentBuilderFactory is responsible for XXE / DTD posture; XMLSchema does not re-parse
XmlSchemaCollection.read(Element el)elsame as read(Document)same as above
XmlSchemaCollection.setSchemaResolver(URIResolver)resolvercaller-suppliedreplacing the default is the documented path for production hardening (inferred — §14 Q12)
XmlSchemaCollection.setBaseUri(String)baseUricaller-supplied trusted stringnot validated; if attacker can set this they can pivot the import-resolver origin
XmlSchemaCollection.setExtReg(ExtensionRegistry)registrycaller-suppliedcaller's choice
XmlSchema.write(OutputStream) / XmlSchema.write(Writer)output sinkcaller-suppliedcaller's choice; FEATURE_SECURE_PROCESSING=true is set on the internal TransformerFactory, with external DTD/stylesheet access disabled where supported
XmlSchemaWalker.walk(XmlSchemaElement)walked schemaas untrusted as the schemanone — pure in-memory walking
XmlSchemaPathFinderSAX events + schema modelas untrusted as bothconfigure backtracking limits for the deployment; defaults bound decision points and replayed events per document
XmlSchemaElementValidator (walker module)SAX events + schema modelas untrusted as bothcaller validates / sanitizes outside
DomBuilderFromSaxSAX eventsas untrusted as the source of the eventsFEATURE_SECURE_PROCESSING=true is set (documented: DomBuilderFromSax.java line 81)
System property org.apache.ws.commons.schema.extension_registryclass nametrusted by §3 item 7operator must lock down property setting in shared-JVM deployments

Size / shape / rate

  • No documented limit on schema-document size (inferred — §14 Q8).
  • Import/include resolution has a default maximum depth of 64 and a default maximum of 1000 resolved schema documents per top-level read; both limits are configurable with JVM system properties (documented: README.txt).
  • Schema-model construction has a default maximum structural nesting depth of 512, including nested include/import/redefine document resolutions; the limit is configurable with a JVM system property (documented: README.txt).
  • Walker expansion cycles are rejected for type derivation, substitution groups, model groups, and attribute groups. This prevents recursive stack exhaustion for malformed but parseable schemas; it is not a general limit on the size or cost of an acyclic schema.
  • No rate limit on URL fetches when following xs:import (inferred — §14 Q12).
  • XmlSchemaPathFinder bounds decision points and replayed events per document by default; these limits are configurable through the org.apache.ws.commons.schema.walker.maxDecisionPoints and org.apache.ws.commons.schema.walker.maxReplayedEvents system properties (documented: XmlSchemaPathFinder.java).

§7 Adversary model

Actors

ActorIn scope?Capabilities
Producer of the input schema bytesyesfull byte control of the schema; can include <xs:import schemaLocation="…"/> pointing anywhere
Producer of an imported schema at a URL the parent schema referencesyesreturns a malicious downstream .xsd after the parent triggers the fetch
Network attacker on the path between XMLSchema and an HTTP schemaLocationpartial (inferred — §14 Q13) — TLS is the JDK URL handler's concern; XMLSchema does no certificate pinning; if the operator allowed plain http:// fetches a network attacker can substitute
In-process callers (the embedding application)out of scopetrivially full control
Owner of the host filesystemout of scopeby construction
Author of a hostile URIResolver / ExtensionRegistryout of scope (§3 item 7)
Author of system-property setting on JVM startupout of scope if operator-controlled; in scope only when an untrusted actor can set org.apache.ws.commons.schema.extension_registry (inferred — §14 Q9)
Co-tenant on the same JVM (multi-app servlet container)out of scope (inferred — §14 Q14)
Side-channel observerout of scope (inferred — §14 Q14)
Quantum adversaryout of scope

§8 Security properties the project provides

P1 — Memory-safety on the schema parse, given a JDK conformant to §5

  • Condition: bytes arrive through one of the read(...) paths; the JDK platform supplies a working DocumentBuilder; XMLSchema sets FEATURE_SECURE_PROCESSING=true on its factories.
  • Violation symptom: a crafted .xsd causes XMLSchema's own code (not the JDK XML parser) to throw an unhandled exception that is not a XmlSchemaException / ParserConfigurationException / IOException / SAXException — i.e. crashes outside the documented failure mode. Memory corruption is JVM-level and not a Java-side defect.
  • Severity: typically correctness-only (Java does not have memory corruption); VALID-HARDENING if the symptom is an unhandled RuntimeException that the caller cannot catch through the documented surface (inferred — §14 Q15).
  • (inferred — §14 Q15)

P2 — Internal parser DTD and external-entity hardening

  • Condition: XMLSchema's read(InputSource | Reader | Source) non-DOMSource paths take the internal DocumentBuilderFactory.
  • Property: DOCTYPE declarations are rejected by default. External general entities, external parameter entities, external DTD loading, and JAXP external-DTD access are disabled; a no-op EntityResolver is installed as a fallback. If org.apache.ws.commons.schema.allowDTD=true is set, DOCTYPE declarations may be accepted but external DTD/entity resolution remains disabled.
  • Violation symptom: attacker-controlled schema bytes cause the internal parser to fetch or expand external DTD/entity content, or a DOCTYPE is accepted while allowDTD is unset.
  • Severity: high for external file disclosure / SSRF through XXE; medium for parser-resource exhaustion when the embedding application accepts untrusted schemas.

P3 — Round-trip parse → model → serialize consistency

  • Condition: a well-formed schema is parsed and serialized; the serializer's TransformerFactory is configured with FEATURE_SECURE_PROCESSING=true.
  • Violation symptom: a serialized schema is not a valid XSD, or differs semantically from the parsed one (inferred — §14 Q16).
  • Severity: correctness-only; not security-relevant unless the divergence creates a security-meaningful misinterpretation downstream (inferred — §14 Q16).
  • (inferred — §14 Q16)

P4 — xmlschema-walker deterministic visit order

  • Condition: visitor pattern is invoked on the in-memory model.
  • Violation symptom: visit order varies across invocations on the same model, breaking caller assumptions.
  • Severity: correctness-only.
  • (inferred — §14 Q17)

P5 — Bounded recursive schema walking

  • Condition: an attacker-controlled schema is passed to XmlSchemaWalker.walk(XmlSchemaElement).
  • Property: cyclic type derivation, substitution-group, model-group, and attribute-group expansions terminate with XmlSchemaException rather than recursing indefinitely. Legal recursive content that passes through an element declaration remains walkable.
  • Violation symptom: a parseable schema causes the walker to recurse until StackOverflowError or another resource-exhaustion failure.
  • Severity: medium availability impact when the embedding application accepts untrusted schemas (inferred — §14 Q23).

P6 — Bounded schema-model structural descent

  • Condition: attacker-controlled schema bytes or DOM content are passed to XmlSchemaCollection.read(...).
  • Property: deeply nested schema structure, including depth split across nested include/import/redefine document resolutions, terminates with XmlSchemaException instead of exhausting the Java thread stack.
  • Violation symptom: a parseable schema causes SchemaBuilder to recurse until StackOverflowError or another resource-exhaustion failure.
  • Severity: medium availability impact when the embedding application accepts untrusted schemas.

§9 Security properties the project does not provide

State each plainly so a triager can route an inbound report to the matching disclaimer.

  • No SSRF defense on xs:import/xs:include schemaLocation URLs. The bundled DefaultURIResolver constructs a URL from the parent schema's base URI plus the schema-location value and returns an InputSource pointing at it. The JDK then fetches it on parse. XMLSchema applies no allowlist, no protocol restriction, and no host filtering of any kind. The caller is responsible for installing a restricting URIResolver if the input schema is attacker-controlled (documented: DefaultURIResolver.java).
  • No guarantee that DTD-bearing schemas are accepted by default. XMLSchema rejects DOCTYPE declarations on its internal parser unless org.apache.ws.commons.schema.allowDTD=true is set. The compatibility mode still disables external DTD and external entity resolution.
  • No defense when the caller passes in a pre-parsed Document or Element. The hardening on the internal DocumentBuilderFactory is moot — the caller's parser produced the DOM (documented: XmlSchemaCollection.read(Document) / .read(Element)).
  • No bound on schema-document size, imported bytes, or fetch rate. Import/include depth, total resolved documents per top-level read, and structural nesting depth are bounded, but a schema can still consume substantial resources within those limits (inferred — §14 Q8; resource limits documented in README.txt).
  • No protection of imported schemas at rest. Schemas pulled from HTTP are fetched in cleartext if the URL is http://. The caller must use TLS-protected URLs or install a restricting resolver (documented: DefaultURIResolver.java).
  • No defense against the system-property-controlled ExtensionRegistry being a malicious class. The named class is loaded into the running JVM and instantiated.
  • No data-at-rest protection. Schemas serialized by XmlSchemaSerializer are plain XML on whatever sink the caller provided.
  • No constant-time guarantees. XMLSchema does not deal with secrets.
  • No defense against side-channel observation.
  • No quantum resistance.

False-friend properties (call out separately)

  • org.apache.ws.commons.schema.allowDTD=true looks like it restores legacy XML parser behavior, but it does not restore external DTD or external entity fetching. The toggle accepts DOCTYPE declarations for compatibility only; external fetches remain disabled.
  • DefaultURIResolver looks like a sandbox, but it isn't. It is the bundled resolver; its job is to resolve xs:include/xs:import, not to filter destinations.
  • XmlSchemaCollection.setBaseUri(String) looks like a chroot for imports, but it isn't. If the importing schema sets an absolute URL in schemaLocation, the base URI is irrelevant — the absolute URL wins (inferred — §14 Q18).
  • xmlschema-walker.XmlSchemaElementValidator looks like a document validator, but it is a tooling helper. It is not a drop-in replacement for javax.xml.validation.Validator and does not promise XSD-1.0 / 1.1 conformance (inferred — §14 Q3).

Well-known attack classes XMLSchema does not single-handedly defend against

  • XXE / external-entity disclosure when the caller pre-parses a DOM with an unsafe XML parser before calling read(Document) / read(Element). XMLSchema's internal parser path rejects DOCTYPE by default and disables external DTD/entity resolution.
  • SSRF via xs:import schemaLocation — see §9 first bullet.
  • Billion-laughs / quadratic blowup — partially mitigated by FEATURE_SECURE_PROCESSING=true, but not universally.
  • Schema-amplification DoS — large or heavily-recursive acyclic schemas can exhaust memory or CPU within the documented resource limits; structural nesting and cyclic walker expansion are rejected as described in §8 P5 and §8 P6.
  • Confused-deputy fetch via untrusted baseUri + relative schemaLocation — the operator-supplied base URI is trusted.

§10 Downstream responsibilities

The embedding Java application must:

  1. Decide whether the schema bytes being parsed are attacker-controllable. If yes, install a restricting URIResolver via XmlSchemaCollection.setSchemaResolver(...) that refuses arbitrary http:// / https:// / file:// / jar: / ftp: URLs. The bundled DefaultURIResolver does not filter (documented: DefaultURIResolver.java).
  2. When passing a pre-parsed Document / Element into XmlSchemaCollection.read(...), use a DocumentBuilderFactory hardened against XXE — specifically with disallow-doctype-decl=true and external-entity processing disabled.
  3. Do not enable org.apache.ws.commons.schema.allowDTD=true for attacker-controlled schema bytes unless compatibility requires it and the deployment accepts internal DTD subset processing. External DTD and external entity resolution remain disabled by XMLSchema in that mode.
  4. Bound maximum schema size, imported bytes, and fetch rate at the caller level. XMLSchema provides configurable import/include depth per-read resolution, and structural nesting limits, but these do not replace deployment-specific resource budgets (inferred — §14 Q8).
  5. Set org.apache.ws.commons.schema.extension_registry only at JVM startup from a trusted source; do not allow untrusted actors to set it.
  6. Set XmlSchemaCollection.setBaseUri(...) from an operator-trusted string, not from anywhere an attacker can influence.
  7. Run on a release-supported branch (currently 2.3.0 line) (documented: RELEASE-NOTE.txt).

The embedding Java application should additionally implement these defense-in-depth controls:

  1. Enforce URL scheme and destination restrictions in the resolver: allow only https:// to approved hosts; deny file://, jar:, loopback, link-local, and RFC1918/private address ranges.
  2. Keep org.apache.ws.commons.schema.allowDTD unset unless a deployment has known DTD-bearing schema inputs and has tested the compatibility mode on its JDK XML provider.
  3. Supplement XMLSchema's import/include depth, per-read resolution, and structural nesting limits with caller-boundary budgets for total imported bytes and fetch rate per top-level parse.
  4. Use connect/read timeouts for import fetches and fail closed on timeout or policy-check errors.
  5. Log import-resolution decisions (requested URI, normalized target, allow/deny result, reason) for incident response and triage.
  6. Prefer integrity-controlled schema sources (pinned internal mirror or checksum-verified artifacts) instead of live internet fetches.

§11 Known misuse patterns

  • Passing an attacker-controlled .xsd to XmlSchemaCollection.read(InputSource) with the DefaultURIResolver in place. The schema's xs:include / xs:import are followed unrestricted, leading to SSRF / cross-origin fetch / file:// disclosure (documented: DefaultURIResolver.java). The fix is per §10 item 1.
  • Trusting read(Document) / read(Element) to inherit XXE defenses from XMLSchema. XMLSchema does not re-parse; the caller's factory chose the posture.
  • Setting org.apache.ws.commons.schema.extension_registry from a servlet-context init parameter or a config file an end user can influence. The named class is loaded and instantiated at XmlSchemaCollection construction.
  • Treating XmlSchemaElementValidator (walker module) as a conformant XSD validator. It is a tooling helper; conformant document validation against an XSD requires the JDK javax.xml.validation.Validator (inferred — §14 Q3).
  • Using the same XmlSchemaCollection instance across thread boundaries without external synchronization. XMLSchema does not document its threading model (inferred — §14 Q19).
  • Fetching imported schemas over plain http:// from a remote registry. The operator should restrict to https:// or pin to a trusted mirror.
  • Letting the parsed schema's base URI be derived from the attacker-controlled bytes (e.g. an absolute xmlns:tns URL the attacker provided) and then walking the URI graph from that base.

§11a Known non-findings (recurring false positives)

This section is the highest-leverage input for automated agentic security scans. Each entry: tool symptom, why it is safe under the model, the section that licenses the call.

  • new URL(baseUri, schemaLocation).openConnection() — SSRF risk in DefaultURIResolver.” Bundled behavior, explicitly documented as defaulted unrestricted; operator must install a restricting resolver per §10 item 1. → OUT-OF-MODEL: trusted-input (if the maintainer rules at Q12 that the default is dev/test), or VALID-HARDENING (if the maintainer rules the default is supported).
  • DocumentBuilderFactory.newInstance() allows XXE in XmlSchemaCollection.” Current XMLSchema internal parsing rejects DOCTYPE by default and disables external DTD/entity resolution. A report must show a bypass of those controls to be VALID.
  • Class.forName(System.getProperty(...)) is dynamic-class-loading.” Documented extension point; the system property is the trust gate (documented: XmlSchemaCollection.java line 361). → OUT-OF-MODEL: trusted-input.
  • AccessController.doPrivileged deprecated in JDK 17.” JDK compatibility wrapper; deprecation is informational on JDK 17 and required on pre-17 JDKs. → KNOWN-NON-FINDING.
  • “Hardcoded password in test resources.” No such resource exists in this repo; if a tool flags w3c-testcases/ data, it is W3C conformance suite data (documented: top-level w3c-testcases/). → OUT-OF-MODEL: unsupported-component.
  • XmlSchemaSerializer uses identity Transformer — could be exploited via XSLT injection.” Identity transform; no stylesheet reachable from input (documented: XmlSchema.java). → KNOWN-NON-FINDING.
  • URLConnection.getInputStream() without timeout.” True; XMLSchema does no read-timeout on fetched imports (inferred — §14 Q12). → VALID-HARDENING if Q12 rules the default-resolver is production-safe; otherwise documented as a §10 responsibility.
  • “Path traversal via XmlSchemaCollection.setBaseUri().” Caller- supplied trusted string per §6. → OUT-OF-MODEL: trusted-input.
  • “Schemas in w3c-testcases/ contain wide-open DTDs.” W3C conformance suite, used as input to unit tests (documented: top-level w3c-testcases/). → OUT-OF-MODEL: unsupported-component.
  • ExtensionRegistry is Class.forName-loaded — RCE.” Trusted system property per §3 item 7. → OUT-OF-MODEL: trusted-input.
  • XmlSchemaCollection.read(InputSource) with a file:// system ID follows it to read arbitrary local files.” (No read(URL) or read(InputStream) overload exists; earlier revisions of this table listed both in error.) Caller passed the URL; trusted entry point. → OUT-OF-MODEL: trusted-input.

§12 Conditions that would change this model

Revise this document when any of the following lands:

  • A change in the default URIResolver behavior — e.g. adding host filtering, refusing non-HTTPS, or adding read/connect timeouts.
  • A change in the default parser DTD/XXE posture, including the org.apache.ws.commons.schema.allowDTD compatibility contract.
  • A new public entry point on XmlSchemaCollection that accepts new input shapes.
  • A new built-in resource limit, or a change to an existing resource limit.
  • A new feature flag in xmlschema-walker's validator that turns it into a claimed-conformant document validator.
  • An upgrade of the supported JDK minimum that changes the JDK XML provider behavior.
  • A change in the system-property contract for ExtensionRegistry.
  • A vulnerability report that cannot be cleanly routed to one of the §13 dispositions — evidence the model has a gap.

§13 Triage dispositions

A report against XMLSchema receives exactly one of the following:

DispositionMeaningLicensed by
VALIDViolates a §8 property via an in-scope §7 adversary using an in-scope §6 input.§8, §6, §7
VALID-HARDENINGNo §8 property violated, but a §11 misuse pattern can be made harder to fall into by code change. Typically no CVE.§11
OUT-OF-MODEL: trusted-inputRequires attacker control of a §6 parameter the model marks trusted (caller-supplied Document / Element, caller-supplied baseUri, caller-supplied URIResolver, JVM system property, etc.).§6
OUT-OF-MODEL: adversary-not-in-scopeRequires a §7 actor the model excludes (in-process caller, hostile URIResolver, operator).§7
OUT-OF-MODEL: unsupported-componentLands in w3c-testcases/, */src/test/, etc/, xmlschema-bundle-test/.§3 items 4, 8
OUT-OF-MODEL: non-default-buildOnly manifests under a §5a configuration the maintainer rules dev/test (e.g. an unsafe custom URIResolver).§5a
OUT-OF-MODEL: out-of-layerConcerns a document validation step delegated to javax.xml.validation.Validator, or a WSDL parser upstream.§3 items 1–3
BY-DESIGN: property-disclaimedConcerns a §9 property the project explicitly does not provide (no SSRF defense, no guarantee of default DTD acceptance, no schema-size, imported-byte, or fetch-rate ceiling).§9
KNOWN-NON-FINDINGMatches a §11a recurring false positive.§11a
MODEL-GAPCannot be cleanly routed to any of the above — triggers §12 model revision.§12

§14 Open questions for the maintainers

Every (inferred) tag in the body maps to one of these. Proposed answers are inline; please confirm, correct, or strike.

Wave 1 — security policy + meta

Q1. XMLSchema does not currently ship an in-repo SECURITY.md. The de facto policy is “report via https://www.apache.org/security/”. Should the project (a) adopt a SECURITY.md that names a supported- branch matrix (proposed), (b) leave reporting to the foundation page only, or (c) defer to the Webservices PMC's umbrella policy? (meta)

Q2. Confirm that XMLSchema's threat model treats the project as a schema-modeling library that performs network IO when resolving imports, not a generic XML parser (proposed: yes). (maps to §2)

Q3. xmlschema-walker.XmlSchemaElementValidator — proposed position is “tooling helper, not a claimed-conformant document validator”. Confirm? (maps to §3 item 1, §9 false-friend, §11)

Wave 2 — XXE / DTD posture (highest leverage)

Q4. When read(Document) / read(Element) is the entry point, proposed position is “the caller's DOM was already parsed; XMLSchema makes no XXE claim about it” (OUT-OF-MODEL: trusted-input). Confirm? (maps to §3 item 5, §13)

Q5. When the URI resolver follows an xs:import schemaLocation, proposed position is “what the remote host returns is parsed by the internal XMLSchema parser path; the fetch itself is the attacker-influenced action and §9 disclaims SSRF defense” (§9). Confirm? (maps to §3 item 6, §9)

Q6. DTD compatibility posture. XMLSchema now rejects DOCTYPE declarations by default on the internal schema parser, disables external DTD/entity resolution, and offers org.apache.ws.commons.schema.allowDTD=true to accept DTD-bearing schema documents while keeping external resolution disabled. Confirm that this is the supported posture for untrusted schema bytes. (maps to §5a, §8 P2, §9, §10, §11a)

Wave 3 — URI resolver / SSRF

Q7. Confirm that XMLSchema does not sanitize schemaLocation when it begins with file://, jar:, etc. (proposed: no sanitization; operator's URIResolver is the gate). (maps to §5, §11a)

Q8. XMLSchema has no documented bound on schema-document size, imported bytes, or fetch rate. Import/include resolution does have configurable defaults of 64 levels and 1000 resolved schema documents per top-level read. The caller remains responsible for additional deployment- specific resource budgets. (maps to §5, §9, §10 item 4)

Q9. org.apache.ws.commons.schema.extension_registry system property: confirm that production deployments are expected to set it (if at all) at JVM startup from a trusted source — i.e. an untrusted-actor-set value is OUT-OF-MODEL: trusted-input (proposed). (maps to §5a, §11)

Q10. Negative-side inventory in §5: XMLSchema opens no sockets other than what the JDK URL handler does when following an import; spawns no processes; installs no signal handlers; reads only the documented system property; writes nothing of its own initiative. Confirm? (maps to §5)

Q11. Build-time variants: confirm there are no compile-time feature toggles; the security envelope is shaped only by runtime extension points (proposed). (maps to §5a)

Q12. The big URI-resolver question. The bundled DefaultURIResolver follows http:// / https:// / file:// / jar: URLs without filtering. Is this:

  • (a) “Supported production posture” — a report that an attacker schema's <xs:import schemaLocation='http://attacker/'/> triggered a fetch is VALID?
  • (b) “Dev/test default; operators are documented as required to install a restricting resolver per §10” — same report is OUT-OF-MODEL: non-default-build?

Proposed: (b) with a clarification in README.txt and/or SECURITY.md that production deployments handling untrusted schema bytes must install a restricting URIResolver. (maps to §5a, §9, §10 item 1, §11a, §13)

Wave 4 — adversary model, edge cases

Q13. Network attacker on http:// import fetches: proposed position is “operator is documented as required to use https:// or a restricting resolver; TLS validity is the JDK URL handler's concern”. Confirm? (maps to §7)

Q14. Co-tenant in shared JVM and side-channel observers: out of scope (proposed)? (maps to §7)

Q15. §8 P1 (memory safety on parse): proposed wording “any RuntimeException outside the documented XmlSchemaException/ ParserConfigurationException/IOException/SAXException family is VALID-HARDENING”. Confirm? (maps to §8 P1)

Q16. §8 P3 (round-trip parse → model → serialize consistency): do you claim this as a security property, or only as a correctness one? Proposed: correctness-only unless the divergence creates a security-meaningful downstream misinterpretation, in which case it is a VALID-HARDENING. (maps to §8 P3)

Q17. §8 P4 (walker deterministic visit order): is the visit order documented? Proposed: correctness-only. (maps to §8 P4)

Q18. setBaseUri(...) semantics: if an <xs:import schemaLocation='http://absolute/'/> is encountered, the base URI is ignored. Confirm? (maps to §9 false-friend)

Q19. Threading model: is XmlSchemaCollection documented as thread-safe? Proposed: not thread-safe; callers synchronize. (maps to §11)

Wave 5 — coexistence & publication

Q20. This document should be hosted in-repo at docs/security/threat-model.md (proposed) or on ws.apache.org/xmlschema/? (meta)

Q21. §11a known-non-findings is thin (~11 patterns). Could the XMLSchema PMC populate from the JIRA “not a bug” / “wontfix” closures (XMLSCHEMA-* tickets)? Concrete asks: 3–5 patterns the PMC sees recur in inbound reports. (meta — §11a)

Q22. What kind of change to XMLSchema should trigger a revision (proposed list in §12 — confirm or correct)? (meta — §12)

Q23. xmlschema-walker cycle handling: should rejection of cyclic type derivation, substitution-group, model-group, and attribute-group expansions be treated as a claimed medium-severity availability property for attacker-controlled schemas? Proposed: yes; malformed but parseable cycles must terminate with XmlSchemaException, while legal recursive content through element declarations remains supported. (maps to §4, §6, §8 P5)


Appendix: SECURITY.md / website → §x back-map

XMLSchema ships a SECURITY.md that points vulnerability reporters to the Apache Software Foundation security process. The threat-model sources are the in-repo README.txt, the RELEASE-NOTE.txt, SECURITY.md, and the JavaDoc / source comments. The project website is https://ws.apache.org/xmlschema/.

SourceClaimLands in
SECURITY.mdvulnerability reports go through the Apache Software Foundation security process and this threat model documents scope / triage§1
README.txt“lightweight schema object model that can be used to manipulate and generate XML schema representations”§1, §2 intended use
RELEASE-NOTE.txt (2.3.0)Java 17 minimum, Java 7 dropped§5 environment
xmlschema-core/src/main/java/org/apache/ws/commons/schema/XmlSchemaCollection.java line 361org.apache.ws.commons.schema.extension_registry system property loaded via Class.forName§5a, §6, §11
xmlschema-core/src/main/java/org/apache/ws/commons/schema/SchemaBuilder.javaorg.apache.ws.commons.schema.maxNestingDepth structural descent limit§5, §5a, §6, §8 P6
XmlSchemaCollection.javainternal parser sets FEATURE_SECURE_PROCESSING, rejects DOCTYPE by default, disables external DTD/entity resolution, and honors org.apache.ws.commons.schema.allowDTD for compatibility§5a, §8 P2
XmlSchemaCollection.java line 745AccessController.doPrivileged wrapper for the SAX parse§5
XmlSchema.javaserializer TransformerFactory sets FEATURE_SECURE_PROCESSING and disables external DTD/stylesheet access where supported§5a, §8 P2
xmlschema-core/src/main/java/.../resolver/DefaultURIResolver.javaURL composed from baseUri + schemaLocation; no filtering§3 item 7, §9 SSRF disclaim, §10 item 1, §11 first bullet
xmlschema-core/src/main/java/.../resolver/URIResolver.javaResolver interface — caller-pluggable§2 caller-roles, §10 item 1
xmlschema-walker/src/main/java/.../docpath/DomBuilderFromSax.java line 81factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, TRUE)§5a, §8 P2
xmlschema-walker/src/main/java/.../docpath/XmlSchemaPathFinder.javaConfigurable per-document limits on decision points and replayed events§4, §5a, §6, §12
xmlschema-walker/src/main/java/.../walker/XmlSchemaWalker.java and XmlSchemaScope.javaActive-path cycle detection for schema expansion§4, §6, §8 P5