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 9a0cbdbc Fixing one more DefaultURIResolver case
9a0cbdbc is described below
commit 9a0cbdbc58bc55c4e3949cbadb27ca6d0e229181
Author: Colm O hEigeartaigh <[email protected]>
AuthorDate: Wed Sep 16 11:38:44 2026 +0100
Fixing one more DefaultURIResolver case
---
THREAT-MODEL.md | 12 ++++++++----
.../ws/commons/schema/resolver/DefaultURIResolver.java | 14 ++++++++++++--
.../src/test/java/tests/DefaultURIResolverTest.java | 13 +++++++++++++
3 files changed, 33 insertions(+), 6 deletions(-)
diff --git a/THREAT-MODEL.md b/THREAT-MODEL.md
index dffe0103..24ac6f76 100644
--- a/THREAT-MODEL.md
+++ b/THREAT-MODEL.md
@@ -452,9 +452,10 @@ matching disclaimer.
`https`, `file` and `jar`, judged through any `jar:` wrapper — and
refuses a location that changes the scheme of a remote base. It also
refuses, for every location and whatever the base, a `file:` URL that
- names a non-local authority (a UNC path on Windows, so an SMB
- connection to a host the schema author chose) and a `jar:` URL whose
- archive would be fetched over the network. Within the `http` and
+ names a non-local host — in its authority, or as a path beginning
+ `//`, which is a UNC path on Windows and so an SMB connection to a
+ host the schema author chose — and a `jar:` URL whose archive would be
+ fetched over the network. Within the `http` and
`https` targets it does allow, it applies **no host or address
filtering of any kind**: any
`http(s)` host is fetched on request, including loopback, link-local
@@ -702,7 +703,10 @@ Revise this document when any of the following lands:
`file://host/share/x.xsd` and `jar:http://host/a.jar!/x.xsd` resolved
from a local or absent base. §4 B3 and §9 are updated. This does not
change the Q12(b) posture: absolute `http(s)` and local `file:`
- locations are still followed.
+ locations are still followed. A follow-up closed a gap in the `file:`
+ rule as first written: it tested only the URI authority, so
+ `file:////host/share/x.xsd`, which parses with no authority and
+ carries the host in its path instead, was not caught.
- **2026-09-16** — "Fix up DTD handling" (#147) changed the default
parser DTD posture, a revision trigger under the second bullet above:
external DTD and external entity resolution are now disabled
diff --git
a/xmlschema-core/src/main/java/org/apache/ws/commons/schema/resolver/DefaultURIResolver.java
b/xmlschema-core/src/main/java/org/apache/ws/commons/schema/resolver/DefaultURIResolver.java
index 1f7a45f8..347b2653 100644
---
a/xmlschema-core/src/main/java/org/apache/ws/commons/schema/resolver/DefaultURIResolver.java
+++
b/xmlschema-core/src/main/java/org/apache/ws/commons/schema/resolver/DefaultURIResolver.java
@@ -241,9 +241,19 @@ public class DefaultURIResolver implements
CollectionURIResolver {
private static boolean isLocalFileUri(String uri) {
try {
URI parsed = new URI(uri);
+ if (!"file".equalsIgnoreCase(parsed.getScheme())) {
+ return false;
+ }
final String authority = parsed.getAuthority();
- return "file".equalsIgnoreCase(parsed.getScheme())
- && (authority == null || authority.length() == 0 ||
"localhost".equalsIgnoreCase(authority));
+ if (authority != null && authority.length() > 0
+ && !"localhost".equalsIgnoreCase(authority)) {
+ return false;
+ }
+ // A host can also arrive in the path rather than the authority:
"file:////host/share"
+ // parses with no authority at all, and a path beginning "//" is a
UNC path on Windows.
+ // No schema names a local file that way, so refuse the shape
outright.
+ final String path = parsed.getPath();
+ return path == null || !path.startsWith("//");
} catch (URISyntaxException e) {
return false;
}
diff --git a/xmlschema-core/src/test/java/tests/DefaultURIResolverTest.java
b/xmlschema-core/src/test/java/tests/DefaultURIResolverTest.java
index 6cadfa04..0144066e 100644
--- a/xmlschema-core/src/test/java/tests/DefaultURIResolverTest.java
+++ b/xmlschema-core/src/test/java/tests/DefaultURIResolverTest.java
@@ -234,4 +234,17 @@ public class DefaultURIResolverTest extends Assert {
assertEquals("jar:file:///tmp/a.jar!/has space.xsd",
result.getSystemId());
}
+
+ @Test
+ public void testFileUrlCarryingItsHostInThePathIsRefused() {
+ // "file:////host/share/x.xsd" parses with a null authority and the
host in the path, so an
+ // authority-only check lets it through. On Windows that path is a UNC
path.
+ assertSchemeRefused("file:////attacker.example/share/x.xsd", null,
"non-local authority");
+ assertSchemeRefused("file:////attacker.example/share/x.xsd",
localBase(), "non-local authority");
+ assertSchemeRefused("file://///attacker.example/share/x.xsd", null,
"non-local authority");
+
assertSchemeRefused("jar:file:////attacker.example/share/a.jar!/x.xsd", null,
+ "non-local authority");
+ // The same shape reached by composing a relative location against a
local base.
+ assertSchemeRefused("////attacker.example/share/x.xsd", localBase(),
"non-local authority");
+ }
}