This is an automated email from the ASF dual-hosted git repository. asf-gitbox-commits pushed a commit to branch 5.9.x-javax in repository https://gitbox.apache.org/repos/asf/tapestry-5.git
commit 4eb672944353cd9110dbd8f9c5c5f7211a2c7ee8 Author: Ben Weidig <[email protected]> AuthorDate: Wed Oct 7 08:16:26 2026 +0200 Improving classpath asset handling --- .../assets/ClasspathAssetRequestHandler.java | 36 ++++++++++++++++------ 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/assets/ClasspathAssetRequestHandler.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/assets/ClasspathAssetRequestHandler.java index 1391bcee0..c93d4e5d1 100644 --- a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/assets/ClasspathAssetRequestHandler.java +++ b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/assets/ClasspathAssetRequestHandler.java @@ -59,24 +59,42 @@ public class ClasspathAssetRequestHandler implements AssetRequestHandler public boolean handleAssetRequest(Request request, Response response, String extraPath) throws IOException { ChecksumPath path = new ChecksumPath(streamer, baseFolder, extraPath); - + + // Resolve the resource first, then check the protection rule against the + // fully-normalized path that will actually be loaded and streamed (Resource#getPath()). + final Resource resource; + + try + { + resource = assetSource.resourceForPath(path.resourcePath); + } + catch (IllegalStateException ex) + { + // The path normalized to a location above the classpath root (e.g. a "../" escape). + // Fail closed: treat it as blocked rather than surfacing it as a server error. + if (LOGGER.isWarnEnabled()) + { + LOGGER.warn("Blocked request for classpath asset '" + path.resourcePath + + "': " + ex.getMessage()); + } + return false; + } + + final String resourcePath = resource.getPath(); + final boolean handled; - - final String resourcePath = path.resourcePath.replace("\\.", ""); - - if (classpathAssetProtectionRule.block(resourcePath) && !path.resourcePath.equals(ChecksumPath.NON_EXISTING_RESOURCE)) + + if (classpathAssetProtectionRule.block(resourcePath) && !path.resourcePath.equals(ChecksumPath.NON_EXISTING_RESOURCE)) { - if (LOGGER.isWarnEnabled()) + if (LOGGER.isWarnEnabled()) { - LOGGER.warn("Blocked request for classpath asset '" + path.resourcePath + + LOGGER.warn("Blocked request for classpath asset '" + resourcePath + "'. Contribute a new ClasspathAssetProtectionRule if you need this asset to be publicly accessible."); } handled = false; } else { - Resource resource = assetSource.resourceForPath(path.resourcePath); - handled = path.stream(resource); } return handled;
