| <!-- |
| Licensed to the Apache Software Foundation (ASF) under one |
| or more contributor license agreements. See the NOTICE file |
| distributed with this work for additional information |
| regarding copyright ownership. The ASF licenses this file |
| to you under the Apache License, Version 2.0 (the |
| "License"); you may not use this file except in compliance |
| with the License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, |
| software distributed under the License is distributed on an |
| "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| KIND, either express or implied. See the License for the |
| specific language governing permissions and limitations |
| under the License. |
| --> |
| |
| # 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 |
| |
| | Role | Trust level | Notes | |
| | --- | --- | --- | |
| | **Embedding Java application** | trusted | Calls `XmlSchemaCollection.read(...)`, decides whether the input stream came from disk, classpath, or wire; decides which `URIResolver` to plug in. | |
| | **`URIResolver` implementation** | trusted | Either 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` implementation** | trusted | Pluggable 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 table | The *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 elsewhere | Following an `xs:import` is a **second, possibly cross-origin, fetch**. This is the principal SSRF surface. | |
| | **JDK XML platform** (`DocumentBuilderFactory`, `TransformerFactory`, `SchemaFactory`) | trusted upstream | XMLSchema 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 |
| |
| | Family | Representative entry point | Touches outside the process? | In-model? | |
| | --- | --- | --- | --- | |
| | `xmlschema-core` object model — `XmlSchema*` types, `XmlSchemaCollection`, `SchemaBuilder` | `XmlSchemaCollection.read(InputSource, ...)` and overloads | **no** for in-memory model; **yes** when the URI resolver follows `xs:import`/`xs:include` | **yes** | |
| | `xmlschema-core` URI resolver — `DefaultURIResolver`, `CollectionURIResolver`, `URIResolver` | `XmlSchemaCollection.setSchemaResolver()` | **yes** — by design, fetches imported schemas | **yes** | |
| | `xmlschema-core` serializer — `XmlSchemaSerializer` | `XmlSchema.write(OutputStream)` | **no** | **yes** | |
| | `xmlschema-core` resource loader (internal) — hardened `DocumentBuilderFactory` and `TransformerFactory` instances | invoked by `XmlSchemaCollection.read(InputSource, ...)`, recursive schema reparses, and `XmlSchema.write(...)` | **no** except where the URI resolver fetches imported schemas before parsing | **yes** | |
| | `xmlschema-walker` visitor — `XmlSchemaWalker`, `XmlSchemaVisitor`, `XmlSchemaScope` | walked by a caller-supplied `XmlSchemaVisitor` | **no** | **yes** | |
| | `xmlschema-walker` element validator — `XmlSchemaElementValidator` | walked at SAX-event time; consults the schema model | **no** (operates on caller-supplied SAX events) | **yes** | |
| | `xmlschema-walker` document path finder — `XmlSchemaPathFinder` | walked at SAX-event time; matches events against the schema model | **no** (operates on caller-supplied SAX events) | **yes** | |
| | `xmlschema-walker` DOM-from-SAX helper — `DomBuilderFromSax` | builds a DOM out of SAX events for validator inspection | **no** | **yes** | |
| | `xmlschema-bundle-test` | OSGi packaging regression test | n/a | **out of model** *(§3)* | |
| | `w3c-testcases/` | W3C schema test data | n/a | **out 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 |
| |
| | # | Transition | Authentication | Authorization | |
| | --- | --- | --- | --- | |
| | B1 | Caller → `XmlSchemaCollection.read(InputSource | Reader | Source | Document | Element)` | none — caller is trusted | none | |
| | B2 | `XmlSchemaCollection.read(InputSource, ...)` → hardened JDK `DocumentBuilder` | none | DOCTYPE rejected by default; external DTD/entity resolution disabled | |
| | B3 | Schema parser → `URIResolver.resolveEntity(namespace, schemaLocation, baseUri)` | none | bundled `DefaultURIResolver` does **no host filtering**: it constructs `new URL(new URL(baseUri), schemaLocation)` and hands back an `InputSource` pointing at it | |
| | B4 | Resolved `InputSource` → `XmlSchemaCollection.read(InputSource, ...)` (recursive) | none | none | |
| | B5 | `XmlSchema.write(...)` → JDK `TransformerFactory` (with `FEATURE_SECURE_PROCESSING=true` and external DTD/stylesheet access disabled where supported) | none | none | |
| | B6 | `XmlSchemaCollection` ctor → `System.getProperty("org.apache.ws.commons.schema.extension_registry")` → `Class.forName()` | none | trusts 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*: |
| |
| | Knob | Default | Maintainer stance | Effect | |
| | --- | --- | --- | --- | |
| | `org.apache.ws.commons.schema.extension_registry` system property | unset *(documented: `XmlSchemaCollection.java` line 361)* | dev-time customization; if set by an untrusted actor the named class is loaded into the JVM | extension-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-supplied | base URI against which relative `schemaLocation` values resolve | |
| | `org.apache.ws.commons.schema.walker.maxDecisionPoints` system property | `10000` *(documented: `XmlSchemaPathFinder.java`)* | operator-tunable per-process limit | maximum decision points created while matching one document | |
| | `org.apache.ws.commons.schema.walker.maxReplayedEvents` system property | `1000000` *(documented: `XmlSchemaPathFinder.java`)* | operator-tunable per-process limit | maximum previously traversed events replayed while backtracking through one document | |
| | `org.apache.ws.commons.schema.maxImportDepth` system property | `64` *(documented: `README.txt`)* | operator-tunable per-process limit | maximum import/include resolution depth for one schema read | |
| | `org.apache.ws.commons.schema.maxSchemaResolutions` system property | `1000` *(documented: `README.txt`)* | operator-tunable per-process limit | maximum schema documents resolved during one top-level read | |
| | `org.apache.ws.commons.schema.maxNestingDepth` system property | `512` *(documented: `README.txt`)* | operator-tunable per-process limit | maximum structural nesting depth while building the schema model, including nested include/import/redefine document resolutions | |
| | `org.apache.ws.commons.schema.allowDTD` system property | `false` *(documented: `README.txt`)* | compatibility toggle for operator-controlled deployments | allows DOCTYPE declarations in schema documents; external DTD and external entity resolution remain disabled | |
| | `DocumentBuilderFactory` provider | JDK default (typically Xerces fork) *(inferred — §14 Q6)* | depends on the JDK | shape 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 point | Parameter | Attacker-controllable? | Caller must enforce | |
| | --- | --- | --- | --- | |
| | `XmlSchemaCollection.read(InputSource is)` | `is` bytes | **yes** | XMLSchema 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` characters | **yes** | same as above | |
| | `XmlSchemaCollection.read(Source src)` | `src` | **yes** | `SAXSource`/`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)` | `doc` | **yes if doc was parsed from untrusted bytes** | caller's `DocumentBuilderFactory` is responsible for XXE / DTD posture; XMLSchema does not re-parse | |
| | `XmlSchemaCollection.read(Element el)` | `el` | same as `read(Document)` | same as above | |
| | `XmlSchemaCollection.setSchemaResolver(URIResolver)` | resolver | caller-supplied | replacing the default is the documented path for production hardening *(inferred — §14 Q12)* | |
| | `XmlSchemaCollection.setBaseUri(String)` | `baseUri` | **caller-supplied trusted string** | not validated; if attacker can set this they can pivot the import-resolver origin | |
| | `XmlSchemaCollection.setExtReg(ExtensionRegistry)` | registry | caller-supplied | caller's choice | |
| | `XmlSchema.write(OutputStream)` / `XmlSchema.write(Writer)` | output sink | caller-supplied | caller's choice; `FEATURE_SECURE_PROCESSING=true` is set on the internal `TransformerFactory`, with external DTD/stylesheet access disabled where supported | |
| | `XmlSchemaWalker.walk(XmlSchemaElement)` | walked schema | as untrusted as the schema | none — pure in-memory walking | |
| | `XmlSchemaPathFinder` | SAX events + schema model | as untrusted as both | configure backtracking limits for the deployment; defaults bound decision points and replayed events per document | |
| | `XmlSchemaElementValidator` (walker module) | SAX events + schema model | as untrusted as both | caller validates / sanitizes outside | |
| | `DomBuilderFromSax` | SAX events | as untrusted as the source of the events | `FEATURE_SECURE_PROCESSING=true` is set *(documented: `DomBuilderFromSax.java` line 81)* | |
| | System property `org.apache.ws.commons.schema.extension_registry` | class name | **trusted by §3 item 7** | operator 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 |
| |
| | Actor | In scope? | Capabilities | |
| | --- | --- | --- | |
| | **Producer of the input schema bytes** | **yes** | full byte control of the schema; can include `<xs:import schemaLocation="…"/>` pointing anywhere | |
| | **Producer of an imported schema** at a URL the parent schema references | **yes** | returns a malicious downstream `.xsd` after the parent triggers the fetch | |
| | **Network attacker on the path between XMLSchema and an HTTP `schemaLocation`** | **partial** *(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 scope** | trivially full control | |
| | **Owner of the host filesystem** | **out of scope** | by construction | |
| | **Author of a hostile `URIResolver` / `ExtensionRegistry`** | **out of scope** *(§3 item 7)* | |
| | **Author of system-property setting on JVM startup** | **out 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 observer** | **out of scope** *(inferred — §14 Q14)* | |
| | **Quantum adversary** | **out 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: |
| |
| | Disposition | Meaning | Licensed by | |
| | --- | --- | --- | |
| | `VALID` | Violates a §8 property via an in-scope §7 adversary using an in-scope §6 input. | §8, §6, §7 | |
| | `VALID-HARDENING` | No §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-input` | Requires 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-scope` | Requires a §7 actor the model excludes (in-process caller, hostile `URIResolver`, operator). | §7 | |
| | `OUT-OF-MODEL: unsupported-component` | Lands in `w3c-testcases/`, `*/src/test/`, `etc/`, `xmlschema-bundle-test/`. | §3 items 4, 8 | |
| | `OUT-OF-MODEL: non-default-build` | Only manifests under a §5a configuration the maintainer rules dev/test (e.g. an unsafe custom `URIResolver`). | §5a | |
| | `OUT-OF-MODEL: out-of-layer` | Concerns a *document* validation step delegated to `javax.xml.validation.Validator`, or a WSDL parser upstream. | §3 items 1–3 | |
| | `BY-DESIGN: property-disclaimed` | Concerns 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-FINDING` | Matches a §11a recurring false positive. | §11a | |
| | `MODEL-GAP` | Cannot 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/>. |
| |
| | Source | Claim | Lands in | |
| | --- | --- | --- | |
| | `SECURITY.md` | vulnerability 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 361 | `org.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.java` | `org.apache.ws.commons.schema.maxNestingDepth` structural descent limit | §5, §5a, §6, §8 P6 | |
| | `XmlSchemaCollection.java` | internal 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 745 | `AccessController.doPrivileged` wrapper for the SAX parse | §5 | |
| | `XmlSchema.java` | serializer `TransformerFactory` sets `FEATURE_SECURE_PROCESSING` and disables external DTD/stylesheet access where supported | §5a, §8 P2 | |
| | `xmlschema-core/src/main/java/.../resolver/DefaultURIResolver.java` | URL 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.java` | Resolver interface — caller-pluggable | §2 caller-roles, §10 item 1 | |
| | `xmlschema-walker/src/main/java/.../docpath/DomBuilderFromSax.java` line 81 | `factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, TRUE)` | §5a, §8 P2 | |
| | `xmlschema-walker/src/main/java/.../docpath/XmlSchemaPathFinder.java` | Configurable per-document limits on decision points and replayed events | §4, §5a, §6, §12 | |
| | `xmlschema-walker/src/main/java/.../walker/XmlSchemaWalker.java` and `XmlSchemaScope.java` | Active-path cycle detection for schema expansion | §4, §6, §8 P5 | |