Skip to content

[4.1.x] MYFACES-4761: Facelet path validation - #1043

Merged
volosied merged 6 commits into
apache:4.1.xfrom
volosied:facelet-path-validation
Aug 17, 2026
Merged

[4.1.x] MYFACES-4761: Facelet path validation#1043
volosied merged 6 commits into
apache:4.1.xfrom
volosied:facelet-path-validation

Conversation

@volosied

Copy link
Copy Markdown
Contributor

No description provided.

@volosied volosied changed the title Facelet path validation [4.1.x] Facelet path validation Aug 13, 2026
// Path-validation helpers

private static final Set<String> BLOCKED_SCHEMES = new HashSet<>(
Arrays.asList("http", "https", "ftp", "ftps", "mailto", "tel",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be better to have an allowed scheme(s) rather than blocked?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed!

@tandraschko

Copy link
Copy Markdown
Member

Please provide some unittests

Strengthen resolveURL() with four layered guards to prevent unsafe
Facelet resource resolution:

1. Scheme check — rejects remote/network URI schemes (http, https, ftp,
   etc.) using a fast colon-index scan; OSGi/container schemes (jar,
   wsjar, file, zip) are intentionally allowed.

2. Traversal guard — for relative paths, verifies the resolved URL
   remains within the application base (WAR/EAR root) to prevent
   directory traversal attacks.

3. WEB-INF XML guard (scaffolded, currently disabled) — isWebInfConfigFile()
   is in place to block XML config descriptors under WEB-INF/ if .xml is
   ever added as a Facelet suffix.

4. Extension/suffix check — rejects paths whose extension is not in the
   configured Facelet suffix set (jakarta.faces.FACELETS_SUFFIX /
   jakarta.faces.FACELETS_VIEW_MAPPINGS), cached after the first call.

Also adds FINE-level logging at each rejection point and a log of the
computed allowed-suffix set on first initialisation.

UnitTest project stage bypasses guards 2-4 to allow tests that use
synthetic paths not backed by a real WAR layout.
Add InvalidFileException (extends IOException) with a typed Reason enum
to replace the generic MalformedURLException throws in resolveURL().

Reason values:
  DISALLOWED_SCHEME  — blocked remote/network URI scheme
  PATH_TRAVERSAL     — resolved URL escapes the application base
  INVALID_EXTENSION  — extension not a configured Facelet suffix

Callers can now catch InvalidFileException and inspect getReason() to
programmatically distinguish between rejection causes without parsing
exception messages.
@volosied
volosied force-pushed the facelet-path-validation branch from b7f90a2 to db5f058 Compare August 17, 2026 18:58
@volosied
volosied merged commit f3f62dc into apache:4.1.x Aug 17, 2026
@volosied volosied changed the title [4.1.x] Facelet path validation [4.1.x] MYFACES-4761: Facelet path validation Aug 18, 2026
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.

4 participants