Skip to content

Reject remote file: authorities in the schema-download gate - #103

Merged
pjfanning merged 1 commit into
apache:trunkfrom
pjfanning:fix-file-uri-ssrf-gate
Aug 31, 2026
Merged

Reject remote file: authorities in the schema-download gate#103
pjfanning merged 1 commit into
apache:trunkfrom
pjfanning:fix-file-uri-ssrf-gate

Conversation

@pjfanning

Copy link
Copy Markdown
Member

Problem

StscState.shouldDownloadURI gates resolution of <xsd:import> / <xsd:include> / <xsd:redefine> schemaLocations. With network downloads disabled (the default), remote http(s):// locations are correctly refused — but any file: URI was accepted regardless of the gate and without inspecting the authority:

return equalsIgnoreCase(uri.getScheme(), "file");   // host never checked

An accepted URL reaches StscImporter.downloadDocumentnew URL(absoluteURL)loader.parse(url, …) and is opened. So when an application compiles an untrusted XSD with default options, a Windows UNC location like file://attacker.example.com/share/evil.xsd in an import passes the gate and triggers an outbound SMB connection to the attacker's host (SSRF with attacker-controlled host and protocol, capable of leaking NTLM credentials) — even though the operator has network downloads disabled. A file:///etc/... location similarly reaches the local filesystem.

Fix

Accept a file: URI only when it has no remote authority (null, empty, or localhost). Legitimate local-file includes carry no authority and keep working; a UNC / remote-host file: URI is now refused like any other blocked download. The jar:/zip: recursion just above funnels back through this same check for its embedded URI, so it is covered too.

This does not change the behavior when a caller has opted into downloads (via setCompileDownloadUrls, an EntityResolver, or -Dxmlbean.downloadurls=true), where _doingDownloads short-circuits to true before this check.

Testing

  • ./gradlew compileJava clean
  • ./gradlew test --tests compile.scomp.checkin.CompilationTests --tests compile.scomp.som.checkin.PartialSOMCheckinTest passes (exercise schema import/include resolution)

🤖 Generated with Claude Code

StscState.shouldDownloadURI gates schema import/include/redefine
resolution. Remote http(s) locations are refused when downloads are
disabled (the default), but any file: URI was accepted regardless of
the gate and without inspecting the authority. A Windows UNC location
such as file://attacker.example.com/share/evil.xsd in an untrusted
schema therefore passed the gate and was fetched by StscImporter
(new URL(absoluteURL) -> loader.parse), reaching an attacker-controlled
host over SMB - an SSRF with attacker-controlled host and protocol -
even though "network downloads disabled" was in effect.

Accept a file: URI only when it has no remote authority (null, empty,
or localhost). Local file includes, which have no authority, keep
working; a UNC/remote-host file: URI is now refused like any other
download.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@pjfanning
pjfanning merged commit 74c3149 into apache:trunk Aug 31, 2026
3 checks passed
@pjfanning
pjfanning deleted the fix-file-uri-ssrf-gate branch August 31, 2026 16:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant