This is an automated email from the ASF dual-hosted git repository.
coheigea pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ws-xmlschema.git
The following commit(s) were added to refs/heads/master by this push:
new c5d8f567 Documenting threat-safety concerns
c5d8f567 is described below
commit c5d8f5672f9bfedddd5db780c2573a5275c2bd4e
Author: Colm O hEigeartaigh <[email protected]>
AuthorDate: Thu Sep 17 09:46:36 2026 +0100
Documenting threat-safety concerns
---
THREAT-MODEL.md | 27 ++++++++++++++++------
.../ws/commons/schema/XmlSchemaCollection.java | 6 +++++
2 files changed, 26 insertions(+), 7 deletions(-)
diff --git a/THREAT-MODEL.md b/THREAT-MODEL.md
index a55da09b..9bf45b3f 100644
--- a/THREAT-MODEL.md
+++ b/THREAT-MODEL.md
@@ -217,6 +217,17 @@ A finding is in-model only if it reaches a row marked
**yes**.
- **Filesystem**: caller-supplied paths; XMLSchema does no path
sanitization of `schemaLocation` values that begin with `file://`
*(inferred — §14 Q7)*.
+- **Threading**: a single `XmlSchemaCollection` is assumed to be used by
+ one thread at a time. The in-progress import stack, the schema and
+ unresolved-type maps and the per-read limit counters are plain mutable
+ instance state with no synchronization, so concurrent `read` calls on
+ one collection corrupt each other — measured on 8 threads sharing a
+ collection: `NoSuchElementException` from an emptied import stack,
+ `ConcurrentModificationException` from the schema map, and per-read
+ budgets charged across unrelated reads. This is long-standing: the same
+ two corruption signatures reproduce on the pre-hardening baseline. A
+ collection per thread is the supported pattern *(documented:
+ `XmlSchemaCollection.java` class javadoc)*.
- **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
@@ -557,12 +568,14 @@ The embedding Java application **must**:
*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
+5. Give each thread its own `XmlSchemaCollection`; a collection is not
+ safe for concurrent `read` calls.
+6. 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
+7. 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)
+8. Run on a release-supported branch (currently 2.3.0 line)
*(documented: `RELEASE-NOTE.txt`)*.
The embedding Java application **should** additionally implement these
@@ -571,16 +584,16 @@ 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.
-3. Supplement XMLSchema's import/include depth, per-read resolution, and
+2. 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. Tune, or tighten beyond, the default per-fetch bounds of §5a, and
+3. Tune, or tighten beyond, the default per-fetch bounds of §5a, and
fail closed on timeout or policy-check errors. The defaults bound a
remote fetch; an aggregate budget across the whole import graph is
still a caller responsibility.
-5. Log import-resolution decisions (requested URI, normalized target,
+4. 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
+5. Prefer integrity-controlled schema sources (pinned internal mirror
or checksum-verified artifacts) instead of live internet fetches.
## §11 Known misuse patterns
diff --git
a/xmlschema-core/src/main/java/org/apache/ws/commons/schema/XmlSchemaCollection.java
b/xmlschema-core/src/main/java/org/apache/ws/commons/schema/XmlSchemaCollection.java
index 0c3b0507..97df7772 100644
---
a/xmlschema-core/src/main/java/org/apache/ws/commons/schema/XmlSchemaCollection.java
+++
b/xmlschema-core/src/main/java/org/apache/ws/commons/schema/XmlSchemaCollection.java
@@ -82,6 +82,12 @@ import
org.apache.ws.commons.schema.utils.TargetNamespaceValidator;
* <code>THREAT-MODEL.md</code> section 10 in the project sources for the full
set of caller
* responsibilities.
* </p>
+ * <p>
+ * <strong>A collection is not safe for concurrent use.</strong> The
in-progress import stack,
+ * the schema and unresolved-type maps and the per-read limit counters are all
plain mutable
+ * state, so two threads calling a <code>read</code> method on one collection
corrupt each
+ * other. Give each thread its own collection.
+ * </p>
*/
public final class XmlSchemaCollection {